summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/crypto.csproj30
-rw-r--r--crypto/src/crypto/tls/AbstractTlsContext.cs13
-rw-r--r--crypto/src/crypto/tls/ByteQueueStream.cs114
-rw-r--r--crypto/src/crypto/tls/RecordStream.cs25
-rw-r--r--crypto/src/crypto/tls/TlsClientProtocol.cs48
-rw-r--r--crypto/src/crypto/tls/TlsProtocol.cs182
-rw-r--r--crypto/src/crypto/tls/TlsServerProtocol.cs50
-rw-r--r--crypto/src/security/SecureRandom.cs13
-rw-r--r--crypto/test/src/cms/test/CMSTestUtil.cs37
-rw-r--r--crypto/test/src/cms/test/MiscDataStreamTest.cs15
-rw-r--r--crypto/test/src/cms/test/SignedDataStreamTest.cs548
-rw-r--r--crypto/test/src/cms/test/SignedDataTest.cs374
-rw-r--r--crypto/test/src/crypto/tls/test/ByteQueueStreamTest.cs134
-rw-r--r--crypto/test/src/crypto/tls/test/TlsProtocolNonBlockingTest.cs126
14 files changed, 1002 insertions, 707 deletions
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index 0df3859b4..df7df9f5a 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -3039,6 +3039,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\IBlockResult.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\IBufferedCipher.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -3104,11 +3109,21 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\IStreamCalculator.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\IStreamCipher.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\IVerifier.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\IWrapper.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -4454,6 +4469,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\tls\ByteQueueStream.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\tls\CertChainType.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -11600,6 +11620,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "test\src\crypto\tls\test\ByteQueueStreamTest.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "test\src\crypto\tls\test\DtlsProtocolTest.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -11690,6 +11715,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "test\src\crypto\tls\test\TlsProtocolNonBlockingTest.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "test\src\crypto\tls\test\TlsPskProtocolTest.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
diff --git a/crypto/src/crypto/tls/AbstractTlsContext.cs b/crypto/src/crypto/tls/AbstractTlsContext.cs
index e283ee58c..ae7efc64d 100644
--- a/crypto/src/crypto/tls/AbstractTlsContext.cs
+++ b/crypto/src/crypto/tls/AbstractTlsContext.cs
@@ -12,10 +12,21 @@ namespace Org.BouncyCastle.Crypto.Tls
     {
         private static long counter = Times.NanoTime();
 
+#if NETCF_1_0
+        private static object counterLock = new object();
+        private static long NextCounterValue()
+        {
+            lock (counterLock)
+            {
+                return ++counter;
+            }
+        }
+#else
         private static long NextCounterValue()
         {
             return Interlocked.Increment(ref counter);
         }
+#endif
 
         private readonly IRandomGenerator mNonceRandom;
         private readonly SecureRandom mSecureRandom;
@@ -26,7 +37,7 @@ namespace Org.BouncyCastle.Crypto.Tls
         private TlsSession mSession = null;
         private object mUserObject = null;
 
-       internal AbstractTlsContext(SecureRandom secureRandom, SecurityParameters securityParameters)
+        internal AbstractTlsContext(SecureRandom secureRandom, SecurityParameters securityParameters)
         {
             IDigest d = TlsUtilities.CreateHash(HashAlgorithm.sha256);
             byte[] seed = new byte[d.GetDigestSize()];
diff --git a/crypto/src/crypto/tls/ByteQueueStream.cs b/crypto/src/crypto/tls/ByteQueueStream.cs
new file mode 100644
index 000000000..bf603e006
--- /dev/null
+++ b/crypto/src/crypto/tls/ByteQueueStream.cs
@@ -0,0 +1,114 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class ByteQueueStream
+        : Stream
+    {
+        private readonly ByteQueue buffer;
+
+        public ByteQueueStream()
+        {
+            this.buffer = new ByteQueue();
+        }
+
+        public virtual int Available
+        {
+            get { return buffer.Available; }
+        }
+
+        public override bool CanRead
+        {
+            get { return true; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return false; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return true; }
+        }
+
+        public override void Close()
+        {
+        }
+
+        public override void Flush()
+        {
+        }
+
+        public override long Length
+        {
+            get { throw new NotSupportedException(); }
+        }
+
+        public virtual int Peek(byte[] buf)
+        {
+            int bytesToRead = System.Math.Min(buffer.Available, buf.Length);
+            buffer.Read(buf, 0, bytesToRead, 0);
+            return bytesToRead;
+        }
+
+        public override long Position
+        {
+            get { throw new NotSupportedException(); }
+            set { throw new NotSupportedException(); }
+        }
+
+        public virtual int Read(byte[] buf)
+        {
+            return Read(buf, 0, buf.Length);
+        }
+
+        public override int Read(byte[] buf, int off, int len)
+        {
+            int bytesToRead = System.Math.Min(buffer.Available, len);
+            buffer.RemoveData(buf, off, bytesToRead, 0);
+            return bytesToRead;
+        }
+
+        public override int ReadByte()
+        {
+            if (buffer.Available == 0)
+                return -1;
+
+            return buffer.RemoveData(1, 0)[0] & 0xFF;
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void SetLength(long value)
+        {
+            throw new NotSupportedException();
+        }
+
+        public virtual int Skip(int n)
+        {
+            int bytesToSkip = System.Math.Min(buffer.Available, n);
+            buffer.RemoveData(bytesToSkip);
+            return bytesToSkip;
+        }
+
+        public virtual void Write(byte[] buf)
+        {
+            buffer.AddData(buf, 0, buf.Length);
+        }
+
+        public override void Write(byte[] buf, int off, int len)
+        {
+            buffer.AddData(buf, off, len);
+        }
+
+        public override void WriteByte(byte b)
+        {
+            buffer.AddData(new byte[]{ b }, 0, 1);
+        }
+    }
+}
diff --git a/crypto/src/crypto/tls/RecordStream.cs b/crypto/src/crypto/tls/RecordStream.cs
index db5b158bc..6f3fc41c6 100644
--- a/crypto/src/crypto/tls/RecordStream.cs
+++ b/crypto/src/crypto/tls/RecordStream.cs
@@ -8,6 +8,11 @@ namespace Org.BouncyCastle.Crypto.Tls
     {
         private const int DEFAULT_PLAINTEXT_LIMIT = (1 << 14);
 
+        internal const int TLS_HEADER_SIZE = 5;
+        internal const int TLS_HEADER_TYPE_OFFSET = 0;
+        internal const int TLS_HEADER_VERSION_OFFSET = 1;
+        internal const int TLS_HEADER_LENGTH_OFFSET = 3;
+
         private TlsProtocol mHandler;
         private Stream mInput;
         private Stream mOutput;
@@ -116,11 +121,11 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         internal virtual bool ReadRecord()
         {
-            byte[] recordHeader = TlsUtilities.ReadAllOrNothing(5, mInput);
+            byte[] recordHeader = TlsUtilities.ReadAllOrNothing(TLS_HEADER_SIZE, mInput);
             if (recordHeader == null)
                 return false;
 
-            byte type = TlsUtilities.ReadUint8(recordHeader, 0);
+            byte type = TlsUtilities.ReadUint8(recordHeader, TLS_HEADER_TYPE_OFFSET);
 
             /*
              * RFC 5246 6. If a TLS implementation receives an unexpected record type, it MUST send an
@@ -130,13 +135,13 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             if (!mRestrictReadVersion)
             {
-                int version = TlsUtilities.ReadVersionRaw(recordHeader, 1);
+                int version = TlsUtilities.ReadVersionRaw(recordHeader, TLS_HEADER_VERSION_OFFSET);
                 if ((version & 0xffffff00) != 0x0300)
                     throw new TlsFatalAlert(AlertDescription.illegal_parameter);
             }
             else
             {
-                ProtocolVersion version = TlsUtilities.ReadVersion(recordHeader, 1);
+                ProtocolVersion version = TlsUtilities.ReadVersion(recordHeader, TLS_HEADER_VERSION_OFFSET);
                 if (mReadVersion == null)
                 {
                     mReadVersion = version;
@@ -147,7 +152,7 @@ namespace Org.BouncyCastle.Crypto.Tls
                 }
             }
 
-            int length = TlsUtilities.ReadUint16(recordHeader, 3);
+            int length = TlsUtilities.ReadUint16(recordHeader, TLS_HEADER_LENGTH_OFFSET);
             byte[] plaintext = DecodeAndVerify(type, mInput, length);
             mHandler.ProcessRecord(type, plaintext, 0, plaintext.Length);
             return true;
@@ -247,11 +252,11 @@ namespace Org.BouncyCastle.Crypto.Tls
              */
             CheckLength(ciphertext.Length, mCiphertextLimit, AlertDescription.internal_error);
 
-            byte[] record = new byte[ciphertext.Length + 5];
-            TlsUtilities.WriteUint8(type, record, 0);
-            TlsUtilities.WriteVersion(mWriteVersion, record, 1);
-            TlsUtilities.WriteUint16(ciphertext.Length, record, 3);
-            Array.Copy(ciphertext, 0, record, 5, ciphertext.Length);
+            byte[] record = new byte[ciphertext.Length + TLS_HEADER_SIZE];
+            TlsUtilities.WriteUint8(type, record, TLS_HEADER_TYPE_OFFSET);
+            TlsUtilities.WriteVersion(mWriteVersion, record, TLS_HEADER_VERSION_OFFSET);
+            TlsUtilities.WriteUint16(ciphertext.Length, record, TLS_HEADER_LENGTH_OFFSET);
+            Array.Copy(ciphertext, 0, record, TLS_HEADER_SIZE, ciphertext.Length);
             mOutput.Write(record, 0, record.Length);
             mOutput.Flush();
         }
diff --git a/crypto/src/crypto/tls/TlsClientProtocol.cs b/crypto/src/crypto/tls/TlsClientProtocol.cs
index 7b8439acc..14c1cf4a4 100644
--- a/crypto/src/crypto/tls/TlsClientProtocol.cs
+++ b/crypto/src/crypto/tls/TlsClientProtocol.cs
@@ -21,21 +21,56 @@ namespace Org.BouncyCastle.Crypto.Tls
         protected CertificateStatus mCertificateStatus = null;
         protected CertificateRequest mCertificateRequest = null;
 
+        /**
+         * Constructor for blocking mode.
+         * @param stream The bi-directional stream of data to/from the server
+         * @param secureRandom Random number generator for various cryptographic functions
+         */
         public TlsClientProtocol(Stream stream, SecureRandom secureRandom)
-            :   base(stream, secureRandom)
+            : base(stream, secureRandom)
         {
         }
 
+        /**
+         * Constructor for blocking mode.
+         * @param input The stream of data from the server
+         * @param output The stream of data to the server
+         * @param secureRandom Random number generator for various cryptographic functions
+         */
         public TlsClientProtocol(Stream input, Stream output, SecureRandom secureRandom)
-            :   base(input, output, secureRandom)
+            : base(input, output, secureRandom)
+        {
+        }
+
+        /**
+         * Constructor for non-blocking mode.<br>
+         * <br>
+         * When data is received, use {@link #offerInput(java.nio.ByteBuffer)} to
+         * provide the received ciphertext, then use
+         * {@link #readInput(byte[], int, int)} to read the corresponding cleartext.<br>
+         * <br>
+         * Similarly, when data needs to be sent, use
+         * {@link #offerOutput(byte[], int, int)} to provide the cleartext, then use
+         * {@link #readOutput(byte[], int, int)} to get the corresponding
+         * ciphertext.
+         * 
+         * @param secureRandom
+         *            Random number generator for various cryptographic functions
+         */
+        public TlsClientProtocol(SecureRandom secureRandom)
+            : base(secureRandom)
         {
         }
 
         /**
-         * Initiates a TLS handshake in the role of client
+         * Initiates a TLS handshake in the role of client.<br>
+         * <br>
+         * In blocking mode, this will not return until the handshake is complete.
+         * In non-blocking mode, use {@link TlsPeer#NotifyHandshakeComplete()} to
+         * receive a callback when the handshake is complete.
          *
          * @param tlsClient The {@link TlsClient} to use for the handshake.
-         * @throws IOException If handshake was not successful.
+         * @throws IOException If in blocking mode and handshake was not successful.
          */
         public virtual void Connect(TlsClient tlsClient)
         {
@@ -71,7 +106,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             SendClientHelloMessage();
             this.mConnectionState = CS_CLIENT_HELLO;
 
-            CompleteHandshake();
+            BlockForHandshake();
         }
 
         protected override void CleanupHandshake()
@@ -116,6 +151,7 @@ namespace Org.BouncyCastle.Crypto.Tls
                 this.mConnectionState = CS_CLIENT_FINISHED;
                 this.mConnectionState = CS_END;
 
+                CompleteHandshake();
                 return;
             }
 
@@ -208,6 +244,8 @@ namespace Org.BouncyCastle.Crypto.Tls
                     ProcessFinishedMessage(buf);
                     this.mConnectionState = CS_SERVER_FINISHED;
                     this.mConnectionState = CS_END;
+
+                    CompleteHandshake();
                     break;
                 }
                 default:
diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs
index 8eb7beb3f..7acc34d3c 100644
--- a/crypto/src/crypto/tls/TlsProtocol.cs
+++ b/crypto/src/crypto/tls/TlsProtocol.cs
@@ -72,6 +72,10 @@ namespace Org.BouncyCastle.Crypto.Tls
         protected bool mAllowCertificateStatus = false;
         protected bool mExpectSessionTicket = false;
 
+        protected bool mBlocking = true;
+        protected ByteQueueStream mInputBuffers = null;
+        protected ByteQueueStream mOutputBuffer = null;
+
         public TlsProtocol(Stream stream, SecureRandom secureRandom)
             :   this(stream, stream, secureRandom)
         {
@@ -83,6 +87,15 @@ namespace Org.BouncyCastle.Crypto.Tls
             this.mSecureRandom = secureRandom;
         }
 
+        public TlsProtocol(SecureRandom secureRandom)
+        {
+            this.mBlocking = false;
+            this.mInputBuffers = new ByteQueueStream();
+            this.mOutputBuffer = new ByteQueueStream();
+            this.mRecordStream = new RecordStream(this, mInputBuffers, mOutputBuffer);
+            this.mSecureRandom = secureRandom;
+        }
+
         protected abstract TlsContext Context { get; }
 
         internal abstract AbstractTlsContext ContextAdmin { get; }
@@ -140,13 +153,10 @@ namespace Org.BouncyCastle.Crypto.Tls
             this.mExpectSessionTicket = false;
         }
 
