diff --git a/tls-uses-pqc/Program.cs b/tls-uses-pqc/Program.cs new file mode 100644 index 0000000..5585079 --- /dev/null +++ b/tls-uses-pqc/Program.cs @@ -0,0 +1,76 @@ +// This test verifies that OpenSSL TLS uses PQC key exchange by default. +// It performs a standard TLS handshake and then checks that a PQC group was negotiated. + +using System.Net; +using System.Net.Security; +using System.Net.Sockets; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; + +// Create a self-signed certificate. +using var key = ECDsa.Create(); +var certReq = new CertificateRequest("CN=localhost", key, HashAlgorithmName.SHA256); +using var cert = certReq.CreateSelfSigned(DateTimeOffset.UtcNow.AddMinutes(-1), DateTimeOffset.UtcNow.AddYears(1)); + +// Set up a loopback TCP connection. +var listener = new TcpListener(IPAddress.Loopback, 0); +listener.Start(); +int port = ((IPEndPoint)listener.LocalEndpoint).Port; + +// Server side: accept and authenticate as TLS server. +var serverTask = Task.Run(async () => +{ + using var serverClient = await listener.AcceptTcpClientAsync(); + await using var serverSsl = new SslStream(serverClient.GetStream(), false); + await serverSsl.AuthenticateAsServerAsync(cert); + return GetNegotiatedGroupName(serverSsl); +}); + +// Client side: connect and authenticate as TLS client. +using var client = new TcpClient(); +await client.ConnectAsync(IPAddress.Loopback, port); +await using var clientSsl = new SslStream(client.GetStream(), false, (sender, certificate, chain, errors) => true /* accept cert */); +await clientSsl.AuthenticateAsClientAsync("localhost"); + +string? clientGroup = GetNegotiatedGroupName(clientSsl); +string? serverGroup = await serverTask; +listener.Stop(); + +Console.WriteLine($"Client negotiated group: {clientGroup}"); +Console.WriteLine($"Server negotiated group: {serverGroup}"); + +// Verify PQC was used: the group name should contain "MLKEM". +bool clientPqc = clientGroup != null && clientGroup.Contains("MLKEM", StringComparison.OrdinalIgnoreCase); +bool serverPqc = serverGroup != null && serverGroup.Contains("MLKEM", StringComparison.OrdinalIgnoreCase); + +if (clientPqc && serverPqc) +{ + Console.WriteLine("PASS: PQC key exchange negotiated."); + return 0; +} + +Console.WriteLine($"FAIL: Expected PQC key exchange group containing 'MLKEM', got client: '{clientGroup}', server: '{serverGroup}'"); +return 1; + +// Use OpenSSL interop to get the negotiated key exchange group (SslStream doesn't expose this information). +static string? GetNegotiatedGroupName(SslStream sslStream) +{ + var secCtxField = typeof(SslStream).GetField("_securityContext", BindingFlags.NonPublic | BindingFlags.Instance)!; + var safeSslHandle = (SafeHandle)secCtxField.GetValue(sslStream)!; + bool added = false; + safeSslHandle.DangerousAddRef(ref added); + try + { + IntPtr namePtr = SSL_get0_group_name(safeSslHandle.DangerousGetHandle()); + return namePtr == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(namePtr); + } + finally + { + if (added) safeSslHandle.DangerousRelease(); + } +} + +[DllImport("libssl.so.3")] +static extern IntPtr SSL_get0_group_name(IntPtr ssl); diff --git a/tls-uses-pqc/test.json b/tls-uses-pqc/test.json new file mode 100644 index 0000000..d19123e --- /dev/null +++ b/tls-uses-pqc/test.json @@ -0,0 +1,16 @@ +{ + "name": "tls-uses-pqc", + "enabled": true, + "requiresSdk": true, + "version": "10.0", + "versionSpecific": false, + "type": "bash", + "cleanup": true, + "ignoredRIDs":[ + "rhel.8", // no PQC key exchange support + "rhel.9", // no PQC key exchange support + "centos.8", // no PQC key exchange support + "centos.9", // no PQC key exchange support + "fedora.42" // no PQC key exchange support + ] +} diff --git a/tls-uses-pqc/test.sh b/tls-uses-pqc/test.sh new file mode 100755 index 0000000..7369d68 --- /dev/null +++ b/tls-uses-pqc/test.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -euo pipefail +IFS=$'\n\t' + +dotnet run diff --git a/tls-uses-pqc/tls-uses-pqc.csproj b/tls-uses-pqc/tls-uses-pqc.csproj new file mode 100644 index 0000000..305d8ad --- /dev/null +++ b/tls-uses-pqc/tls-uses-pqc.csproj @@ -0,0 +1,10 @@ + + + + Exe + $(TestTargetFramework) + enable + enable + + +