summary refs log tree commit diff
path: root/crypto/test/src
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2015-03-07 23:18:28 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2015-03-07 23:18:28 +0700
commitcc3e0bb5dc165f33eabfe3f1d1f88aaff4471c5f (patch)
tree14f913ea1c3f11683ea0acf2c34a95f6a5a30afe /crypto/test/src
parentVarious updates from Java build (diff)
downloadBouncyCastle.NET-ed25519-cc3e0bb5dc165f33eabfe3f1d1f88aaff4471c5f.tar.xz
Port of some of the TLS tests from Java
Diffstat (limited to 'crypto/test/src')
-rw-r--r--crypto/test/src/crypto/tls/test/PipedStream.cs134
-rw-r--r--crypto/test/src/crypto/tls/test/TlsProtocolTest.cs80
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestUtilities.cs29
-rw-r--r--crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs84
4 files changed, 327 insertions, 0 deletions
diff --git a/crypto/test/src/crypto/tls/test/PipedStream.cs b/crypto/test/src/crypto/tls/test/PipedStream.cs
new file mode 100644
index 000000000..6b2c15059
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/PipedStream.cs
@@ -0,0 +1,134 @@
+using System;
+using System.IO;
+using System.Threading;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class PipedStream
+        :   Stream
+    {
+        private readonly MemoryStream mBuf = new MemoryStream();
+        private bool mClosed = false;
+
+        private PipedStream mOther = null;
+        private long mReadPos = 0;
+
+        internal PipedStream()
+        {
+        }
+
+        internal PipedStream(PipedStream other)
+        {
+            lock (other)
+            {
+                this.mOther = other;
+                other.mOther = this;
+            }
+        }
+
+        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()
+        {
+            lock (this)
+            {
+                mClosed = true;
+                Monitor.PulseAll(this);
+            }
+        }
+
+        public override void Flush()
+        {
+        }
+
+        public override long Length
+        {
+            get { throw new NotImplementedException(); }
+        }
+
+        public override long Position
+        {
+            get { throw new NotImplementedException(); }
+            set { throw new NotImplementedException(); }
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void SetLength(long value)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            lock (mOther)
+            {
+                WaitForData();
+                int len = (int)System.Math.Min(count, mOther.mBuf.Position - mReadPos);
+                Array.Copy(mOther.mBuf.GetBuffer(), mReadPos, buffer, offset, len);
+                mReadPos += len;
+                return len;
+            }
+        }
+
+        public override int ReadByte()
+        {
+            lock (mOther)
+            {
+                WaitForData();
+                bool eof = (mReadPos >= mOther.mBuf.Position);
+                return eof ? -1 : mOther.mBuf.GetBuffer()[mReadPos++];
+            }
+        }
+
+        public override void Write(byte[] buf, int off, int len)
+        {
+            lock (this)
+            {
+                CheckOpen();
+                mBuf.Write(buf, off, len);
+                Monitor.PulseAll(this);
+            }
+        }
+
+        public override void WriteByte(byte value)
+        {
+            lock (this)
+            {
+                CheckOpen();
+                mBuf.WriteByte(value);
+                Monitor.PulseAll(mBuf);
+            }
+        }
+
+        private void CheckOpen()
+        {
+            if (mClosed)
+                throw new ObjectDisposedException(this.GetType().Name);
+        }
+
+        private void WaitForData()
+        {
+            while (mReadPos >= mOther.mBuf.Position && !mOther.mClosed)
+            {
+                Monitor.Wait(mOther);
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs b/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs
new file mode 100644
index 000000000..4c49420c6
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs
@@ -0,0 +1,80 @@
+using System;
+using System.IO;
+using System.Threading;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    [TestFixture]
+    public class TlsProtocolTest
+    {
+        [Test]
+        public void TestClientServer()
+        {
+            SecureRandom secureRandom = new SecureRandom();
+
+            PipedStream clientPipe = new PipedStream();
+            PipedStream serverPipe = new PipedStream(clientPipe);
+
+            TlsClientProtocol clientProtocol = new TlsClientProtocol(clientPipe, secureRandom);
+            TlsServerProtocol serverProtocol = new TlsServerProtocol(serverPipe, secureRandom);
+
+            Server server = new Server(serverProtocol);
+
+            Thread serverThread = new Thread(server.Run);
+            serverThread.Start();
+
+            MockTlsClient client = new MockTlsClient(null);
+            clientProtocol.Connect(client);
+
+            // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity
+            int length = 1000;
+
+            byte[] data = new byte[length];
+            secureRandom.NextBytes(data);
+
+            Stream output = clientProtocol.Stream;
+            output.Write(data, 0, data.Length);
+
+            byte[] echo = new byte[data.Length];
+            int count = Streams.ReadFully(clientProtocol.Stream, echo);
+
+            Assert.AreEqual(count, data.Length);
+            Assert.IsTrue(Arrays.AreEqual(data, echo));
+
+            output.Close();
+
+            serverThread.Join();
+        }
+
+        internal class Server
+        {
+            private readonly TlsServerProtocol mServerProtocol;
+
+            internal Server(TlsServerProtocol serverProtocol)
+            {
+                this.mServerProtocol = serverProtocol;
+            }
+
+            public void Run()
+            {
+                try
+                {
+                    MockTlsServer server = new MockTlsServer();
+                    mServerProtocol.Accept(server);
+                    Streams.PipeAll(mServerProtocol.Stream, mServerProtocol.Stream);
+                    mServerProtocol.Close();
+                }
+                catch (Exception)
+                {
+                    //throw new RuntimeException(e);
+                }
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs b/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs
index 272dfd4fd..a76858ce6 100644
--- a/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs
+++ b/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections;
 using System.Globalization;
 using System.IO;
 using System.Text;
@@ -89,6 +90,34 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
             return new DefaultTlsSignerCredentials(context, certificate, privateKey, signatureAndHashAlgorithm);
         }
 
+        internal static TlsSignerCredentials LoadSignerCredentials(TlsContext context, IList supportedSignatureAlgorithms,
+            byte signatureAlgorithm, string certResource, string keyResource)
+        {
+            /*
+             * TODO Note that this code fails to provide default value for the client supported
+             * algorithms if it wasn't sent.
+             */
+
+            SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
+            if (supportedSignatureAlgorithms != null)
+            {
+                foreach (SignatureAndHashAlgorithm alg in supportedSignatureAlgorithms)
+                {
+                    if (alg.Signature == signatureAlgorithm)
+                    {
+                        signatureAndHashAlgorithm = alg;
+                        break;
+                    }
+                }
+
+                if (signatureAndHashAlgorithm == null)
+                    return null;
+            }
+
+            return LoadSignerCredentials(context, new String[]{ certResource, "x509-ca.pem" },
+                keyResource, signatureAndHashAlgorithm);
+        }
+
         internal static Certificate LoadCertificateChain(string[] resources)
         {
             X509CertificateStructure[] chain = new X509CertificateStructure[resources.Length];
diff --git a/crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs b/crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs
new file mode 100644
index 000000000..b771ab7cf
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs
@@ -0,0 +1,84 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    public class UnreliableDatagramTransport
+        :   DatagramTransport
+    {
+        private readonly DatagramTransport transport;
+        private readonly Random random;
+        private readonly int percentPacketLossReceiving, percentPacketLossSending;
+
+        public UnreliableDatagramTransport(DatagramTransport transport, Random random,
+            int percentPacketLossReceiving, int percentPacketLossSending)
+        {
+            if (percentPacketLossReceiving < 0 || percentPacketLossReceiving > 100)
+                throw new ArgumentException("out of range", "percentPacketLossReceiving");
+            if (percentPacketLossSending < 0 || percentPacketLossSending > 100)
+                throw new ArgumentException("out of range", "percentPacketLossSending");
+
+            this.transport = transport;
+            this.random = random;
+            this.percentPacketLossReceiving = percentPacketLossReceiving;
+            this.percentPacketLossSending = percentPacketLossSending;
+        }
+
+        public virtual int GetReceiveLimit()
+        {
+            return transport.GetReceiveLimit();
+        }
+
+        public virtual int GetSendLimit()
+        {
+            return transport.GetSendLimit();
+        }
+
+        public virtual int Receive(byte[] buf, int off, int len, int waitMillis)
+        {
+            long endMillis = DateTimeUtilities.CurrentUnixMs() + waitMillis;
+            for (;;)
+            {
+                int length = transport.Receive(buf, off, len, waitMillis);
+                if (length < 0 || !LostPacket(percentPacketLossReceiving))
+                {
+                    return length;
+                }
+
+                Console.WriteLine("PACKET LOSS (" + length + " byte packet not received)");
+
+                long now = DateTimeUtilities.CurrentUnixMs();
+                if (now >= endMillis)
+                {
+                    return -1;
+                }
+
+                waitMillis = (int)(endMillis - now);
+            }
+        }
+
+        public virtual void Send(byte[] buf, int off, int len)
+        {
+            if (LostPacket(percentPacketLossSending))
+            {
+                Console.WriteLine("PACKET LOSS (" + len + " byte packet not sent)");
+            }
+            else
+            {
+                transport.Send(buf, off, len);
+            }
+        }
+
+        public virtual void Close()
+        {
+            transport.Close();
+        }
+
+        private bool LostPacket(int percentPacketLoss)
+        {
+            return percentPacketLoss > 0 && random.Next(100) < percentPacketLoss;
+        }
+    }
+}