-        protected virtual void CompleteHandshake()
+        protected virtual void BlockForHandshake()
         {
-            try
+            if (mBlocking)
             {
-                /*
-                 * We will now read data, until we have completed the handshake.
-                 */
                 while (this.mConnectionState != CS_END)
                 {
                     if (this.mClosed)
@@ -156,7 +166,13 @@ namespace Org.BouncyCastle.Crypto.Tls
 
                     SafeReadRecord();
                 }
+            }
+        }
 
+        protected virtual void CompleteHandshake()
+        {
+            try
+            {
                 this.mRecordStream.FinaliseHandshake();
 
                 this.mSplitApplicationDataRecords = !TlsUtilities.IsTlsV11(Context);
@@ -168,7 +184,10 @@ namespace Org.BouncyCastle.Crypto.Tls
                 {
                     this.mAppDataReady = true;
 
-                    this.mTlsStream = new TlsStream(this);
+                    if (mBlocking)
+                    {
+                        this.mTlsStream = new TlsStream(this);
+                    }
                 }
 
                 if (this.mTlsSession != null)
@@ -573,9 +592,156 @@ namespace Org.BouncyCastle.Crypto.Tls
         }
 
         /// <summary>The secure bidirectional stream for this connection</summary>
+        /// <remarks>Only allowed in blocking mode.</remarks>
         public virtual Stream Stream
         {
-            get { return this.mTlsStream; }
+            get
+            {
+                if (!mBlocking)
+                    throw new InvalidOperationException("Cannot use Stream in non-blocking mode! Use OfferInput()/OfferOutput() instead.");
+                return this.mTlsStream;
+            }
+        }
+
+        /**
+         * Offer input from an arbitrary source. Only allowed in non-blocking mode.<br>
+         * <br>
+         * After this method returns, the input buffer is "owned" by this object. Other code
+         * must not attempt to do anything with it.<br>
+         * <br>
+         * This method will decrypt and process all records that are fully available.
+         * If only part of a record is available, the buffer will be retained until the
+         * remainder of the record is offered.<br>
+         * <br>
+         * If any records containing application data were processed, the decrypted data
+         * can be obtained using {@link #readInput(byte[], int, int)}. If any records
+         * containing protocol data were processed, a response may have been generated.
+         * You should always check to see if there is any available output after calling
+         * this method by calling {@link #getAvailableOutputBytes()}.
+         * @param input The input buffer to offer
+         * @throws IOException If an error occurs while decrypting or processing a record
+         */
+        public virtual void OfferInput(byte[] input)
+        {
+            if (mBlocking)
+                throw new InvalidOperationException("Cannot use OfferInput() in blocking mode! Use Stream instead.");
+            if (mClosed)
+                throw new IOException("Connection is closed, cannot accept any more input");
+
+            mInputBuffers.Write(input);
+
+            // loop while there are enough bytes to read the length of the next record
+            while (mInputBuffers.Available >= RecordStream.TLS_HEADER_SIZE)
+            {
+                byte[] header = new byte[RecordStream.TLS_HEADER_SIZE];
+                mInputBuffers.Peek(header);
+
+                int totalLength = TlsUtilities.ReadUint16(header, RecordStream.TLS_HEADER_LENGTH_OFFSET) + RecordStream.TLS_HEADER_SIZE;
+                if (mInputBuffers.Available < totalLength)
+                {
+                    // not enough bytes to read a whole record
+                    break;
+                }
+
+                SafeReadRecord();
+            }
+        }
+
+        /**
+         * Gets the amount of received application data. A call to {@link #readInput(byte[], int, int)}
+         * is guaranteed to be able to return at least this much data.<br>
+         * <br>
+         * Only allowed in non-blocking mode.
+         * @return The number of bytes of available application data
+         */
+        public virtual int GetAvailableInputBytes()
+        {
+            if (mBlocking)
+                throw new InvalidOperationException("Cannot use GetAvailableInputBytes() in blocking mode! Use ApplicationDataAvailable() instead.");
+
+            return ApplicationDataAvailable();
+        }
+
+        /**
+         * Retrieves received application data. Use {@link #getAvailableInputBytes()} to check
+         * how much application data is currently available. This method functions similarly to
+         * {@link InputStream#read(byte[], int, int)}, except that it never blocks. If no data
+         * is available, nothing will be copied and zero will be returned.<br>
+         * <br>
+         * Only allowed in non-blocking mode.
+         * @param buffer The buffer to hold the application data
+         * @param offset The start offset in the buffer at which the data is written
+         * @param length The maximum number of bytes to read
+         * @return The total number of bytes copied to the buffer. May be less than the
+         *          length specified if the length was greater than the amount of available data.
+         */
+        public virtual int ReadInput(byte[] buffer, int offset, int length)
+        {
+            if (mBlocking)
+                throw new InvalidOperationException("Cannot use ReadInput() in blocking mode! Use Stream instead.");
+
+            return ReadApplicationData(buffer, offset, System.Math.Min(length, ApplicationDataAvailable()));
+        }
+
+        /**
+         * Offer output from an arbitrary source. Only allowed in non-blocking mode.<br>
+         * <br>
+         * After this method returns, the specified section of the buffer will have been
+         * processed. Use {@link #readOutput(byte[], int, int)} to get the bytes to
+         * transmit to the other peer.<br>
+         * <br>
+         * This method must not be called until after the handshake is complete! Attempting
+         * to call it before the handshake is complete will result in an exception.
+         * @param buffer The buffer containing application data to encrypt
+         * @param offset The offset at which to begin reading data
+         * @param length The number of bytes of data to read
+         * @throws IOException If an error occurs encrypting the data, or the handshake is not complete
+         */
+        public virtual void OfferOutput(byte[] buffer, int offset, int length)
+        {
+            if (mBlocking)
+                throw new InvalidOperationException("Cannot use OfferOutput() in blocking mode! Use Stream instead.");
+            if (!mAppDataReady)
+                throw new IOException("Application data cannot be sent until the handshake is complete!");
+
+            WriteData(buffer, offset, length);
+        }
+
+        /**
+         * Gets the amount of encrypted data available to be sent. A call to
+         * {@link #readOutput(byte[], int, int)} is guaranteed to be able to return at
+         * least this much data.<br>
+         * <br>
+         * Only allowed in non-blocking mode.
+         * @return The number of bytes of available encrypted data
+         */
+        public virtual int GetAvailableOutputBytes()
+        {
+            if (mBlocking)
+                throw new InvalidOperationException("Cannot use GetAvailableOutputBytes() in blocking mode! Use Stream instead.");
+
+            return mOutputBuffer.Available;
+        }
+
+        /**
+         * Retrieves encrypted data to be sent. Use {@link #getAvailableOutputBytes()} to check
+         * how much encrypted data is currently available. This method functions similarly to
+         * {@link InputStream#read(byte[], int, int)}, except that it never blocks. If no data
+         * is available, nothing will be copied and zero will be returned.<br>
+         * <br>
+         * Only allowed in non-blocking mode.
+         * @param buffer The buffer to hold the encrypted data
+         * @param offset The start offset in the buffer at which the data is written
+         * @param length The maximum number of bytes to read
+         * @return The total number of bytes copied to the buffer. May be less than the
+         *          length specified if the length was greater than the amount of available data.
+         */
+        public virtual int ReadOutput(byte[] buffer, int offset, int length)
+        {
+            if (mBlocking)
+                throw new InvalidOperationException("Cannot use ReadOutput() in blocking mode! Use Stream instead.");
+
+            return mOutputBuffer.Read(buffer, offset, length);
         }
 
         /**
@@ -764,7 +930,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             mRecordStream.Flush();
         }
 
-        protected internal virtual bool IsClosed
+        public virtual bool IsClosed
         {
             get { return mClosed; }
         }
diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs
index b73cb5a30..27f7a1dfd 100644
--- a/crypto/src/crypto/tls/TlsServerProtocol.cs
+++ b/crypto/src/crypto/tls/TlsServerProtocol.cs
@@ -22,21 +22,57 @@ namespace Org.BouncyCastle.Crypto.Tls
         protected short mClientCertificateType = -1;
         protected TlsHandshakeHash mPrepareFinishHash = null;
 
+        /**
+         * Constructor for blocking mode.
+         * @param stream The bi-directional stream of data to/from the client
+         * @param output The stream of data to the client
+         * @param secureRandom Random number generator for various cryptographic functions
+         */
         public TlsServerProtocol(Stream stream, SecureRandom secureRandom)
-            :   base(stream, secureRandom)
+            : base(stream, secureRandom)
         {
         }
 
+        /**
+         * Constructor for blocking mode.
+         * @param input The stream of data from the client
+         * @param output The stream of data to the client
+         * @param secureRandom Random number generator for various cryptographic functions
+         */
         public TlsServerProtocol(Stream input, Stream output, SecureRandom secureRandom)
-            :   base(input, output, secureRandom)
+            : base(input, output, secureRandom)
+        {
+        }
+
+        /**
+         * Constructor for non-blocking mode.<br>
+         * <br>
+         * When data is received, use {@link #offerInput(java.nio.ByteBuffer)} to
+         * provide the received ciphertext, then use
+         * {@link #readInput(byte[], int, int)} to read the corresponding cleartext.<br>
+         * <br>
+         * Similarly, when data needs to be sent, use
+         * {@link #offerOutput(byte[], int, int)} to provide the cleartext, then use
+         * {@link #readOutput(byte[], int, int)} to get the corresponding
+         * ciphertext.
+         * 
+         * @param secureRandom
+         *            Random number generator for various cryptographic functions
+         */
+        public TlsServerProtocol(SecureRandom secureRandom)
+            : base(secureRandom)
         {
         }
 
         /**
-         * Receives a TLS handshake in the role of server
+         * Receives a TLS handshake in the role of server.<br>
+         * <br>
+         * In blocking mode, this will not return until the handshake is complete.
+         * In non-blocking mode, use {@link TlsPeer#notifyHandshakeComplete()} to
+         * receive a callback when the handshake is complete.
          *
-         * @param mTlsServer
-         * @throws IOException If handshake was not successful.
+         * @param tlsServer
+         * @throws IOException If in blocking mode and handshake was not successful.
          */
         public virtual void Accept(TlsServer tlsServer)
         {
@@ -60,7 +96,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             this.mRecordStream.SetRestrictReadVersion(false);
 
-            CompleteHandshake();
+            BlockForHandshake();
         }
 
         protected override void CleanupHandshake()
@@ -329,6 +365,8 @@ namespace Org.BouncyCastle.Crypto.Tls
                     SendFinishedMessage();
                     this.mConnectionState = CS_SERVER_FINISHED;
                     this.mConnectionState = CS_END;
+
+                    CompleteHandshake();
                     break;
                 }
                 default:
