diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2015-03-07 23:18:28 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2015-03-07 23:18:28 +0700 |
commit | cc3e0bb5dc165f33eabfe3f1d1f88aaff4471c5f (patch) | |
tree | 14f913ea1c3f11683ea0acf2c34a95f6a5a30afe | |
parent | Various updates from Java build (diff) | |
download | BouncyCastle.NET-ed25519-cc3e0bb5dc165f33eabfe3f1d1f88aaff4471c5f.tar.xz |
Port of some of the TLS tests from Java
-rw-r--r-- | crypto/crypto.csproj | 15 | ||||
-rw-r--r-- | crypto/test/src/crypto/tls/test/PipedStream.cs | 134 | ||||
-rw-r--r-- | crypto/test/src/crypto/tls/test/TlsProtocolTest.cs | 80 | ||||
-rw-r--r-- | crypto/test/src/crypto/tls/test/TlsTestUtilities.cs | 29 | ||||
-rw-r--r-- | crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs | 84 |
5 files changed, 342 insertions, 0 deletions
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 3f713e1c0..7b3dde612 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -11011,11 +11011,21 @@ BuildAction = "Compile" /> <File + RelPath = "test\src\crypto\tls\test\PipedStream.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\crypto\tls\test\TlsClientTest.cs" SubType = "Code" BuildAction = "Compile" /> <File + RelPath = "test\src\crypto\tls\test\TlsProtocolTest.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\crypto\tls\test\TlsServerTest.cs" SubType = "Code" BuildAction = "Compile" @@ -11026,6 +11036,11 @@ BuildAction = "Compile" /> <File + RelPath = "test\src\crypto\tls\test\UnreliableDatagramTransport.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\math\ec\test\AllTests.cs" SubType = "Code" BuildAction = "Compile" 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; + } + } +} |