diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index 9d185ade3..35474aebb 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -11088,6 +11088,21 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "test\src\crypto\tls\test\DtlsProtocolTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "test\src\crypto\tls\test\DtlsTestCase.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "test\src\crypto\tls\test\DtlsTestSuite.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "test\src\crypto\tls\test\LoggingDatagramTransport.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -11098,6 +11113,16 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "test\src\crypto\tls\test\MockDtlsClient.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "test\src\crypto\tls\test\MockDtlsServer.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "test\src\crypto\tls\test\MockPskTlsClient.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -11138,6 +11163,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "test\src\crypto\tls\test\PskTlsClientTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "test\src\crypto\tls\test\TlsClientTest.cs"
SubType = "Code"
BuildAction = "Compile"
diff --git a/crypto/src/crypto/tls/DtlsReliableHandshake.cs b/crypto/src/crypto/tls/DtlsReliableHandshake.cs
index bf9e61d03..8e4439e67 100644
--- a/crypto/src/crypto/tls/DtlsReliableHandshake.cs
+++ b/crypto/src/crypto/tls/DtlsReliableHandshake.cs
@@ -114,17 +114,17 @@ namespace Org.BouncyCastle.Crypto.Tls
{
for (; ; )
{
- int Received = mRecordLayer.Receive(buf, 0, receiveLimit, readTimeoutMillis);
- if (Received < 0)
+ int received = mRecordLayer.Receive(buf, 0, receiveLimit, readTimeoutMillis);
+ if (received < 0)
{
break;
}
- if (Received < 12)
+ if (received < 12)
{
continue;
}
int fragment_length = TlsUtilities.ReadUint24(buf, 9);
- if (Received != (fragment_length + 12))
+ if (received != (fragment_length + 12))
{
continue;
}
diff --git a/crypto/test/src/crypto/tls/test/DtlsProtocolTest.cs b/crypto/test/src/crypto/tls/test/DtlsProtocolTest.cs
new file mode 100644
index 000000000..bc99ccc63
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/DtlsProtocolTest.cs
@@ -0,0 +1,102 @@
+using System;
+using System.IO;
+using System.Threading;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+ [TestFixture]
+ public class DtlsProtocolTest
+ {
+ [Test]
+ public void TestClientServer()
+ {
+ SecureRandom secureRandom = new SecureRandom();
+
+ DtlsClientProtocol clientProtocol = new DtlsClientProtocol(secureRandom);
+ DtlsServerProtocol serverProtocol = new DtlsServerProtocol(secureRandom);
+
+ MockDatagramAssociation network = new MockDatagramAssociation(1500);
+
+ Server server = new Server(serverProtocol, network.Server);
+
+ Thread serverThread = new Thread(new ThreadStart(server.Run));
+ serverThread.Start();
+
+ DatagramTransport clientTransport = network.Client;
+
+ clientTransport = new UnreliableDatagramTransport(clientTransport, secureRandom, 0, 0);
+
+ clientTransport = new LoggingDatagramTransport(clientTransport, Console.Out);
+
+ MockDtlsClient client = new MockDtlsClient(null);
+
+ DtlsTransport dtlsClient = clientProtocol.Connect(client, clientTransport);
+
+ for (int i = 1; i <= 10; ++i)
+ {
+ byte[] data = new byte[i];
+ Arrays.Fill(data, (byte)i);
+ dtlsClient.Send(data, 0, data.Length);
+ }
+
+ byte[] buf = new byte[dtlsClient.GetReceiveLimit()];
+ while (dtlsClient.Receive(buf, 0, buf.Length, 100) >= 0)
+ {
+ }
+
+ dtlsClient.Close();
+
+ server.Shutdown(serverThread);
+ }
+
+ internal class Server
+ {
+ private readonly DtlsServerProtocol mServerProtocol;
+ private readonly DatagramTransport mServerTransport;
+ private volatile bool isShutdown = false;
+
+ internal Server(DtlsServerProtocol serverProtocol, DatagramTransport serverTransport)
+ {
+ this.mServerProtocol = serverProtocol;
+ this.mServerTransport = serverTransport;
+ }
+
+ public void Run()
+ {
+ try
+ {
+ MockDtlsServer server = new MockDtlsServer();
+ DtlsTransport dtlsServer = mServerProtocol.Accept(server, mServerTransport);
+ byte[] buf = new byte[dtlsServer.GetReceiveLimit()];
+ while (!isShutdown)
+ {
+ int length = dtlsServer.Receive(buf, 0, buf.Length, 1000);
+ if (length >= 0)
+ {
+ dtlsServer.Send(buf, 0, length);
+ }
+ }
+ dtlsServer.Close();
+ }
+ catch (Exception e)
+ {
+ Console.Error.WriteLine(e.StackTrace);
+ }
+ }
+
+ internal void Shutdown(Thread serverThread)
+ {
+ if (!isShutdown)
+ {
+ isShutdown = true;
+ serverThread.Join();
+ }
+ }
+ }
+ }
+}
diff --git a/crypto/test/src/crypto/tls/test/DtlsTestCase.cs b/crypto/test/src/crypto/tls/test/DtlsTestCase.cs
new file mode 100644
index 000000000..d4af04fac
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/DtlsTestCase.cs
@@ -0,0 +1,153 @@
+using System;
+using System.IO;
+using System.Threading;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+ [TestFixture]
+ public class DtlsTestCase
+ {
+ private static void CheckDtlsVersion(ProtocolVersion version)
+ {
+ if (version != null && !version.IsDtls)
+ throw new InvalidOperationException("Non-DTLS version");
+ }
+
+ [Test, TestCaseSource(typeof(DtlsTestSuite), "Suite")]
+ public void RunTest(TlsTestConfig config)
+ {
+ CheckDtlsVersion(config.clientMinimumVersion);
+ CheckDtlsVersion(config.clientOfferVersion);
+ CheckDtlsVersion(config.serverMaximumVersion);
+ CheckDtlsVersion(config.serverMinimumVersion);
+
+ SecureRandom secureRandom = new SecureRandom();
+
+ DtlsClientProtocol clientProtocol = new DtlsClientProtocol(secureRandom);
+ DtlsServerProtocol serverProtocol = new DtlsServerProtocol(secureRandom);
+
+ MockDatagramAssociation network = new MockDatagramAssociation(1500);
+
+ TlsTestClientImpl clientImpl = new TlsTestClientImpl(config);
+ TlsTestServerImpl serverImpl = new TlsTestServerImpl(config);
+
+ Server server = new Server(this, serverProtocol, network.Server, serverImpl);
+
+ Thread serverThread = new Thread(new ThreadStart(server.Run));
+ serverThread.Start();
+
+ Exception caught = null;
+ try
+ {
+ DatagramTransport clientTransport = network.Client;
+
+ if (TlsTestConfig.DEBUG)
+ {
+ clientTransport = new LoggingDatagramTransport(clientTransport, Console.Out);
+ }
+
+ DtlsTransport dtlsClient = clientProtocol.Connect(clientImpl, clientTransport);
+
+ for (int i = 1; i <= 10; ++i)
+ {
+ byte[] data = new byte[i];
+ Arrays.Fill(data, (byte)i);
+ dtlsClient.Send(data, 0, data.Length);
+ }
+
+ byte[] buf = new byte[dtlsClient.GetReceiveLimit()];
+ while (dtlsClient.Receive(buf, 0, buf.Length, 100) >= 0)
+ {
+ }
+
+ dtlsClient.Close();
+ }
+ catch (Exception e)
+ {
+ caught = e;
+ LogException(caught);
+ }
+
+ server.Shutdown(serverThread);
+
+ // TODO Add checks that the various streams were closed
+
+ Assert.AreEqual(config.expectFatalAlertConnectionEnd, clientImpl.FirstFatalAlertConnectionEnd, "Client fatal alert connection end");
+ Assert.AreEqual(config.expectFatalAlertConnectionEnd, serverImpl.FirstFatalAlertConnectionEnd, "Server fatal alert connection end");
+
+ Assert.AreEqual(config.expectFatalAlertDescription, clientImpl.FirstFatalAlertDescription, "Client fatal alert description");
+ Assert.AreEqual(config.expectFatalAlertDescription, serverImpl.FirstFatalAlertDescription, "Server fatal alert description");
+
+ if (config.expectFatalAlertConnectionEnd == -1)
+ {
+ Assert.IsNull(caught, "Unexpected client exception");
+ Assert.IsNull(server.mCaught, "Unexpected server exception");
+ }
+ }
+
+ protected void LogException(Exception e)
+ {
+ if (TlsTestConfig.DEBUG)
+ {
+ Console.Error.WriteLine(e.StackTrace);
+ }
+ }
+
+ internal class Server
+ {
+ private readonly DtlsTestCase mOuter;
+ private readonly DtlsServerProtocol mServerProtocol;
+ private readonly DatagramTransport mServerTransport;
+ private readonly TlsTestServerImpl mServerImpl;
+
+ private volatile bool isShutdown = false;
+ internal Exception mCaught = null;
+
+ internal Server(DtlsTestCase outer, DtlsServerProtocol serverProtocol, DatagramTransport serverTransport, TlsTestServerImpl serverImpl)
+ {
+ this.mOuter = outer;
+ this.mServerProtocol = serverProtocol;
+ this.mServerTransport = serverTransport;
+ this.mServerImpl = serverImpl;
+ }
+
+ public void Run()
+ {
+ try
+ {
+ DtlsTransport dtlsServer = mServerProtocol.Accept(mServerImpl, mServerTransport);
+ byte[] buf = new byte[dtlsServer.GetReceiveLimit()];
+ while (!isShutdown)
+ {
+ int length = dtlsServer.Receive(buf, 0, buf.Length, 100);
+ if (length >= 0)
+ {
+ dtlsServer.Send(buf, 0, length);
+ }
+ }
+ dtlsServer.Close();
+ }
+ catch (Exception e)
+ {
+ mCaught = e;
+ mOuter.LogException(mCaught);
+ }
+ }
+
+ internal void Shutdown(Thread serverThread)
+ {
+ if (!isShutdown)
+ {
+ isShutdown = true;
+ serverThread.Interrupt();
+ serverThread.Join();
+ }
+ }
+ }
+ }
+}
diff --git a/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs
new file mode 100644
index 000000000..eb9d42e5f
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs
@@ -0,0 +1,134 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+ public class DtlsTestSuite
+ {
+ // Make the access to constants less verbose
+ internal class C : TlsTestConfig {}
+
+ public DtlsTestSuite()
+ {
+ }
+
+ public static IEnumerable Suite()
+ {
+ IList testSuite = new ArrayList();
+
+ AddFallbackTests(testSuite);
+ AddVersionTests(testSuite, ProtocolVersion.DTLSv10);
+ AddVersionTests(testSuite, ProtocolVersion.DTLSv12);
+
+ return testSuite;
+ }
+
+ private static void AddFallbackTests(IList testSuite)
+ {
+ {
+ TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12);
+ c.clientFallback = true;
+
+ testSuite.Add(new TestCaseData(c).SetName("FallbackGood"));
+ }
+
+ /*
+ * NOTE: Temporarily disabled automatic test runs because of problems getting a clean exit
+ * of the DTLS server after a fatal alert. As of writing, manual runs show the correct
+ * alerts being raised
+ */
+
+ //{
+ // TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12);
+ // c.clientOfferVersion = ProtocolVersion.DTLSv10;
+ // c.clientFallback = true;
+ // c.ExpectServerFatalAlert(AlertDescription.inappropriate_fallback);
+
+ // testSuite.Add(new TestCaseData(c).SetName("FallbackBad"));
+ //}
+
+ {
+ TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12);
+ c.clientOfferVersion = ProtocolVersion.DTLSv10;
+
+ testSuite.Add(new TestCaseData(c).SetName("FallbackNone"));
+ }
+ }
+
+ private static void AddVersionTests(IList testSuite, ProtocolVersion version)
+ {
+ string prefix = version.ToString()
+ .Replace(" ", "")
+ .Replace("\\", "")
+ .Replace(".", "")
+ + "_";
+
+ /*
+ * NOTE: Temporarily disabled automatic test runs because of problems getting a clean exit
+ * of the DTLS server after a fatal alert. As of writing, manual runs show the correct
+ * alerts being raised
+ */
+
+ //{
+ // TlsTestConfig c = CreateDtlsTestConfig(version);
+ // c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY;
+ // c.ExpectServerFatalAlert(AlertDescription.decrypt_error);
+
+ // testSuite.Add(new TestCaseData(c).SetName(prefix + "BadCertificateVerify"));
+ //}
+
+ //{
+ // TlsTestConfig c = CreateDtlsTestConfig(version);
+ // c.clientAuth = C.CLIENT_AUTH_INVALID_CERT;
+ // c.ExpectServerFatalAlert(AlertDescription.bad_certificate);
+
+ // testSuite.Add(new TestCaseData(c).SetName(prefix + "BadClientCertificate"));
+ //}
+
+ //{
+ // TlsTestConfig c = CreateDtlsTestConfig(version);
+ // c.clientAuth = C.CLIENT_AUTH_NONE;
+ // c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY;
+ // c.ExpectServerFatalAlert(AlertDescription.handshake_failure);
+
+ // testSuite.Add(new TestCaseData(c).SetName(prefix + "BadMandatoryCertReqDeclined"));
+ //}
+
+ {
+ TlsTestConfig c = CreateDtlsTestConfig(version);
+
+ testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodDefault"));
+ }
+
+ {
+ TlsTestConfig c = CreateDtlsTestConfig(version);
+ c.serverCertReq = C.SERVER_CERT_REQ_NONE;
+
+ testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodNoCertReq"));
+ }
+
+ {
+ TlsTestConfig c = CreateDtlsTestConfig(version);
+ c.clientAuth = C.CLIENT_AUTH_NONE;
+
+ testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodOptionalCertReqDeclined"));
+ }
+ }
+
+ private static TlsTestConfig CreateDtlsTestConfig(ProtocolVersion version)
+ {
+ TlsTestConfig c = new TlsTestConfig();
+ c.clientMinimumVersion = ProtocolVersion.DTLSv10;
+ /*
+ * TODO We'd like to just set the offer version to DTLSv12, but there is a known issue with
+ * overly-restrictive version checks b/w BC DTLS 1.2 client, BC DTLS 1.0 server
+ */
+ c.clientOfferVersion = version;
+ c.serverMaximumVersion = version;
+ c.serverMinimumVersion = ProtocolVersion.DTLSv10;
+ return c;
+ }
+ }
+}
diff --git a/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs b/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs
index 0391f4fef..48df36ca9 100644
--- a/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs
+++ b/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs
@@ -24,14 +24,14 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
this.server = new MockDatagramTransport(this, serverQueue, clientQueue);
}
- public DatagramTransport getClient()
+ public virtual DatagramTransport Client
{
- return client;
+ get { return client; }
}
- public DatagramTransport getServer()
+ public virtual DatagramTransport Server
{
- return server;
+ get { return server; }
}
private class MockDatagramTransport
@@ -64,8 +64,14 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
{
if (receiveQueue.Count < 1)
{
- Monitor.Wait(waitMillis);
-
+ try
+ {
+ Monitor.Wait(receiveQueue, waitMillis);
+ }
+ catch (ThreadInterruptedException)
+ {
+ // TODO Keep waiting until full wait expired?
+ }
if (receiveQueue.Count < 1)
{
return -1;
diff --git a/crypto/test/src/crypto/tls/test/MockDtlsClient.cs b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs
new file mode 100644
index 000000000..32491c425
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+ public class MockDtlsClient
+ : DefaultTlsClient
+ {
+ protected TlsSession mSession;
+
+ public MockDtlsClient(TlsSession session)
+ {
+ this.mSession = session;
+ }
+
+ public override TlsSession GetSessionToResume()
+ {
+ return this.mSession;
+ }
+
+ public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
+ {
+ TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+ output.WriteLine("DTLS client raised alert: " + AlertLevel.GetText(alertLevel)
+ + ", " + AlertDescription.GetText(alertDescription));
+ if (message != null)
+ {
+ output.WriteLine("> " + message);
+ }
+ if (cause != null)
+ {
+ output.WriteLine(cause);
+ }
+ }
+
+ public override void NotifyAlertReceived(byte alertLevel, byte alertDescription)
+ {
+ TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+ output.WriteLine("DTLS client received alert: " + AlertLevel.GetText(alertLevel)
+ + ", " + AlertDescription.GetText(alertDescription));
+ }
+
+ public override ProtocolVersion ClientVersion
+ {
+ get { return ProtocolVersion.DTLSv12; }
+ }
+
+ public override ProtocolVersion MinimumVersion
+ {
+ get { return ProtocolVersion.DTLSv10; }
+ }
+
+ //public override int[] GetCipherSuites()
+ //{
+ // return Arrays.Concatenate(base.GetCipherSuites(),
+ // new int[]
+ // {
+ // CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ // CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
+ // CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
+ // CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
+ // CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
+ // });
+ //}
+
+ public override IDictionary GetClientExtensions()
+ {
+ IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions());
+ TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions);
+ // TODO[draft-ietf-tls-session-hash-01] Enable once code-point assigned (only for compatible server though)
+ //TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions);
+ TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9);
+ TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions);
+ return clientExtensions;
+ }
+
+ public override void NotifyServerVersion(ProtocolVersion serverVersion)
+ {
+ base.NotifyServerVersion(serverVersion);
+
+ Console.WriteLine("Negotiated " + serverVersion);
+ }
+
+ public override TlsAuthentication GetAuthentication()
+ {
+ return new MyTlsAuthentication(mContext);
+ }
+
+ public override void NotifyHandshakeComplete()
+ {
+ base.NotifyHandshakeComplete();
+
+ TlsSession newSession = mContext.ResumableSession;
+ if (newSession != null)
+ {
+ byte[] newSessionID = newSession.SessionID;
+ string hex = Hex.ToHexString(newSessionID);
+
+ if (this.mSession != null && Arrays.AreEqual(this.mSession.SessionID, newSessionID))
+ {
+ Console.WriteLine("Resumed session: " + hex);
+ }
+ else
+ {
+ Console.WriteLine("Established session: " + hex);
+ }
+
+ this.mSession = newSession;
+ }
+ }
+
+ internal class MyTlsAuthentication
+ : TlsAuthentication
+ {
+ private readonly TlsContext mContext;
+
+ internal MyTlsAuthentication(TlsContext context)
+ {
+ this.mContext = context;
+ }
+
+ public virtual void NotifyServerCertificate(Certificate serverCertificate)
+ {
+ X509CertificateStructure[] chain = serverCertificate.GetCertificateList();
+ Console.WriteLine("DTLS client received server certificate chain of length " + chain.Length);
+ for (int i = 0; i != chain.Length; i++)
+ {
+ X509CertificateStructure entry = chain[i];
+ // TODO Create fingerprint based on certificate signature algorithm digest
+ Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+ + entry.Subject + ")");
+ }
+ }
+
+ public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest)
+ {
+ byte[] certificateTypes = certificateRequest.CertificateTypes;
+ if (certificateTypes == null || !Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign))
+ return null;
+
+ return TlsTestUtilities.LoadSignerCredentials(mContext, certificateRequest.SupportedSignatureAlgorithms,
+ SignatureAlgorithm.rsa, "x509-client.pem", "x509-client-key.pem");
+ }
+ };
+ }
+}
diff --git a/crypto/test/src/crypto/tls/test/MockDtlsServer.cs b/crypto/test/src/crypto/tls/test/MockDtlsServer.cs
new file mode 100644
index 000000000..19062181b
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/MockDtlsServer.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+ public class MockDtlsServer
+ : DefaultTlsServer
+ {
+ public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
+ {
+ TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+ output.WriteLine("DTLS server raised alert: " + AlertLevel.GetText(alertLevel)
+ + ", " + AlertDescription.GetText(alertDescription));
+ if (message != null)
+ {
+ output.WriteLine("> " + message);
+ }
+ if (cause != null)
+ {
+ output.WriteLine(cause);
+ }
+ }
+
+ public override void NotifyAlertReceived(byte alertLevel, byte alertDescription)
+ {
+ TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+ output.WriteLine("DTLS server received alert: " + AlertLevel.GetText(alertLevel)
+ + ", " + AlertDescription.GetText(alertDescription));
+ }
+
+ protected override int[] GetCipherSuites()
+ {
+ return Arrays.Concatenate(base.GetCipherSuites(),
+ new int[]
+ {
+ CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
+ CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
+ CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
+ CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
+ });
+ }
+
+ public override CertificateRequest GetCertificateRequest()
+ {
+ byte[] certificateTypes = new byte[]{ ClientCertificateType.rsa_sign,
+ ClientCertificateType.dss_sign, ClientCertificateType.ecdsa_sign };
+
+ IList serverSigAlgs = null;
+ if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mServerVersion))
+ {
+ serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms();
+ }
+
+ IList certificateAuthorities = new ArrayList();
+ certificateAuthorities.Add(TlsTestUtilities.LoadCertificateResource("x509-ca.pem").Subject);
+
+ return new CertificateRequest(certificateTypes, serverSigAlgs, certificateAuthorities);
+ }
+
+ public override void NotifyClientCertificate(Certificate clientCertificate)
+ {
+ X509CertificateStructure[] chain = clientCertificate.GetCertificateList();
+ Console.WriteLine("DTLS server received client certificate chain of length " + chain.Length);
+ for (int i = 0; i != chain.Length; i++)
+ {
+ X509CertificateStructure entry = chain[i];
+ // TODO Create fingerprint based on certificate signature algorithm digest
+ Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+ + entry.Subject + ")");
+ }
+ }
+
+ protected override ProtocolVersion MaximumVersion
+ {
+ get { return ProtocolVersion.DTLSv12; }
+ }
+
+ protected override ProtocolVersion MinimumVersion
+ {
+ get { return ProtocolVersion.DTLSv10; }
+ }
+
+ protected override TlsEncryptionCredentials GetRsaEncryptionCredentials()
+ {
+ return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[] { "x509-server.pem", "x509-ca.pem" },
+ "x509-server-key.pem");
+ }
+
+ protected override TlsSignerCredentials GetRsaSignerCredentials()
+ {
+ return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa,
+ "x509-server.pem", "x509-server-key.pem");
+ }
+ }
+}
diff --git a/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs b/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs
index a186a8b58..dfc0e93a0 100644
--- a/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs
+++ b/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs
@@ -122,7 +122,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
for (int i = 0; i != chain.Length; i++)
{
X509CertificateStructure entry = chain[i];
- // TODO Create Fingerprint based on certificate signature algorithm digest
+ // TODO Create fingerprint based on certificate signature algorithm digest
Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+ entry.Subject + ")");
}
diff --git a/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs b/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs
index 2b9549e82..8a6b9f496 100644
--- a/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs
+++ b/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs
@@ -110,7 +110,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
for (int i = 0; i != chain.Length; i++)
{
X509CertificateStructure entry = chain[i];
- // TODO Create Fingerprint based on certificate signature algorithm digest
+ // TODO Create fingerprint based on certificate signature algorithm digest
Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+ entry.Subject + ")");
}
diff --git a/crypto/test/src/crypto/tls/test/MockTlsClient.cs b/crypto/test/src/crypto/tls/test/MockTlsClient.cs
index dbeb3fe41..4d7c59afa 100644
--- a/crypto/test/src/crypto/tls/test/MockTlsClient.cs
+++ b/crypto/test/src/crypto/tls/test/MockTlsClient.cs
@@ -121,7 +121,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
for (int i = 0; i != chain.Length; i++)
{
X509CertificateStructure entry = chain[i];
- // TODO Create Fingerprint based on certificate signature algorithm digest
+ // TODO Create fingerprint based on certificate signature algorithm digest
Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+ entry.Subject + ")");
}
diff --git a/crypto/test/src/crypto/tls/test/PskTlsClientTest.cs b/crypto/test/src/crypto/tls/test/PskTlsClientTest.cs
new file mode 100644
index 000000000..7072c7105
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/PskTlsClientTest.cs
@@ -0,0 +1,79 @@
+using System;
+using System.IO;
+using System.Net.Sockets;
+using System.Text;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+ /**
+ * A simple test designed to conduct a TLS handshake with an external TLS server.
+ * <p>
+ * Please refer to GnuTLSSetup.html or OpenSSLSetup.html (under 'docs'), and x509-*.pem files in
+ * this package (under 'src/test/resources') for help configuring an external TLS server.
+ * </p><p>
+ * In both cases, extra options are required to enable PSK ciphersuites and configure identities/keys.
+ * </p>
+ */
+ public class PskTlsClientTest
+ {
+ private static readonly SecureRandom secureRandom = new SecureRandom();
+
+ public static void Main(string[] args)
+ {
+ string hostname = "localhost";
+ int port = 5556;
+
+ long time1 = DateTime.UtcNow.Ticks;
+
+ /*
+ * Note: This is the default PSK identity for 'openssl s_server' testing, the server must be
+ * started with "-psk 6161616161" to make the keys match, and possibly the "-psk_hint"
+ * option should be present.
+ */
+ string psk_identity = "Client_identity";
+ byte[] psk = new byte[]{ 0x61, 0x61, 0x61, 0x61, 0x61 };
+
+ BasicTlsPskIdentity pskIdentity = new BasicTlsPskIdentity(psk_identity, psk);
+
+ MockPskTlsClient client = new MockPskTlsClient(null, pskIdentity);
+ TlsClientProtocol protocol = OpenTlsConnection(hostname, port, client);
+ protocol.Close();
+
+ long time2 = DateTime.UtcNow.Ticks;
+ Console.WriteLine("Elapsed 1: " + (time2 - time1)/TimeSpan.TicksPerMillisecond + "ms");
+
+ client = new MockPskTlsClient(client.GetSessionToResume(), pskIdentity);
+ protocol = OpenTlsConnection(hostname, port, client);
+
+ long time3 = DateTime.UtcNow.Ticks;
+ Console.WriteLine("Elapsed 2: " + (time3 - time2)/TimeSpan.TicksPerMillisecond + "ms");
+
+ byte[] req = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\n\r\n");
+
+ Stream tlsStream = protocol.Stream;
+ tlsStream.Write(req, 0, req.Length);
+ tlsStream.Flush();
+
+ StreamReader reader = new StreamReader(tlsStream);
+
+ String line;
+ while ((line = reader.ReadLine()) != null)
+ {
+ Console.WriteLine(">>> " + line);
+ }
+
+ protocol.Close();
+ }
+
+ internal static TlsClientProtocol OpenTlsConnection(string hostname, int port, TlsClient client)
+ {
+ TcpClient tcp = new TcpClient(hostname, port);
+
+ TlsClientProtocol protocol = new TlsClientProtocol(tcp.GetStream(), secureRandom);
+ protocol.Connect(client);
+ return protocol;
+ }
+ }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsTestCase.cs b/crypto/test/src/crypto/tls/test/TlsTestCase.cs
index 8ac1c4ed2..4b0c12710 100644
--- a/crypto/test/src/crypto/tls/test/TlsTestCase.cs
+++ b/crypto/test/src/crypto/tls/test/TlsTestCase.cs
@@ -149,7 +149,13 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
{
while (!mCanExit)
{
- Monitor.Wait(this);
+ try
+ {
+ Monitor.Wait(this);
+ }
+ catch (ThreadInterruptedException)
+ {
+ }
}
}
}
|