diff --git a/crypto/src/security/SecureRandom.cs b/crypto/src/security/SecureRandom.cs
index f46427a5c..137a471c1 100644
--- a/crypto/src/security/SecureRandom.cs
+++ b/crypto/src/security/SecureRandom.cs
@@ -13,12 +13,16 @@ namespace Org.BouncyCastle.Security
     {
         private static long counter = Times.NanoTime();
 
+#if NETCF_1_0
+        private static object counterLock = new object();
         private static long NextCounterValue()
         {
-            return Interlocked.Increment(ref counter);
+            lock (counterLock)
+            {
+                return ++counter;
+            }
         }
 
-#if NETCF_1_0
         private static readonly SecureRandom[] master = { null };
         private static SecureRandom Master
         {
@@ -43,6 +47,11 @@ namespace Org.BouncyCastle.Security
             }
         }
 #else
+        private static long NextCounterValue()
+        {
+            return Interlocked.Increment(ref counter);
+        }
+
         private static readonly SecureRandom master = new SecureRandom(new CryptoApiRandomGenerator());
         private static SecureRandom Master
         {
diff --git a/crypto/test/src/cms/test/CMSTestUtil.cs b/crypto/test/src/cms/test/CMSTestUtil.cs
index ef7f9169f..69f7c2983 100644
--- a/crypto/test/src/cms/test/CMSTestUtil.cs
+++ b/crypto/test/src/cms/test/CMSTestUtil.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections;
 using System.IO;
 using System.Text;
 
@@ -12,6 +13,7 @@ using Org.BouncyCastle.Utilities.Encoders;
 using Org.BouncyCastle.Utilities.IO;
 using Org.BouncyCastle.X509;
 using Org.BouncyCastle.X509.Extension;
+using Org.BouncyCastle.X509.Store;
 
 namespace Org.BouncyCastle.Cms.Tests
 {
@@ -450,7 +452,40 @@ namespace Org.BouncyCastle.Cms.Tests
 		*  INTERNAL METHODS
 		*
 		*/
-		private static AuthorityKeyIdentifier CreateAuthorityKeyId(
+        internal static IX509Store MakeAttrCertStore(params IX509AttributeCertificate[] attrCerts)
+        {
+            IList attrCertList = new ArrayList();
+            foreach (IX509AttributeCertificate attrCert in attrCerts)
+            {
+                attrCertList.Add(attrCert);
+            }
+
+            return X509StoreFactory.Create("AttributeCertificate/Collection", new X509CollectionStoreParameters(attrCertList));
+        }
+
+        internal static IX509Store MakeCertStore(params X509Certificate[] certs)
+        {
+            IList certList = new ArrayList();
+            foreach (X509Certificate cert in certs)
+            {
+                certList.Add(cert);
+            }
+
+            return X509StoreFactory.Create("Certificate/Collection", new X509CollectionStoreParameters(certList));
+        }
+
+        internal static IX509Store MakeCrlStore(params X509Crl[] crls)
+        {
+            IList crlList = new ArrayList();
+            foreach (X509Crl crl in crls)
+            {
+                crlList.Add(crl);
+            }
+
+            return X509StoreFactory.Create("CRL/Collection", new X509CollectionStoreParameters(crlList));
+        }
+
+        private static AuthorityKeyIdentifier CreateAuthorityKeyId(
 			AsymmetricKeyParameter _pubKey)
 		{
 			SubjectPublicKeyInfo _info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey);
diff --git a/crypto/test/src/cms/test/MiscDataStreamTest.cs b/crypto/test/src/cms/test/MiscDataStreamTest.cs
index f958d058f..4cb19884b 100644
--- a/crypto/test/src/cms/test/MiscDataStreamTest.cs
+++ b/crypto/test/src/cms/test/MiscDataStreamTest.cs
@@ -207,15 +207,12 @@ namespace Org.BouncyCastle.Cms.Tests
 
 			sp.GetSignedContent().Drain();
 
-			//
-			// compute expected content digest
-			//
-			IDigest md = DigestUtilities.GetDigest("SHA1");
-			byte[] cDataOutBytes = cDataOut.ToArray();
-			md.BlockUpdate(cDataOutBytes, 0, cDataOutBytes.Length);
-			byte[] hash = DigestUtilities.DoFinal(md);
-
-			VerifySignatures(sp, hash);
+            byte[] cDataOutBytes = cDataOut.ToArray();
+
+            // compute expected content digest
+            byte[] hash = DigestUtilities.CalculateDigest("SHA1", cDataOutBytes);
+
+            VerifySignatures(sp, hash);
 		}
 	}
 }
