diff --git a/crypto/test/src/tls/test/MockRawKeysTlsClient.cs b/crypto/test/src/tls/test/MockRawKeysTlsClient.cs
new file mode 100644
index 000000000..594c4c94e
--- /dev/null
+++ b/crypto/test/src/tls/test/MockRawKeysTlsClient.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Collections.Generic;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Tls.Crypto;
+using Org.BouncyCastle.Tls.Crypto.Impl.BC;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Tls.Tests
+{
+ internal class MockRawKeysTlsClient
+ : DefaultTlsClient
+ {
+ private short m_serverCertType;
+ private short m_clientCertType;
+ private short[] m_offerServerCertTypes;
+ private short[] m_offerClientCertTypes;
+ private ProtocolVersion m_tlsVersion;
+ private Ed25519PrivateKeyParameters m_privateKey;
+
+ internal MockRawKeysTlsClient(short serverCertType, short clientCertType, short[] offerServerCertTypes,
+ short[] offerClientCertTypes, Ed25519PrivateKeyParameters privateKey, ProtocolVersion tlsVersion)
+ : base(new BcTlsCrypto(new SecureRandom()))
+ {
+ m_serverCertType = serverCertType;
+ m_clientCertType = clientCertType;
+ m_offerServerCertTypes = offerServerCertTypes;
+ m_offerClientCertTypes = offerClientCertTypes;
+ m_privateKey = privateKey;
+ m_tlsVersion = tlsVersion;
+ }
+
+ protected override ProtocolVersion[] GetSupportedVersions()
+ {
+ return new ProtocolVersion[]{ m_tlsVersion };
+ }
+
+ protected override int[] GetSupportedCipherSuites()
+ {
+ return TlsUtilities.IsTlsV13(m_tlsVersion)
+ ? new int[]{ CipherSuite.TLS_AES_128_GCM_SHA256 }
+ : new int[]{ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 };
+ }
+
+ protected override short[] GetAllowedClientCertificateTypes() => m_offerClientCertTypes;
+
+ protected override short[] GetAllowedServerCertificateTypes() => m_offerServerCertTypes;
+
+ protected override CertificateStatusRequest GetCertificateStatusRequest()
+ {
+ return m_serverCertType == CertificateType.RawPublicKey ? null : base.GetCertificateStatusRequest();
+ }
+
+ protected override IList<CertificateStatusRequestItemV2> GetMultiCertStatusRequest()
+ {
+ return m_serverCertType == CertificateType.RawPublicKey ? null : base.GetMultiCertStatusRequest();
+ }
+
+ public override TlsAuthentication GetAuthentication()
+ {
+ return new MyTlsAuthentication(this);
+ }
+
+ internal class MyTlsAuthentication
+ : TlsAuthentication
+ {
+ private readonly MockRawKeysTlsClient m_outer;
+ private TlsCredentialedSigner m_credentials;
+
+ internal MyTlsAuthentication(MockRawKeysTlsClient outer)
+ {
+ m_outer = outer;
+ }
+
+ public void NotifyServerCertificate(TlsServerCertificate serverCertificate)
+ {
+ Assert.AreEqual(m_outer.m_serverCertType, serverCertificate.Certificate.CertificateType,
+ "wrong certificate type from server");
+ }
+
+ public TlsCredentials GetClientCredentials(CertificateRequest certificateRequest)
+ {
+ var clientCertType = m_outer.m_clientCertType;
+ var context = m_outer.m_context;
+ var crypto = (BcTlsCrypto)m_outer.Crypto;
+ var privateKey = m_outer.m_privateKey;
+
+ if (clientCertType < 0)
+ {
+ Assert.Fail("should not have received a certificate request");
+ }
+
+ Assert.AreEqual(clientCertType, context.SecurityParameters.ClientCertificateType,
+ "wrong certificate type in request");
+
+ if (m_credentials == null)
+ {
+ switch (clientCertType)
+ {
+ case CertificateType.X509:
+ m_credentials = TlsTestUtilities.LoadSignerCredentials(context,
+ certificateRequest.SupportedSignatureAlgorithms, SignatureAlgorithm.ed25519,
+ "x509-client-ed25519.pem", "x509-client-key-ed25519.pem");
+ break;
+ case CertificateType.RawPublicKey:
+ TlsCertificate rawKeyCert = new BcTlsRawKeyCertificate(crypto,
+ SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(privateKey.GeneratePublicKey()));
+ Certificate cert = new Certificate(CertificateType.RawPublicKey,
+ TlsUtilities.IsTlsV13(context) ? TlsUtilities.EmptyBytes : null,
+ new CertificateEntry[]{ new CertificateEntry(rawKeyCert, null) });
+ m_credentials = new BcDefaultTlsCredentialedSigner(new TlsCryptoParameters(context),
+ crypto, privateKey, cert, SignatureAndHashAlgorithm.ed25519);
+ break;
+ default:
+ throw new ArgumentException("Only supports X509 and raw keys");
+ }
+ }
+
+ return m_credentials;
+ }
+ };
+ }
+}
diff --git a/crypto/test/src/tls/test/MockRawKeysTlsServer.cs b/crypto/test/src/tls/test/MockRawKeysTlsServer.cs
new file mode 100644
index 000000000..e136c6571
--- /dev/null
+++ b/crypto/test/src/tls/test/MockRawKeysTlsServer.cs
@@ -0,0 +1,134 @@
+using System;
+using System.Collections.Generic;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Tls.Crypto;
+using Org.BouncyCastle.Tls.Crypto.Impl.BC;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Tls.Tests
+{
+ internal class MockRawKeysTlsServer
+ : DefaultTlsServer
+ {
+ private short m_serverCertType;
+ private short m_clientCertType;
+ private short[] m_allowedClientCertTypes;
+ private Ed25519PrivateKeyParameters m_privateKey;
+ private ProtocolVersion m_tlsVersion;
+ private TlsCredentialedSigner m_credentials;
+
+ internal IDictionary<int, byte[]> m_receivedClientExtensions;
+
+ internal MockRawKeysTlsServer(short serverCertType, short clientCertType, short[] allowedClientCertTypes,
+ Ed25519PrivateKeyParameters privateKey, ProtocolVersion tlsVersion)
+ : base(new BcTlsCrypto(new SecureRandom()))
+ {
+ m_serverCertType = serverCertType;
+ m_clientCertType = clientCertType;
+ m_allowedClientCertTypes = allowedClientCertTypes;
+ m_privateKey = privateKey;
+ m_tlsVersion = tlsVersion;
+ }
+
+ public override TlsCredentials GetCredentials()
+ {
+ /*
+ * TODO[tls13] Should really be finding the first client-supported signature scheme that the
+ * server also supports and has credentials for.
+ */
+ if (TlsUtilities.IsTlsV13(m_context))
+ return GetECDsaSignerCredentials();
+
+ return base.GetCredentials();
+ }
+
+ protected override ProtocolVersion[] GetSupportedVersions()
+ {
+ return new ProtocolVersion[]{ m_tlsVersion };
+ }
+
+ protected override int[] GetSupportedCipherSuites()
+ {
+ return TlsUtilities.IsTlsV13(m_tlsVersion)
+ ? new int[]{ CipherSuite.TLS_AES_128_GCM_SHA256 }
+ : new int[]{ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 };
+ }
+
+ public override void ProcessClientExtensions(IDictionary<int, byte[]> clientExtensions)
+ {
+ m_receivedClientExtensions = clientExtensions;
+
+ base.ProcessClientExtensions(clientExtensions);
+ }
+
+ protected override TlsCredentialedSigner GetECDsaSignerCredentials()
+ {
+ if (m_credentials == null)
+ {
+ var crypto = (BcTlsCrypto)Crypto;
+
+ switch (m_serverCertType)
+ {
+ case CertificateType.X509:
+ m_credentials = TlsTestUtilities.LoadSignerCredentials(m_context,
+ m_context.SecurityParameters.ClientSigAlgs, SignatureAlgorithm.ed25519,
+ "x509-client-ed25519.pem", "x509-client-key-ed25519.pem");
+ break;
+ case CertificateType.RawPublicKey:
+ TlsCertificate rawKeyCert = new BcTlsRawKeyCertificate(crypto,
+ SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(m_privateKey.GeneratePublicKey()));
+ Certificate cert = new Certificate(CertificateType.RawPublicKey,
+ TlsUtilities.IsTlsV13(m_context) ? TlsUtilities.EmptyBytes : null,
+ new CertificateEntry[]{ new CertificateEntry(rawKeyCert, null) });
+ m_credentials = new BcDefaultTlsCredentialedSigner(new TlsCryptoParameters(m_context),
+ crypto, m_privateKey, cert, SignatureAndHashAlgorithm.ed25519);
+ break;
+ default:
+ throw new ArgumentException("Only supports X509 and raw keys");
+ }
+ }
+
+ return m_credentials;
+ }
+
+ protected override short[] GetAllowedClientCertificateTypes() => m_allowedClientCertTypes;
+
+ protected override bool AllowCertificateStatus()
+ {
+ return m_serverCertType == CertificateType.RawPublicKey ? false : base.AllowCertificateStatus();
+ }
+
+ protected override bool AllowMultiCertStatus()
+ {
+ return m_serverCertType == CertificateType.RawPublicKey ? false : base.AllowMultiCertStatus();
+ }
+
+ public override CertificateRequest GetCertificateRequest()
+ {
+ if (m_clientCertType < 0)
+ return null;
+
+ short[] certificateTypes = new short[]{ ClientCertificateType.ecdsa_sign };
+
+ IList<SignatureAndHashAlgorithm> serverSigAlgs = null;
+ if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(m_context.ServerVersion))
+ {
+ serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms(m_context);
+ }
+
+ return TlsUtilities.IsTlsV13(m_tlsVersion)
+ ? new CertificateRequest(TlsUtilities.EmptyBytes, serverSigAlgs, null, null)
+ : new CertificateRequest(certificateTypes, serverSigAlgs, null);
+ }
+
+ public override void NotifyClientCertificate(Certificate clientCertificate)
+ {
+ Assert.AreEqual(m_clientCertType, clientCertificate.CertificateType,
+ "client certificate is the wrong type");
+ }
+ }
+}
diff --git a/crypto/test/src/tls/test/TlsClientRawKeysTest.cs b/crypto/test/src/tls/test/TlsClientRawKeysTest.cs
new file mode 100644
index 000000000..510213fc7
--- /dev/null
+++ b/crypto/test/src/tls/test/TlsClientRawKeysTest.cs
@@ -0,0 +1,99 @@
+using System;
+using System.IO;
+using System.Net.Sockets;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Tls.Tests
+{
+ /// <summary>A simple test designed to conduct a TLS handshake with an external TLS server.</summary>
+ /// <remarks>
+ /// <code>
+ /// openssl genpkey -out ed25519.priv -algorithm ed25519
+ /// openssl pkey -in ed25519.priv -pubout -out ed25519.pub
+ ///
+ /// gnutls-serv --http --debug 10 --priority NORMAL:+CTYPE-CLI-RAWPK:+CTYPE-SRV-RAWPK --rawpkkeyfile ed25519.priv --rawpkfile ed25519.pub
+ /// </code>
+ /// </remarks>
+ [TestFixture]
+ public class TlsClientRawKeysTest
+ {
+ [Test, Explicit]
+ public void TestConnection()
+ {
+ string host = "localhost";
+ int port = 5556;
+
+ RunTest(host, port, ProtocolVersion.TLSv12);
+ RunTest(host, port, ProtocolVersion.TLSv13);
+ }
+
+ private static void RunTest(string host, int port, ProtocolVersion tlsVersion)
+ {
+ MockRawKeysTlsClient client = new MockRawKeysTlsClient(CertificateType.RawPublicKey,
+ CertificateType.RawPublicKey, new short[]{ CertificateType.RawPublicKey },
+ new short[]{ CertificateType.RawPublicKey }, new Ed25519PrivateKeyParameters(new SecureRandom()),
+ tlsVersion);
+ TlsClientProtocol protocol = OpenTlsClientConnection(host, port, client);
+
+ Http11Get(host, port, protocol.Stream);
+
+ protocol.Close();
+ }
+
+ private static void Http11Get(string host, int port, Stream s)
+ {
+ WriteUtf8Line(s, "GET / HTTP/1.1");
+ //WriteUtf8Line(s, "Host: " + host + ":" + port);
+ WriteUtf8Line(s, "");
+ s.Flush();
+
+ Console.WriteLine("---");
+
+ string[] ends = new string[] { "</HTML>", "HTTP/1.1 3", "HTTP/1.1 4" };
+
+ StreamReader reader = new StreamReader(s);
+
+ bool finished = false;
+ string line;
+ while (!finished && (line = reader.ReadLine()) != null)
+ {
+ Console.WriteLine("<<< " + line);
+
+ string upperLine = TlsTestUtilities.ToUpperInvariant(line);
+
+ // TEST CODE ONLY. This is not a robust way of parsing the result!
+ foreach (string end in ends)
+ {
+ if (upperLine.IndexOf(end) >= 0)
+ {
+ finished = true;
+ break;
+ }
+ }
+ }
+
+ Console.Out.Flush();
+ }
+
+ private static TlsClientProtocol OpenTlsClientConnection(string hostname, int port, TlsClient client)
+ {
+ TcpClient tcp = new TcpClient(hostname, port);
+
+ TlsClientProtocol protocol = new TlsClientProtocol(tcp.GetStream());
+ protocol.Connect(client);
+ return protocol;
+ }
+
+ private static void WriteUtf8Line(Stream output, string line)
+ {
+ byte[] buf = Encoding.UTF8.GetBytes(line + "\r\n");
+ output.Write(buf, 0, buf.Length);
+ Console.WriteLine(">>> " + line);
+ }
+ }
+}
diff --git a/crypto/test/src/tls/test/TlsRawKeysProtocolTest.cs b/crypto/test/src/tls/test/TlsRawKeysProtocolTest.cs
new file mode 100644
index 000000000..976df4009
--- /dev/null
+++ b/crypto/test/src/tls/test/TlsRawKeysProtocolTest.cs
@@ -0,0 +1,282 @@
+using System;
+using System.IO;
+using System.Threading;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Tls.Tests
+{
+ [TestFixture]
+ public class TlsRawKeysProtocolTest
+ {
+ private readonly SecureRandom Random = new SecureRandom();
+
+ [Test]
+ public void TestClientSendsExtensionButServerDoesNotSupportIt()
+ {
+ TestClientSendsExtensionButServerDoesNotSupportIt(ProtocolVersion.TLSv12);
+ }
+
+ [Test]
+ public void TestClientSendsExtensionButServerDoesNotSupportIt_13()
+ {
+ TestClientSendsExtensionButServerDoesNotSupportIt(ProtocolVersion.TLSv13);
+ }
+
+ private void TestClientSendsExtensionButServerDoesNotSupportIt(ProtocolVersion tlsVersion)
+ {
+ MockRawKeysTlsClient client = new MockRawKeysTlsClient(CertificateType.X509, -1,
+ new short[]{ CertificateType.RawPublicKey, CertificateType.X509 }, null, GenerateKeyPair(),
+ tlsVersion);
+ MockRawKeysTlsServer server = new MockRawKeysTlsServer(CertificateType.X509, -1, null, GenerateKeyPair(),
+ tlsVersion);
+ PumpData(client, server);
+ }
+
+ [Test]
+ public void TestExtensionsAreOmittedIfSpecifiedButOnlyContainX509()
+ {
+ TestExtensionsAreOmittedIfSpecifiedButOnlyContainX509(ProtocolVersion.TLSv12);
+ }
+
+ [Test]
+ public void TestExtensionsAreOmittedIfSpecifiedButOnlyContainX509_13()
+ {
+ TestExtensionsAreOmittedIfSpecifiedButOnlyContainX509(ProtocolVersion.TLSv13);
+ }
+
+ private void TestExtensionsAreOmittedIfSpecifiedButOnlyContainX509(ProtocolVersion tlsVersion)
+ {
+ MockRawKeysTlsClient client = new MockRawKeysTlsClient(CertificateType.X509, CertificateType.X509,
+ new short[]{ CertificateType.X509 }, new short[]{ CertificateType.X509 }, GenerateKeyPair(),
+ tlsVersion);
+ MockRawKeysTlsServer server = new MockRawKeysTlsServer(CertificateType.X509, CertificateType.X509,
+ new short[]{ CertificateType.X509 }, GenerateKeyPair(), tlsVersion);
+ PumpData(client, server);
+
+ Assert.IsFalse(server.m_receivedClientExtensions.ContainsKey(ExtensionType.client_certificate_type),
+ "client cert type extension should not be sent");
+ Assert.IsFalse(server.m_receivedClientExtensions.ContainsKey(ExtensionType.server_certificate_type),
+ "server cert type extension should not be sent");
+ }
+
+ [Test]
+ public void TestBothSidesUseRawKey()
+ {
+ TestBothSidesUseRawKey(ProtocolVersion.TLSv12);
+ }
+
+ [Test]
+ public void TestBothSidesUseRawKey_13()
+ {
+ TestBothSidesUseRawKey(ProtocolVersion.TLSv13);
+ }
+
+ private void TestBothSidesUseRawKey(ProtocolVersion tlsVersion)
+ {
+ MockRawKeysTlsClient client = new MockRawKeysTlsClient(CertificateType.RawPublicKey,
+ CertificateType.RawPublicKey, new short[]{ CertificateType.RawPublicKey },
+ new short[]{ CertificateType.RawPublicKey }, GenerateKeyPair(), tlsVersion);
+ MockRawKeysTlsServer server = new MockRawKeysTlsServer(CertificateType.RawPublicKey,
+ CertificateType.RawPublicKey, new short[]{ CertificateType.RawPublicKey }, GenerateKeyPair(),
+ tlsVersion);
+ PumpData(client, server);
+ }
+
+ [Test]
+ public void TestServerUsesRawKeyAndClientIsAnonymous()
+ {
+ TestServerUsesRawKeyAndClientIsAnonymous(ProtocolVersion.TLSv12);
+ }
+
+ [Test]
+ public void TestServerUsesRawKeyAndClientIsAnonymous_13()
+ {
+ TestServerUsesRawKeyAndClientIsAnonymous(ProtocolVersion.TLSv13);
+ }
+
+ private void TestServerUsesRawKeyAndClientIsAnonymous(ProtocolVersion tlsVersion)
+ {
+ MockRawKeysTlsClient client = new MockRawKeysTlsClient(CertificateType.RawPublicKey, -1,
+ new short[]{ CertificateType.RawPublicKey }, null, GenerateKeyPair(), tlsVersion);
+ MockRawKeysTlsServer server = new MockRawKeysTlsServer(CertificateType.RawPublicKey, -1, null,
+ GenerateKeyPair(), tlsVersion);
+ PumpData(client, server);
+ }
+
+ [Test]
+ public void TestServerUsesRawKeyAndClientUsesX509()
+ {
+ TestServerUsesRawKeyAndClientUsesX509(ProtocolVersion.TLSv12);
+ }
+
+ [Test]
+ public void TestServerUsesRawKeyAndClientUsesX509_13()
+ {
+ TestServerUsesRawKeyAndClientUsesX509(ProtocolVersion.TLSv13);
+ }
+
+ private void TestServerUsesRawKeyAndClientUsesX509(ProtocolVersion tlsVersion)
+ {
+ MockRawKeysTlsClient client = new MockRawKeysTlsClient(CertificateType.RawPublicKey,
+ CertificateType.X509, new short[]{ CertificateType.RawPublicKey }, null, GenerateKeyPair(),
+ tlsVersion);
+ MockRawKeysTlsServer server = new MockRawKeysTlsServer(CertificateType.RawPublicKey,
+ CertificateType.X509, null, GenerateKeyPair(), tlsVersion);
+ PumpData(client, server);
+ }
+
+ [Test]
+ public void TestServerUsesX509AndClientUsesRawKey()
+ {
+ TestServerUsesX509AndClientUsesRawKey(ProtocolVersion.TLSv12);
+ }
+
+ [Test]
+ public void TestServerUsesX509AndClientUsesRawKey_13()
+ {
+ TestServerUsesX509AndClientUsesRawKey(ProtocolVersion.TLSv13);
+ }
+
+ private void TestServerUsesX509AndClientUsesRawKey(ProtocolVersion tlsVersion)
+ {
+ MockRawKeysTlsClient client = new MockRawKeysTlsClient(CertificateType.X509, CertificateType.RawPublicKey,
+ null, new short[]{ CertificateType.RawPublicKey }, GenerateKeyPair(), tlsVersion);
+ MockRawKeysTlsServer server = new MockRawKeysTlsServer(CertificateType.X509, CertificateType.RawPublicKey,
+ new short[]{ CertificateType.RawPublicKey }, GenerateKeyPair(), tlsVersion);
+ PumpData(client, server);
+ }
+
+ [Test]
+ public void TestClientSendsClientCertExtensionButServerHasNoCommonTypes()
+ {
+ TestClientSendsClientCertExtensionButServerHasNoCommonTypes(ProtocolVersion.TLSv12);
+ }
+
+ [Test]
+ public void TestClientSendsClientCertExtensionButServerHasNoCommonTypes_13()
+ {
+ TestClientSendsClientCertExtensionButServerHasNoCommonTypes(ProtocolVersion.TLSv13);
+ }
+
+ private void TestClientSendsClientCertExtensionButServerHasNoCommonTypes(ProtocolVersion tlsVersion)
+ {
+ try
+ {
+ MockRawKeysTlsClient client = new MockRawKeysTlsClient(CertificateType.X509,
+ CertificateType.RawPublicKey, null, new short[]{ CertificateType.RawPublicKey }, GenerateKeyPair(),
+ tlsVersion);
+ MockRawKeysTlsServer server = new MockRawKeysTlsServer(CertificateType.X509, CertificateType.X509,
+ new short[]{ CertificateType.X509 }, GenerateKeyPair(), tlsVersion);
+ PumpData(client, server);
+ Assert.Fail("Should have caused unsupported_certificate alert");
+ }
+ catch (TlsFatalAlertReceived alert)
+ {
+ Assert.AreEqual(AlertDescription.unsupported_certificate, alert.AlertDescription,
+ "Should have caused unsupported_certificate alert");
+ }
+ }
+
+ [Test]
+ public void TestClientSendsServerCertExtensionButServerHasNoCommonTypes()
+ {
+ TestClientSendsServerCertExtensionButServerHasNoCommonTypes(ProtocolVersion.TLSv12);
+ }
+
+ [Test]
+ public void TestClientSendsServerCertExtensionButServerHasNoCommonTypes_13()
+ {
+ TestClientSendsServerCertExtensionButServerHasNoCommonTypes(ProtocolVersion.TLSv13);
+ }
+
+ private void TestClientSendsServerCertExtensionButServerHasNoCommonTypes(ProtocolVersion tlsVersion)
+ {
+ try
+ {
+ MockRawKeysTlsClient client = new MockRawKeysTlsClient(CertificateType.RawPublicKey,
+ CertificateType.RawPublicKey, new short[]{ CertificateType.RawPublicKey }, null, GenerateKeyPair(),
+ tlsVersion);
+ MockRawKeysTlsServer server = new MockRawKeysTlsServer(CertificateType.X509,
+ CertificateType.RawPublicKey, new short[]{ CertificateType.RawPublicKey }, GenerateKeyPair(),
+ tlsVersion);
+ PumpData(client, server);
+ Assert.Fail("Should have caused unsupported_certificate alert");
+ }
+ catch (TlsFatalAlertReceived alert)
+ {
+ Assert.AreEqual(AlertDescription.unsupported_certificate, alert.AlertDescription,
+ "Should have caused unsupported_certificate alert");
+ }
+ }
+
+ private Ed25519PrivateKeyParameters GenerateKeyPair()
+ {
+ return new Ed25519PrivateKeyParameters(Random);
+ }
+
+ private void PumpData(TlsClient client, TlsServer server)
+ {
+ PipedStream clientPipe = new PipedStream();
+ PipedStream serverPipe = new PipedStream(clientPipe);
+
+ TlsClientProtocol clientProtocol = new TlsClientProtocol(clientPipe);
+ TlsServerProtocol serverProtocol = new TlsServerProtocol(serverPipe);
+
+ Server serverRun = new Server(serverProtocol, server);
+ Thread serverThread = new Thread(new ThreadStart(serverRun.Run));
+ serverThread.Start();
+
+ 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];
+ Random.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 m_serverProtocol;
+ private readonly TlsServer m_server;
+
+ internal Server(TlsServerProtocol serverProtocol, TlsServer server)
+ {
+ m_serverProtocol = serverProtocol;
+ m_server = server;
+ }
+
+ public void Run()
+ {
+ try
+ {
+ m_serverProtocol.Accept(m_server);
+ Streams.PipeAll(m_serverProtocol.Stream, m_serverProtocol.Stream);
+ m_serverProtocol.Close();
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+ }
+}
diff --git a/crypto/test/src/tls/test/TlsServerRawKeysTest.cs b/crypto/test/src/tls/test/TlsServerRawKeysTest.cs
new file mode 100644
index 000000000..22e35505c
--- /dev/null
+++ b/crypto/test/src/tls/test/TlsServerRawKeysTest.cs
@@ -0,0 +1,90 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Tls.Tests
+{
+ /// <summary>A simple test designed to conduct a TLS handshake with an external TLS client.</summary>
+ /// <remarks>
+ /// <code>
+ /// gnutls-cli --rawpkkeyfile ed25519.priv --rawpkfile ed25519.pub --priority NORMAL:+CTYPE-CLI-RAWPK:+CTYPE-SRV-RAWPK --insecure --debug 10 --port 5556 localhost
+ /// </code>
+ /// </remarks>
+ [TestFixture]
+ public class TlsServerRawKeysTest
+ {
+ [Test, Explicit]
+ public void TestConnection()
+ {
+ int port = 5556;
+ ProtocolVersion[] tlsVersions = ProtocolVersion.TLSv13.DownTo(ProtocolVersion.TLSv12);
+
+ TcpListener ss = new TcpListener(IPAddress.Any, port);
+ ss.Start();
+ Stream stdout = Console.OpenStandardOutput();
+ try
+ {
+ foreach (var tlsVersion in tlsVersions)
+ {
+ TcpClient s = ss.AcceptTcpClient();
+ Console.WriteLine("--------------------------------------------------------------------------------");
+ Console.WriteLine("Accepted " + s);
+ Server serverRun = new Server(s, stdout, tlsVersion);
+ Thread t = new Thread(new ThreadStart(serverRun.Run));
+ t.Start();
+ }
+ }
+ finally
+ {
+ ss.Stop();
+ }
+ }
+
+ internal class Server
+ {
+ private readonly TcpClient s;
+ private readonly Stream stdout;
+ private readonly ProtocolVersion tlsVersion;
+
+ internal Server(TcpClient s, Stream stdout, ProtocolVersion tlsVersion)
+ {
+ this.s = s;
+ this.stdout = stdout;
+ this.tlsVersion = tlsVersion;
+ }
+
+ public void Run()
+ {
+ try
+ {
+ MockRawKeysTlsServer server = new MockRawKeysTlsServer(CertificateType.RawPublicKey,
+ CertificateType.RawPublicKey, new short[]{ CertificateType.RawPublicKey },
+ new Ed25519PrivateKeyParameters(new SecureRandom()), tlsVersion);
+ TlsServerProtocol serverProtocol = new TlsServerProtocol(s.GetStream());
+ serverProtocol.Accept(server);
+ Stream log = new TeeOutputStream(serverProtocol.Stream, stdout);
+ Streams.PipeAll(serverProtocol.Stream, log);
+ serverProtocol.Close();
+ }
+ finally
+ {
+ try
+ {
+ s.Close();
+ }
+ catch (IOException)
+ {
+ }
+ }
+ }
+ }
+ }
+}
|