diff --git a/crypto/test/src/cms/test/SignedDataStreamTest.cs b/crypto/test/src/cms/test/SignedDataStreamTest.cs
index 96f3f125d..2131938e7 100644
--- a/crypto/test/src/cms/test/SignedDataStreamTest.cs
+++ b/crypto/test/src/cms/test/SignedDataStreamTest.cs
@@ -233,112 +233,74 @@ namespace Org.BouncyCastle.Cms.Tests
 			VerifySignatures(sp);
 		}
 
-//		[Test]
-//		public void TestSha1WithRsaNoAttributes()
-//		{
-//			IList certList = new ArrayList();
-//			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes(TestMessage));
-//
-//			certList.Add(OrigCert);
-//			certList.Add(SignCert);
-//
-//			IX509Store x509Certs = X509StoreFactory.Create(
-//				"Certificate/Collection",
-//				new X509CollectionStoreParameters(certList));
-//
-//			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
-//
-//			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
-//
-//			gen.AddCertificates(x509Certs);
-//
-//			CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false, false);
-//
-//			CmsSignedDataParser sp = new CmsSignedDataParser(
-//				new CmsTypedStream(new MemoryStream(Encoding.ASCII.GetBytes(TestMessage), false)), s.GetEncoded());
-//
-//			sp.GetSignedContent().Drain();
-//
-//			//
-//			// compute expected content digest
-//			//
-//			IDigest md = DigestUtilities.GetDigest("SHA1");
-//
-//			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
-//			md.BlockUpdate(testBytes, 0, testBytes.Length);
-//			byte[] hash = DigestUtilities.DoFinal(md);
-//
-//			VerifySignatures(sp, hash);
-//		}
+        //[Test]
+        //public void TestSha1WithRsaNoAttributes()
+        //{
+        //    CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes(TestMessage));
 
-//		[Test]
-//		public void TestDsaNoAttributes()
-//		{
-//			IList certList = new ArrayList();
-//			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes(TestMessage));
-//
-//			certList.Add(OrigDsaCert);
-//			certList.Add(SignCert);
-//
-//			IX509Store x509Certs = X509StoreFactory.Create(
-//				"Certificate/Collection",
-//				new X509CollectionStoreParameters(certList));
-//
-//			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
-//
-//			gen.AddSigner(OrigDsaKP.Private, OrigDsaCert, CmsSignedDataGenerator.DigestSha1);
-//
-//			gen.AddCertificates(x509Certs);
-//
-//			CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false, false);
-//
-//			CmsSignedDataParser sp = new CmsSignedDataParser(
-//				new CmsTypedStream(
-//				new MemoryStream(Encoding.ASCII.GetBytes(TestMessage), false)),
-//				s.GetEncoded());
-//
-//			sp.GetSignedContent().Drain();
-//
-//			//
-//			// compute expected content digest
-//			//
-//			IDigest md = DigestUtilities.GetDigest("SHA1");
-//
-//			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
-//			md.BlockUpdate(testBytes, 0, testBytes.Length);
-//			byte[] hash = DigestUtilities.DoFinal(md);
-//
-//			VerifySignatures(sp, hash);
-//		}
+        //    IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
+
+        //    CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+        //    gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+        //    gen.AddCertificates(x509Certs);
+
+        //    CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false, false);
+
+        //    CmsSignedDataParser sp = new CmsSignedDataParser(
+        //        new CmsTypedStream(new MemoryStream(Encoding.ASCII.GetBytes(TestMessage), false)), s.GetEncoded());
+
+        //    sp.GetSignedContent().Drain();
+
+        //    byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+
+        //    // compute expected content digest
+        //    byte[] hash = DigestUtilities.CalculateDigest("SHA1", testBytes);
+
+        //    VerifySignatures(sp, hash);
+        //}
+
+        //[Test]
+        //public void TestDsaNoAttributes()
+        //{
+        //    CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes(TestMessage));
+
+        //    IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigDsaCert, SignCert);
+
+        //    CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+        //    gen.AddSigner(OrigDsaKP.Private, OrigDsaCert, CmsSignedDataGenerator.DigestSha1);
+        //    gen.AddCertificates(x509Certs);
+
+        //    CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false, false);
+
+        //    CmsSignedDataParser sp = new CmsSignedDataParser(
+        //        new CmsTypedStream(
+        //        new MemoryStream(Encoding.ASCII.GetBytes(TestMessage), false)),
+        //        s.GetEncoded());
+
+        //    sp.GetSignedContent().Drain();
+
+        //    byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+
+        //    // compute expected content digest
+        //    byte[] hash = DigestUtilities.CalculateDigest("SHA1", testBytes);
+
+        //    VerifySignatures(sp, hash);
+        //}
 
 		[Test]
 		public void TestSha1WithRsa()
 		{
-			IList certList = new ArrayList();
-			IList crlList = new ArrayList();
 			MemoryStream bOut = new MemoryStream();
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			crlList.Add(SignCrl);
-			crlList.Add(OrigCrl);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-			IX509Store x509Crls = X509StoreFactory.Create(
-				"CRL/Collection",
-				new X509CollectionStoreParameters(crlList));
-
-			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
+            IX509Store x509Crls = CmsTestUtil.MakeCrlStore(SignCrl, OrigCrl);
 
+            CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 			gen.AddCrls(x509Crls);
 
-			Stream sigOut = gen.Open(bOut);
+            Stream sigOut = gen.Open(bOut);
 
 			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
 			sigOut.Write(testBytes, 0, testBytes.Length);
@@ -352,41 +314,33 @@ namespace Org.BouncyCastle.Cms.Tests
 
 			sp.GetSignedContent().Drain();
 
-			//
-			// compute expected content digest
-			//
-			IDigest md = DigestUtilities.GetDigest("SHA1");
-			md.BlockUpdate(testBytes, 0, testBytes.Length);
-			byte[] hash = DigestUtilities.DoFinal(md);
+            // compute expected content digest
+            byte[] hash = DigestUtilities.CalculateDigest("SHA1", testBytes);
 
-			VerifySignatures(sp, hash);
+            VerifySignatures(sp, hash);
 
 			//
 			// try using existing signer
 			//
 			gen = new CmsSignedDataStreamGenerator();
-
 			gen.AddSigners(sp.GetSignerInfos());
-
 			gen.AddCertificates(sp.GetCertificates("Collection"));
 			gen.AddCrls(sp.GetCrls("Collection"));
 
-			bOut.SetLength(0);
-
-			sigOut = gen.Open(bOut, true);
+            bOut.SetLength(0);
 
+            sigOut = gen.Open(bOut, true);
 			sigOut.Write(testBytes, 0, testBytes.Length);
-
 			sigOut.Close();
 
-			VerifyEncodedData(bOut);
+            VerifyEncodedData(bOut);
 
-			//
+            //
 			// look for the CRLs
 			//
 			ArrayList col = new ArrayList(x509Crls.GetMatches(null));
 
-			Assert.AreEqual(2, col.Count);
+            Assert.AreEqual(2, col.Count);
 			Assert.IsTrue(col.Contains(SignCrl));
 			Assert.IsTrue(col.Contains(OrigCrl));
 		}
@@ -394,80 +348,53 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestSha1WithRsaNonData()
 		{
-			IList certList = new ArrayList();
-			IList crlList = new ArrayList();
 			MemoryStream bOut = new MemoryStream();
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			crlList.Add(SignCrl);
-			crlList.Add(OrigCrl);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-			IX509Store x509Crls = X509StoreFactory.Create(
-				"CRL/Collection",
-				new X509CollectionStoreParameters(crlList));
-
-			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
+            IX509Store x509Crls = CmsTestUtil.MakeCrlStore(SignCrl, OrigCrl);
 
+            CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 			gen.AddCrls(x509Crls);
 
-			Stream sigOut = gen.Open(bOut, "1.2.3.4", true);
+            byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
 
-			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+            Stream sigOut = gen.Open(bOut, "1.2.3.4", true);
 			sigOut.Write(testBytes, 0, testBytes.Length);
-
 			sigOut.Close();
 
-			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+            CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
 
-			CmsTypedStream stream = sp.GetSignedContent();
+            CmsTypedStream stream = sp.GetSignedContent();
 
 			Assert.AreEqual("1.2.3.4", stream.ContentType);
 
 			stream.Drain();
 
-			//
-			// compute expected content digest
-			//
-			IDigest md = DigestUtilities.GetDigest("SHA1");
-			md.BlockUpdate(testBytes, 0, testBytes.Length);
-			byte[] hash = DigestUtilities.DoFinal(md);
+            // compute expected content digest
+            byte[] hash = DigestUtilities.CalculateDigest("SHA1", testBytes);
 
-			VerifySignatures(sp, hash);
+            VerifySignatures(sp, hash);
 		}
 
-		[Test]
+        [Test]
 		public void TestSha1AndMD5WithRsa()
 		{
-			IList certList = new ArrayList();
 			MemoryStream bOut = new MemoryStream();
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
+            CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
 			gen.AddDigests(CmsSignedDataStreamGenerator.DigestSha1,
 				CmsSignedDataStreamGenerator.DigestMD5);
 
-			Stream sigOut = gen.Open(bOut);
+            byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
 
-			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+            Stream sigOut = gen.Open(bOut);
 			sigOut.Write(testBytes, 0, testBytes.Length);
 
 			gen.AddCertificates(x509Certs);
-
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestMD5);
 
@@ -486,39 +413,29 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestSha1WithRsaEncapsulatedBufferedStream()
 		{
-			IList certList = new ArrayList();
 			MemoryStream bOut = new MemoryStream();
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
-			//
+            //
 			// find unbuffered length
 			//
 			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
-
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
 			Stream sigOut = gen.Open(bOut, true);
-
 			for (int i = 0; i != 2000; i++)
 			{
 				sigOut.WriteByte((byte)(i & 0xff));
 			}
-
 			sigOut.Close();
 
 			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
 
-			sp.GetSignedContent().Drain();
+            sp.GetSignedContent().Drain();
 
-			VerifySignatures(sp);
+            VerifySignatures(sp);
 
 			int unbufferedLength = bOut.ToArray().Length;
 
@@ -528,9 +445,7 @@ namespace Org.BouncyCastle.Cms.Tests
 			bOut.SetLength(0);
 
 			gen = new CmsSignedDataStreamGenerator();
-
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
 			sigOut = gen.Open(bOut, true);
@@ -541,10 +456,10 @@ namespace Org.BouncyCastle.Cms.Tests
 				data[i] = (byte)(i & 0xff);
 			}
 
-			Streams.PipeAll(new MemoryStream(data, false), sigOut);
+            Streams.PipeAll(new MemoryStream(data, false), sigOut);
 			sigOut.Close();
 
-			VerifyEncodedData(bOut);
+            VerifyEncodedData(bOut);
 
 			Assert.AreEqual(unbufferedLength, bOut.ToArray().Length);
 		}
@@ -552,23 +467,15 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestSha1WithRsaEncapsulatedBuffered()
 		{
-			IList certList = new ArrayList();
 			MemoryStream bOut = new MemoryStream();
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
 			//
 			// find unbuffered length
 			//
 			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
-
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
 			Stream sigOut = gen.Open(bOut, true);
@@ -594,14 +501,11 @@ namespace Org.BouncyCastle.Cms.Tests
 			bOut.SetLength(0);
 
 			gen = new CmsSignedDataStreamGenerator();
-
 			gen.SetBufferSize(300);
-
-			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
-
+            gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
 			gen.AddCertificates(x509Certs);
 
-			sigOut = gen.Open(bOut, true);
+            sigOut = gen.Open(bOut, true);
 
 			for (int i = 0; i != 2000; i++)
 			{
@@ -618,38 +522,29 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestSha1WithRsaEncapsulated()
 		{
-			IList certList = new ArrayList();
 			MemoryStream bOut = new MemoryStream();
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
+            CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
-			Stream sigOut = gen.Open(bOut, true);
+            byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
 
-			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+            Stream sigOut = gen.Open(bOut, true);
 			sigOut.Write(testBytes, 0, testBytes.Length);
-
 			sigOut.Close();
 
-			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+            CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
 
 			sp.GetSignedContent().Drain();
 
 			VerifySignatures(sp);
 
-			byte[] contentDigest = (byte[])gen.GetGeneratedDigests()[CmsSignedGenerator.DigestSha1];
+            byte[] contentDigest = (byte[])gen.GetGeneratedDigests()[CmsSignedGenerator.DigestSha1];
 
-			ArrayList signers = new ArrayList(sp.GetSignerInfos().GetSigners());
+            ArrayList signers = new ArrayList(sp.GetSignerInfos().GetSigners());
 
 			AttributeTable table = ((SignerInformation) signers[0]).SignedAttributes;
 			Asn1.Cms.Attribute hash = table[CmsAttributes.MessageDigest];
@@ -660,26 +555,22 @@ namespace Org.BouncyCastle.Cms.Tests
 			// try using existing signer
 			//
 			gen = new CmsSignedDataStreamGenerator();
-
 			gen.AddSigners(sp.GetSignerInfos());
-
 			gen.AddCertificates(sp.GetCertificates("Collection"));
 			gen.AddCrls(sp.GetCrls("Collection"));
 
-			bOut.SetLength(0);
-
-			sigOut = gen.Open(bOut, true);
+            bOut.SetLength(0);
 
+            sigOut = gen.Open(bOut, true);
 			sigOut.Write(testBytes, 0, testBytes.Length);
-
 			sigOut.Close();
 
-			CmsSignedData sd = new CmsSignedData(
+            CmsSignedData sd = new CmsSignedData(
 				new CmsProcessableByteArray(testBytes), bOut.ToArray());
 
-			Assert.AreEqual(1, sd.GetSignerInfos().GetSigners().Count);
+            Assert.AreEqual(1, sd.GetSignerInfos().GetSigners().Count);
 
-			VerifyEncodedData(bOut);
+            VerifyEncodedData(bOut);
 		}
 
 		private static readonly DerObjectIdentifier dummyOid1 = new DerObjectIdentifier("1.2.3");
@@ -718,32 +609,23 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 	    public void TestSha1WithRsaEncapsulatedSubjectKeyID()
 	    {
-	        IList certList = new ArrayList();
 	        MemoryStream bOut = new MemoryStream();
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
+            CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
 	        gen.AddSigner(OrigKP.Private,
 				CmsTestUtil.CreateSubjectKeyId(OrigCert.GetPublicKey()).GetKeyIdentifier(),
 				CmsSignedDataStreamGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
-			Stream sigOut = gen.Open(bOut, true);
-
-			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
-			sigOut.Write(testBytes, 0, testBytes.Length);
+            byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
 
+            Stream sigOut = gen.Open(bOut, true);
+            sigOut.Write(testBytes, 0, testBytes.Length);
 			sigOut.Close();
 
-			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+            CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
 
 			sp.GetSignedContent().Drain();
 
@@ -762,55 +644,42 @@ namespace Org.BouncyCastle.Cms.Tests
 			// try using existing signer
 			//
 			gen = new CmsSignedDataStreamGenerator();
-
 			gen.AddSigners(sp.GetSignerInfos());
-
-//			gen.AddCertificatesAndCRLs(sp.getCertificatesAndCRLs("Collection", "BC"));
+//			gen.AddCertificatesAndCRLs(sp.GetCertificatesAndCrls("Collection", "BC"));
 			gen.AddCertificates(sp.GetCertificates("Collection"));
 
-			bOut.SetLength(0);
-
-			sigOut = gen.Open(bOut, true);
+            bOut.SetLength(0);
 
+            sigOut = gen.Open(bOut, true);
 			sigOut.Write(testBytes, 0, testBytes.Length);
-
 			sigOut.Close();
 
-			CmsSignedData sd = new CmsSignedData(new CmsProcessableByteArray(testBytes), bOut.ToArray());
+            CmsSignedData sd = new CmsSignedData(new CmsProcessableByteArray(testBytes), bOut.ToArray());
 
 			Assert.AreEqual(1, sd.GetSignerInfos().GetSigners().Count);
 
 	        VerifyEncodedData(bOut);
 	    }
 
-		[Test]
+        [Test]
 		public void TestAttributeGenerators()
 		{
-			IList certList = new ArrayList();
 			MemoryStream bOut = new MemoryStream();
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
 			CmsAttributeTableGenerator signedGen = new SignedGenAttributeTableGenerator();
 			CmsAttributeTableGenerator unsignedGen = new UnsignedGenAttributeTableGenerator();
 
-			gen.AddSigner(OrigKP.Private, OrigCert,
+            CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            gen.AddSigner(OrigKP.Private, OrigCert,
 				CmsSignedDataStreamGenerator.DigestSha1, signedGen, unsignedGen);
-
 			gen.AddCertificates(x509Certs);
 
-			Stream sigOut = gen.Open(bOut, true);
+            byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
 
-			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			Stream sigOut = gen.Open(bOut, true);
 			sigOut.Write(testBytes, 0, testBytes.Length);
-
 			sigOut.Close();
 
 			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
@@ -826,59 +695,44 @@ namespace Org.BouncyCastle.Cms.Tests
 
 			foreach (SignerInformation signer in signers.GetSigners())
 			{
-				checkAttribute(signer.GetContentDigest(), signer.SignedAttributes[dummyOid1]);
-				checkAttribute(signer.GetSignature(), signer.UnsignedAttributes[dummyOid2]);
+				CheckAttribute(signer.GetContentDigest(), signer.SignedAttributes[dummyOid1]);
+				CheckAttribute(signer.GetSignature(), signer.UnsignedAttributes[dummyOid2]);
 			}
 		}
 
-		private void checkAttribute(
-			byte[]				expected,
-			Asn1.Cms.Attribute	attr)
+		private void CheckAttribute(byte[] expected, Asn1.Cms.Attribute	attr)
 		{
 			DerOctetString value = (DerOctetString)attr.AttrValues[0];
 
-			Assert.AreEqual(new DerOctetString(expected), value);
+            Assert.AreEqual(new DerOctetString(expected), value);
 		}
 
-		[Test]
+        [Test]
 		public void TestWithAttributeCertificate()
 		{
-			IList certList = new ArrayList();
-
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(SignCert);
 
+            CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
-			IX509AttributeCertificate attrCert = CmsTestUtil.GetAttributeCertificate();
+            IX509AttributeCertificate attrCert = CmsTestUtil.GetAttributeCertificate();
 
-			ArrayList attrCerts = new ArrayList();
-			attrCerts.Add(attrCert);
-			IX509Store store = X509StoreFactory.Create(
-				"AttributeCertificate/Collection",
-				new X509CollectionStoreParameters(attrCerts));
+            IX509Store store = CmsTestUtil.MakeAttrCertStore(attrCert);
 
-			gen.AddAttributeCertificates(store);
+            gen.AddAttributeCertificates(store);
 
-			MemoryStream bOut = new MemoryStream();
+            MemoryStream bOut = new MemoryStream();
 
-			Stream sigOut = gen.Open(bOut, true);
+            byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
 
-			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			Stream sigOut = gen.Open(bOut, true);
 			sigOut.Write(testBytes, 0, testBytes.Length);
-
 			sigOut.Close();
 
-			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+            CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
 
-			sp.GetSignedContent().Drain();
+            sp.GetSignedContent().Drain();
 
 			Assert.AreEqual(4, sp.Version);
 
@@ -894,27 +748,17 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestSignerStoreReplacement()
 		{
-			IList certList = new ArrayList();
 			MemoryStream bOut = new MemoryStream();
 			byte[] data = Encoding.ASCII.GetBytes(TestMessage);
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
 			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
-
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
 			Stream sigOut = gen.Open(bOut, false);
-
 			sigOut.Write(data, 0, data.Length);
-
 			sigOut.Close();
 
 			CheckSigParseable(bOut.ToArray());
@@ -927,18 +771,15 @@ namespace Org.BouncyCastle.Cms.Tests
 			bOut.SetLength(0);
 
 			gen = new CmsSignedDataStreamGenerator();
-
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha224);
 
-			gen.AddCertificates(x509Certs);
+            gen.AddCertificates(x509Certs);
 
 			sigOut = gen.Open(bOut);
-
 			sigOut.Write(data, 0, data.Length);
-
 			sigOut.Close();
 
-			CheckSigParseable(bOut.ToArray());
+            CheckSigParseable(bOut.ToArray());
 
 			CmsSignedData sd = new CmsSignedData(bOut.ToArray());
 
@@ -953,7 +794,7 @@ namespace Org.BouncyCastle.Cms.Tests
 
 			IEnumerator signerEnum = sd.GetSignerInfos().GetSigners().GetEnumerator();
 			signerEnum.MoveNext();
-			SignerInformation signer = (SignerInformation) signerEnum.Current;
+			SignerInformation signer = (SignerInformation)signerEnum.Current;
 
 			Assert.AreEqual(signer.DigestAlgOid, CmsSignedDataStreamGenerator.DigestSha224);
 
@@ -968,27 +809,18 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestEncapsulatedSignerStoreReplacement()
 		{
-			IList certList = new ArrayList();
 			MemoryStream bOut = new MemoryStream();
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
+            CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
-			Stream sigOut = gen.Open(bOut, true);
+            byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
 
-			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			Stream sigOut = gen.Open(bOut, true);
 			sigOut.Write(testBytes, 0, testBytes.Length);
-
 			sigOut.Close();
 
 			//
@@ -999,20 +831,16 @@ namespace Org.BouncyCastle.Cms.Tests
 			bOut.SetLength(0);
 
 			gen = new CmsSignedDataStreamGenerator();
-
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha224);
-
 			gen.AddCertificates(x509Certs);
 
-			sigOut = gen.Open(bOut, true);
-
+            sigOut = gen.Open(bOut, true);
 			sigOut.Write(testBytes, 0, testBytes.Length);
-
 			sigOut.Close();
 
-			CmsSignedData sd = new CmsSignedData(bOut.ToArray());
+            CmsSignedData sd = new CmsSignedData(bOut.ToArray());
 
-			//
+            //
 			// replace signer
 			//
 			MemoryStream newOut = new MemoryStream();
@@ -1037,40 +865,25 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestCertStoreReplacement()
 		{
-			IList certList = new ArrayList();
 			MemoryStream bOut = new MemoryStream();
 			byte[] data = Encoding.ASCII.GetBytes(TestMessage);
 
-			certList.Add(OrigDsaCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigDsaCert);
 
+            CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
-			Stream sigOut = gen.Open(bOut);
-
+            Stream sigOut = gen.Open(bOut);
 			sigOut.Write(data, 0, data.Length);
-
 			sigOut.Close();
 
-			CheckSigParseable(bOut.ToArray());
+            CheckSigParseable(bOut.ToArray());
 
-			//
+            //
 			// create new certstore with the right certificates
 			//
-			certList = new ArrayList();
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
+            x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
 			//
 			// replace certs
@@ -1090,14 +903,9 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestEncapsulatedCertStoreReplacement()
 		{
-			IList certList = new ArrayList();
 			MemoryStream bOut = new MemoryStream();
 
-			certList.Add(OrigDsaCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigDsaCert);
 
 			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
 
@@ -1115,15 +923,9 @@ namespace Org.BouncyCastle.Cms.Tests
 			//
 			// create new certstore with the right certificates
 			//
-			certList = new ArrayList();
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
+            x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
-			x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			//
+            //
 			// replace certs
 			//
 			MemoryStream original = new MemoryStream(bOut.ToArray(), false);
@@ -1141,30 +943,21 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestCertOrdering1()
 		{
-			IList certList = new ArrayList();
 			MemoryStream bOut = new MemoryStream();
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
+            CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
-			Stream sigOut = gen.Open(bOut, true);
+            byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
 
-			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			Stream sigOut = gen.Open(bOut, true);
 			sigOut.Write(testBytes, 0, testBytes.Length);
-
 			sigOut.Close();
 
-			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+            CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
 
 			sp.GetSignedContent().Drain();
 			x509Certs = sp.GetCertificates("Collection");
@@ -1178,32 +971,23 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestCertOrdering2()
 		{
-			IList certList = new ArrayList();
 			MemoryStream bOut = new MemoryStream();
 
-			certList.Add(SignCert);
-			certList.Add(OrigCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(SignCert, OrigCert);
 
+            CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
-			Stream sigOut = gen.Open(bOut, true);
+            byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
 
-			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+            Stream sigOut = gen.Open(bOut, true);
 			sigOut.Write(testBytes, 0, testBytes.Length);
-
 			sigOut.Close();
 
-			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+            CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
 
-			sp.GetSignedContent().Drain();
+            sp.GetSignedContent().Drain();
 			x509Certs = sp.GetCertificates("Collection");
 			ArrayList a = new ArrayList(x509Certs.GetMatches(null));
 
@@ -1215,13 +999,7 @@ namespace Org.BouncyCastle.Cms.Tests
         [Test]
         public void TestCertsOnly()
         {
-            IList certList = new ArrayList();
-            certList.Add(OrigCert);
-            certList.Add(SignCert);
-
-            IX509Store x509Certs = X509StoreFactory.Create(
-                "Certificate/Collection",
-                new X509CollectionStoreParameters(certList));
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
             MemoryStream bOut = new MemoryStream();
 
diff --git a/crypto/test/src/cms/test/SignedDataTest.cs b/crypto/test/src/cms/test/SignedDataTest.cs
index 96f00eadc..0c176bdeb 100644
--- a/crypto/test/src/cms/test/SignedDataTest.cs
+++ b/crypto/test/src/cms/test/SignedDataTest.cs
@@ -413,64 +413,37 @@ namespace Org.BouncyCastle.Cms.Tests
 			byte[] data = Encoding.ASCII.GetBytes("Hello World!");
 			CmsProcessable msg = new CmsProcessableByteArray(data);
 
-			IList certList = new ArrayList();
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
+            CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
-
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestMD5);
-
 			gen.AddCertificates(x509Certs);
 
-			CmsSignedData s = gen.Generate(msg);
+            CmsSignedData s = gen.Generate(msg);
 
 			IDictionary hashes = new Hashtable();
-			hashes.Add(CmsSignedDataGenerator.DigestSha1, CalculateHash("SHA1", data));
-			hashes.Add(CmsSignedDataGenerator.DigestMD5, CalculateHash("MD5", data));
+			hashes.Add(CmsSignedDataGenerator.DigestSha1, DigestUtilities.CalculateDigest("SHA1", data));
+            hashes.Add(CmsSignedDataGenerator.DigestMD5, DigestUtilities.CalculateDigest("MD5", data));
 
 			s = new CmsSignedData(hashes, s.GetEncoded());
 
 			VerifySignatures(s, null);
 		}
 
-		private byte[] CalculateHash(
-			string	digestName,
-			byte[]	data)
-		{
-			IDigest digest = DigestUtilities.GetDigest(digestName);
-			digest.BlockUpdate(data, 0, data.Length);
-			return DigestUtilities.DoFinal(digest);
-		}
-
-		[Test]
+        [Test]
 		public void TestSha1AndMD5WithRsaEncapsulatedRepeated()
 		{
-			IList certList = new ArrayList();
 			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
 			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
-
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
-
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestMD5);
-
 			gen.AddCertificates(x509Certs);
 
-			CmsSignedData s = gen.Generate(msg, true);
+            CmsSignedData s = gen.Generate(msg, true);
 
 			s = new CmsSignedData(ContentInfo.GetInstance(Asn1Object.FromByteArray(s.GetEncoded())));
 
@@ -550,73 +523,50 @@ namespace Org.BouncyCastle.Cms.Tests
 		}
 
 		// NB: C# build doesn't support "no attributes" version of CmsSignedDataGenerator.Generate
-//		[Test]
-//		public void TestSha1WithRsaNoAttributes()
-//		{
-//			IList certList = new ArrayList();
-//			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello world!"));
-//
-//			certList.Add(OrigCert);
-//			certList.Add(SignCert);
-//
-//			IX509Store x509Certs = X509StoreFactory.Create(
-//				"Certificate/Collection",
-//				new X509CollectionStoreParameters(certList));
-//
-//			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
-//
-//			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
-//
-//			gen.AddCertificates(x509Certs);
-//
-//			CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false, false);
-//
-//			//
-//			// compute expected content digest
-//			//
-//			IDigest md = DigestUtilities.GetDigest("SHA1");
-//
-//			byte[] testBytes = Encoding.ASCII.GetBytes("Hello world!");
-//			md.BlockUpdate(testBytes, 0, testBytes.Length);
-//			byte[] hash = DigestUtilities.DoFinal(md);
-//
-//			VerifySignatures(s, hash);
-//		}
+        //[Test]
+        //public void TestSha1WithRsaNoAttributes()
+        //{
+        //    CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello world!"));
+
+        //    IX509Store x509Certs = MakeCertStore(OrigCert, SignCert);
+
+        //    CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+        //    gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+        //    gen.AddCertificates(x509Certs);
+
+        //    CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false, false);
+
+        //    byte[] testBytes = Encoding.ASCII.GetBytes("Hello world!");
+
+        //    // compute expected content digest
+        //    byte[] hash = DigestUtilities.CalculateDigest("SHA1", testBytes);
+
+        //    VerifySignatures(s, hash);
+        //}
 
 		[Test]
 		public void TestSha1WithRsaAndAttributeTable()
 		{
 			byte[] testBytes = Encoding.ASCII.GetBytes("Hello world!");
-
-			IList certList = new ArrayList();
 			CmsProcessable msg = new CmsProcessableByteArray(testBytes);
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
-
-			IDigest md = DigestUtilities.GetDigest("SHA1");
-			md.BlockUpdate(testBytes, 0, testBytes.Length);
-			byte[] hash = DigestUtilities.DoFinal(md);
+            byte[] hash = DigestUtilities.CalculateDigest("SHA1", testBytes);
 
 			Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.MessageDigest,
 				new DerSet(new DerOctetString(hash)));
 
 			Asn1EncodableVector v = new Asn1EncodableVector(attr);
 
-			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1,
+            CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+            gen.AddSigner(SignKP.Private, SignCert, CmsSignedDataGenerator.DigestSha1,
 				new AttributeTable(v), null);
-
 			gen.AddCertificates(x509Certs);
 
-			CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, null, false);
+            CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, null, false);
 
-			//
+            //
 			// the signature is detached, so need to add msg before passing on
 			//
 			s = new CmsSignedData(msg, s.GetEncoded());
@@ -772,26 +722,13 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestSha1WithRsaCounterSignature()
 		{
-			IList certList = new ArrayList();
-			IList crlList = new ArrayList();
 			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
 
-			certList.Add(SignCert);
-			certList.Add(OrigCert);
-
-			crlList.Add(SignCrl);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-			IX509Store x509Crls = X509StoreFactory.Create(
-				"CRL/Collection",
-				new X509CollectionStoreParameters(crlList));
-
-			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(SignCert, OrigCert);
+            IX509Store x509Crls = CmsTestUtil.MakeCrlStore(SignCrl);
 
+            CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
 			gen.AddSigner(SignKP.Private, SignCert, CmsSignedDataGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 			gen.AddCrls(x509Crls);
 
@@ -825,33 +762,21 @@ namespace Org.BouncyCastle.Cms.Tests
 			string	digestName,
 			string	digestOID)
 		{
-			IList certList = new ArrayList();
 			byte[] msgBytes = Encoding.ASCII.GetBytes("Hello World!");
 			CmsProcessable msg = new CmsProcessableByteArray(msgBytes);
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
+            CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.EncryptionRsaPss, digestOID);
-
 			gen.AddCertificates(x509Certs);
 
-			CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false);
+            CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false);
 
-			//
-			// compute expected content digest
-			//
-			IDigest md = DigestUtilities.GetDigest(digestName);
-			md.BlockUpdate(msgBytes, 0, msgBytes.Length);
-			byte[] expectedDigest = DigestUtilities.DoFinal(md);
+            // compute expected content digest
+            byte[] expectedDigest = DigestUtilities.CalculateDigest(digestName, msgBytes);
 
-			VerifySignatures(s, expectedDigest);
+            VerifySignatures(s, expectedDigest);
 		}
 
 		private void SubjectKeyIDTest(
@@ -859,32 +784,19 @@ namespace Org.BouncyCastle.Cms.Tests
 			X509Certificate			signatureCert,
 			string					digestAlgorithm)
 		{
-			IList certList = new ArrayList();
-			IList crlList = new ArrayList();
 			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
 
-			certList.Add(signatureCert);
-			certList.Add(OrigCert);
-
-			crlList.Add(SignCrl);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-			IX509Store x509Crls = X509StoreFactory.Create(
-				"CRL/Collection",
-				new X509CollectionStoreParameters(crlList));
-
-			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(signatureCert, OrigCert);
+            IX509Store x509Crls = CmsTestUtil.MakeCrlStore(SignCrl);
 
+            CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
 			gen.AddSigner(signaturePair.Private,
 				CmsTestUtil.CreateSubjectKeyId(signatureCert.GetPublicKey()).GetKeyIdentifier(),
 				digestAlgorithm);
-
 			gen.AddCertificates(x509Certs);
 			gen.AddCrls(x509Crls);
 
-			CmsSignedData s = gen.Generate(msg, true);
+            CmsSignedData s = gen.Generate(msg, true);
 
 			Assert.AreEqual(3, s.Version);
 
@@ -962,26 +874,13 @@ namespace Org.BouncyCastle.Cms.Tests
 			X509Certificate			signatureCert,
 			string					digestAlgorithm)
 		{
-			IList certList = new ArrayList();
-			IList crlList = new ArrayList();
 			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
 
-			certList.Add(signatureCert);
-			certList.Add(OrigCert);
-
-			crlList.Add(SignCrl);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-			IX509Store x509Crls = X509StoreFactory.Create(
-				"CRL/Collection",
-				new X509CollectionStoreParameters(crlList));
-
-			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(signatureCert, OrigCert);
+            IX509Store x509Crls = CmsTestUtil.MakeCrlStore(SignCrl);
 
+            CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
 			gen.AddSigner(signaturePair.Private, signatureCert, digestAlgorithm);
-
 			gen.AddCertificates(x509Certs);
 			gen.AddCrls(x509Crls);
 
@@ -1105,22 +1004,13 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestNullContentWithSigner()
 		{
-			IList certList = new ArrayList();
-
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
+            CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
-			CmsSignedData s = gen.Generate(null, false);
+            CmsSignedData s = gen.Generate(null, false);
 
 			s = new CmsSignedData(ContentInfo.GetInstance(Asn1Object.FromByteArray(s.GetEncoded())));
 
@@ -1130,29 +1020,17 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestWithAttributeCertificate()
 		{
-			IList certList = new ArrayList();
 			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
 
-			certList.Add(SignDsaCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(SignDsaCert);
 
+            CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
-			IX509AttributeCertificate attrCert = CmsTestUtil.GetAttributeCertificate();
-
-			ArrayList attrCerts = new ArrayList();
-			attrCerts.Add(attrCert);
+            IX509AttributeCertificate attrCert = CmsTestUtil.GetAttributeCertificate();
 
-			IX509Store store = X509StoreFactory.Create(
-				"AttributeCertificate/Collection",
-				new X509CollectionStoreParameters(attrCerts));
+            IX509Store store = CmsTestUtil.MakeAttrCertStore(attrCert);
 
 			gen.AddAttributeCertificates(store);
 
@@ -1171,13 +1049,7 @@ namespace Org.BouncyCastle.Cms.Tests
 			//
 			// create new certstore
 			//
-			certList = new ArrayList();
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
+            x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
 			//
 			// replace certs
@@ -1190,35 +1062,22 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestCertStoreReplacement()
 		{
-			IList certList = new ArrayList();
 			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
 
-			certList.Add(SignDsaCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(SignDsaCert);
 
+            CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
-			CmsSignedData sd = gen.Generate(msg);
+            CmsSignedData sd = gen.Generate(msg);
 
 			//
 			// create new certstore
 			//
-			certList = new ArrayList();
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
+            x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
-			x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			//
+            //
 			// replace certs
 			//
 			sd = CmsSignedData.ReplaceCertificatesAndCrls(sd, x509Certs, null, null);
@@ -1229,35 +1088,22 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestEncapsulatedCertStoreReplacement()
 		{
-			IList certList = new ArrayList();
 			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
 
-			certList.Add(SignDsaCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(SignDsaCert);
 
+            CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
-			CmsSignedData sd = gen.Generate(msg, true);
+            CmsSignedData sd = gen.Generate(msg, true);
 
 			//
 			// create new certstore
 			//
-			certList = new ArrayList();
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
+            x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
-			//
+            //
 			// replace certs
 			//
 			sd = CmsSignedData.ReplaceCertificatesAndCrls(sd, x509Certs, null, null);
@@ -1268,24 +1114,15 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestCertOrdering1()
 		{
-			IList certList = new ArrayList();
 			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-			certList.Add(SignDsaCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert, SignDsaCert);
 
+            CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
-			CmsSignedData sd = gen.Generate(msg, true);
+            CmsSignedData sd = gen.Generate(msg, true);
 
 			x509Certs = sd.GetCertificates("Collection");
 			ArrayList a = new ArrayList(x509Certs.GetMatches(null));
@@ -1299,29 +1136,20 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestCertOrdering2()
 		{
-			IList certList = new ArrayList();
 			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
 
-			certList.Add(SignCert);
-			certList.Add(SignDsaCert);
-			certList.Add(OrigCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-	
-			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(SignCert, SignDsaCert, OrigCert);
 
+            CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
 			CmsSignedData sd = gen.Generate(msg, true);
 
-			x509Certs = sd.GetCertificates("Collection");
-			ArrayList a = new ArrayList(x509Certs.GetMatches(null));
+            x509Certs = sd.GetCertificates("Collection");
+            ArrayList a = new ArrayList(x509Certs.GetMatches(null));
 
-			Assert.AreEqual(3, a.Count);
+            Assert.AreEqual(3, a.Count);
 			Assert.AreEqual(SignCert, a[0]);
 			Assert.AreEqual(SignDsaCert, a[1]);
 			Assert.AreEqual(OrigCert, a[2]);
@@ -1330,36 +1158,26 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestSignerStoreReplacement()
 		{
-			IList certList = new ArrayList();
 			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
 
-			certList.Add(OrigCert);
-			certList.Add(SignCert);
-
-			IX509Store x509Certs = X509StoreFactory.Create(
-				"Certificate/Collection",
-				new X509CollectionStoreParameters(certList));
-
-			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+            IX509Store x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
 
+            CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
-
 			gen.AddCertificates(x509Certs);
 
-			CmsSignedData original = gen.Generate(msg, true);
+            CmsSignedData original = gen.Generate(msg, true);
 
-			//
+            //
 			// create new Signer
 			//
 			gen = new CmsSignedDataGenerator();
-
 			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha224);
-
 			gen.AddCertificates(x509Certs);
 
-			CmsSignedData newSD = gen.Generate(msg, true);
+            CmsSignedData newSD = gen.Generate(msg, true);
 
-			//
+            //
 			// replace signer
 			//
 			CmsSignedData sd = CmsSignedData.ReplaceSigners(original, newSD.GetSignerInfos());
@@ -1382,17 +1200,17 @@ namespace Org.BouncyCastle.Cms.Tests
 		[Test]
 		public void TestEncapsulatedSamples()
 		{
-			doTestSample("PSSSignDataSHA1Enc.sig");
-			doTestSample("PSSSignDataSHA256Enc.sig");
-			doTestSample("PSSSignDataSHA512Enc.sig");
+			DoTestSample("PSSSignDataSHA1Enc.sig");
+			DoTestSample("PSSSignDataSHA256Enc.sig");
+			DoTestSample("PSSSignDataSHA512Enc.sig");
 		}
 
 		[Test]
 		public void TestSamples()
 		{
-			doTestSample("PSSSignData.data", "PSSSignDataSHA1.sig");
-			doTestSample("PSSSignData.data", "PSSSignDataSHA256.sig");
-			doTestSample("PSSSignData.data", "PSSSignDataSHA512.sig");
+			DoTestSample("PSSSignData.data", "PSSSignDataSHA1.sig");
+			DoTestSample("PSSSignData.data", "PSSSignDataSHA256.sig");
+			DoTestSample("PSSSignData.data", "PSSSignDataSHA512.sig");
 		}
 
 		[Test]
@@ -1421,31 +1239,27 @@ namespace Org.BouncyCastle.Cms.Tests
 			VerifySignatures(sig);
 		}
 
-		private void doTestSample(
-			string sigName)
+		private void DoTestSample(string sigName)
 		{
 			CmsSignedData sig = new CmsSignedData(GetInput(sigName));
 			VerifySignatures(sig);
 		}
 
-		private void doTestSample(
-			string	messageName,
-			string	sigName)
+        private void DoTestSample(string messageName, string sigName)
 		{
 			CmsSignedData sig = new CmsSignedData(
 				new CmsProcessableByteArray(GetInput(messageName)),
 				GetInput(sigName));
 
-			VerifySignatures(sig);
+            VerifySignatures(sig);
 		}
 
-		private byte[] GetInput(
-			string name)
+        private byte[] GetInput(string name)
 		{
 			return Streams.ReadAll(SimpleTest.GetTestDataAsStream("cms.sigs." + name));
 		}
 
-		[Test]
+        [Test]
 		public void TestForMultipleCounterSignatures()
 		{
 			CmsSignedData sd = new CmsSignedData(xtraCounterSig);
@@ -1476,5 +1290,5 @@ namespace Org.BouncyCastle.Cms.Tests
 				Assert.IsTrue(signer.Verify(cert));
 			}
 		}
-	}
+    }
 }
diff --git a/crypto/test/src/crypto/tls/test/ByteQueueStreamTest.cs b/crypto/test/src/crypto/tls/test/ByteQueueStreamTest.cs
new file mode 100644
index 000000000..1d68a5215
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/ByteQueueStreamTest.cs
@@ -0,0 +1,134 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    [TestFixture]
+    public class ByteQueueStreamTest
+    {
+        [Test]
+        public void TestAvailable()
+        {
+            ByteQueueStream input = new ByteQueueStream();
+
+            // buffer is empty
+            Assert.AreEqual(0, input.Available);
+
+            // after adding once
+            input.Write(new byte[10]);
+            Assert.AreEqual(10, input.Available);
+
+            // after adding more than once
+            input.Write(new byte[5]);
+            Assert.AreEqual(15, input.Available);
+
+            // after reading a single byte
+            input.ReadByte();
+            Assert.AreEqual(14, input.Available);
+
+            // after reading into a byte array
+            input.Read(new byte[4]);
+            Assert.AreEqual(10, input.Available);
+
+            input.Close(); // so compiler doesn't whine about a resource leak
+        }
+
+        [Test]
+        public void TestSkip()
+        {
+            ByteQueueStream input = new ByteQueueStream();
+
+            // skip when buffer is empty
+            Assert.AreEqual(0, input.Skip(10));
+
+            // skip equal to available
+            input.Write(new byte[2]);
+            Assert.AreEqual(2, input.Skip(2));
+            Assert.AreEqual(0, input.Available);
+
+            // skip less than available
+            input.Write(new byte[10]);
+            Assert.AreEqual(5, input.Skip(5));
+            Assert.AreEqual(5, input.Available);
+
+            // skip more than available
+            Assert.AreEqual(5, input.Skip(20));
+            Assert.AreEqual(0, input.Available);
+
+            input.Close();// so compiler doesn't whine about a resource leak
+        }
+
+        [Test]
+        public void TestRead()
+        {
+            ByteQueueStream input = new ByteQueueStream();
+            input.Write(new byte[] { 0x01, 0x02 });
+            input.Write(new byte[]{ 0x03 });
+
+            Assert.AreEqual(0x01, input.ReadByte());
+            Assert.AreEqual(0x02, input.ReadByte());
+            Assert.AreEqual(0x03, input.ReadByte());
+            Assert.AreEqual(-1, input.ReadByte());
+
+            input.Close(); // so compiler doesn't whine about a resource leak
+        }
+
+        [Test]
+        public void TestReadArray()
+        {
+            ByteQueueStream input = new ByteQueueStream();
+            input.Write(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 });
+
+            byte[] buffer = new byte[5];
+
+            // read less than available into specified position
+            Assert.AreEqual(1, input.Read(buffer, 2, 1));
+            AssertArrayEquals(new byte[]{ 0x00, 0x00, 0x01, 0x00, 0x00 }, buffer);
+
+            // read equal to available
+            Assert.AreEqual(5, input.Read(buffer));
+            AssertArrayEquals(new byte[]{ 0x02, 0x03, 0x04, 0x05, 0x06 }, buffer);
+
+            // read more than available
+            input.Write(new byte[]{ 0x01, 0x02, 0x03 });
+            Assert.AreEqual(3, input.Read(buffer));
+            AssertArrayEquals(new byte[]{ 0x01, 0x02, 0x03, 0x05, 0x06 }, buffer);
+
+            input.Close(); // so compiler doesn't whine about a resource leak
+        }
+
+        [Test]
+        public void TestPeek()
+        {
+            ByteQueueStream input = new ByteQueueStream();
+
+            byte[] buffer = new byte[5];
+
+            // peek more than available
+            Assert.AreEqual(0, input.Peek(buffer));
+            AssertArrayEquals(new byte[]{ 0x00, 0x00, 0x00, 0x00, 0x00 }, buffer);
+
+            // peek less than available
+            input.Write(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 });
+            Assert.AreEqual(5, input.Peek(buffer));
+            AssertArrayEquals(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05 }, buffer);
+            Assert.AreEqual(6, input.Available);
+
+            // peek equal to available
+            input.ReadByte();
+            Assert.AreEqual(5, input.Peek(buffer));
+            AssertArrayEquals(new byte[]{ 0x02, 0x03, 0x04, 0x05, 0x06 }, buffer);
+            Assert.AreEqual(5, input.Available);
+
+            input.Close(); // so compiler doesn't whine about a resource leak
+        }
+
+        private static void AssertArrayEquals(byte[] a, byte[] b)
+        {
+            Assert.IsTrue(Arrays.AreEqual(a, b));
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsProtocolNonBlockingTest.cs b/crypto/test/src/crypto/tls/test/TlsProtocolNonBlockingTest.cs
new file mode 100644
index 000000000..5fe0f32ad
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/TlsProtocolNonBlockingTest.cs
@@ -0,0 +1,126 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    [TestFixture]
+    public class TlsProtocolNonBlockingTest
+    {
+        [Test]
+        public void TestClientServerFragmented()
+        {
+            // tests if it's really non-blocking when partial records arrive
+            DoTestClientServer(true);
+        }
+
+        [Test]
+        public void TestClientServerNonFragmented()
+        {
+            DoTestClientServer(false);
+        }
+
+        private static void DoTestClientServer(bool fragment)
+        {
+            SecureRandom secureRandom = new SecureRandom();
+
+            TlsClientProtocol clientProtocol = new TlsClientProtocol(secureRandom);
+            TlsServerProtocol serverProtocol = new TlsServerProtocol(secureRandom);
+
+            clientProtocol.Connect(new MockTlsClient(null));
+            serverProtocol.Accept(new MockTlsServer());
+
+            // pump handshake
+            bool hadDataFromServer = true;
+            bool hadDataFromClient = true;
+            while (hadDataFromServer || hadDataFromClient)
+            {
+                hadDataFromServer = PumpData(serverProtocol, clientProtocol, fragment);
+                hadDataFromClient = PumpData(clientProtocol, serverProtocol, fragment);
+            }
+
+            // send data in both directions
+            byte[] data = new byte[1024];
+            secureRandom.NextBytes(data);
+            WriteAndRead(clientProtocol, serverProtocol, data, fragment);
+            WriteAndRead(serverProtocol, clientProtocol, data, fragment);
+
+            // close the connection
+            clientProtocol.Close();
+            PumpData(clientProtocol, serverProtocol, fragment);
+            CheckClosed(serverProtocol);
+            CheckClosed(clientProtocol);
+        }
+
+        private static void WriteAndRead(TlsProtocol writer, TlsProtocol reader, byte[] data, bool fragment)
+        {
+            int dataSize = data.Length;
+            writer.OfferOutput(data, 0, dataSize);
+            PumpData(writer, reader, fragment);
+
+            Assert.AreEqual(dataSize, reader.GetAvailableInputBytes());
+            byte[] readData = new byte[dataSize];
+            reader.ReadInput(readData, 0, dataSize);
+            AssertArrayEquals(data, readData);
+        }
+
+        private static bool PumpData(TlsProtocol from, TlsProtocol to, bool fragment)
+        {
+            int byteCount = from.GetAvailableOutputBytes();
+            if (byteCount == 0)
+            {
+                return false;
+            }
+
+            if (fragment)
+            {
+                while (from.GetAvailableOutputBytes() > 0)
+                {
+                    byte[] buffer = new byte[1];
+                    from.ReadOutput(buffer, 0, 1);
+                    to.OfferInput(buffer);
+                }
+            }
+            else
+            {
+                byte[] buffer = new byte[byteCount];
+                from.ReadOutput(buffer, 0, buffer.Length);
+                to.OfferInput(buffer);
+            }
+
+            return true;
+        }
+
+        private static void CheckClosed(TlsProtocol protocol)
+        {
+            Assert.IsTrue(protocol.IsClosed);
+
+            try
+            {
+                protocol.OfferInput(new byte[10]);
+                Assert.Fail("Input was accepted after close");
+            }
+            catch (IOException e)
+            {
+            }
+
+            try
+            {
+                protocol.OfferOutput(new byte[10], 0, 10);
+                Assert.Fail("Output was accepted after close");
+            }
+            catch (IOException e)
+            {
+            }
+        }
+
+        private static void AssertArrayEquals(byte[] a, byte[] b)
+        {
+            Assert.IsTrue(Arrays.AreEqual(a, b));
+        }
+    }
+}