Skip to content

Commit e7e088b

Browse files
committed
Expose TLS details for QUIC connection
1 parent 3aa1c33 commit e7e088b

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

src/libraries/System.Net.Quic/ref/System.Net.Quic.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,20 @@ public QuicClientConnectionOptions() { }
2323
public sealed partial class QuicConnection : System.IAsyncDisposable
2424
{
2525
internal QuicConnection() { }
26+
public System.Security.Authentication.CipherAlgorithmType CipherAlgorithm { get { throw null; } }
27+
public int CipherStrength { get { throw null; } }
28+
public System.Security.Authentication.HashAlgorithmType HashAlgorithm { get { throw null; } }
29+
public int HashStrength { get { throw null; } }
2630
public static bool IsSupported { get { throw null; } }
31+
public System.Security.Authentication.ExchangeAlgorithmType KeyExchangeAlgorithm { get { throw null; } }
32+
public int KeyExchangeStrength { get { throw null; } }
2733
public System.Net.IPEndPoint LocalEndPoint { get { throw null; } }
2834
public System.Net.Security.SslApplicationProtocol NegotiatedApplicationProtocol { get { throw null; } }
35+
[System.CLSCompliantAttribute(false)]
36+
public System.Net.Security.TlsCipherSuite NegotiatedCipherSuite { get { throw null; } }
2937
public System.Security.Cryptography.X509Certificates.X509Certificate? RemoteCertificate { get { throw null; } }
3038
public System.Net.IPEndPoint RemoteEndPoint { get { throw null; } }
39+
public System.Security.Authentication.SslProtocols SslProtocol { get { throw null; } }
3140
public string TargetHostName { get { throw null; } }
3241
public System.Threading.Tasks.ValueTask<System.Net.Quic.QuicStream> AcceptInboundStreamAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
3342
public System.Threading.Tasks.ValueTask CloseAsync(long errorCode, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
@@ -64,8 +73,8 @@ public sealed partial class QuicException : System.IO.IOException
6473
{
6574
public QuicException(System.Net.Quic.QuicError error, long? applicationErrorCode, string message) { }
6675
public long? ApplicationErrorCode { get { throw null; } }
67-
public long? TransportErrorCode { get { throw null; } }
6876
public System.Net.Quic.QuicError QuicError { get { throw null; } }
77+
public long? TransportErrorCode { get { throw null; } }
6978
}
7079
public sealed partial class QuicListener : System.IAsyncDisposable
7180
{

src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,18 @@
77
using System.Runtime.CompilerServices;
88
using System.Runtime.ExceptionServices;
99
using System.Runtime.InteropServices;
10+
using System.Security.Authentication;
1011
using System.Security.Cryptography.X509Certificates;
1112
using System.Threading;
1213
using System.Threading.Channels;
1314
using System.Threading.Tasks;
1415
using Microsoft.Quic;
1516
using static Microsoft.Quic.MsQuic;
17+
using static Microsoft.Quic.QUIC_CIPHER_ALGORITHM;
18+
using static Microsoft.Quic.QUIC_CIPHER_SUITE;
19+
using static Microsoft.Quic.QUIC_HASH_ALGORITHM;
20+
using static Microsoft.Quic.QUIC_KEY_EXCHANGE_ALGORITHM;
21+
using static Microsoft.Quic.QUIC_TLS_PROTOCOL_VERSION;
1622

1723
using CONNECTED_DATA = Microsoft.Quic.QUIC_CONNECTION_EVENT._Anonymous_e__Union._CONNECTED_e__Struct;
1824
using SHUTDOWN_INITIATED_BY_TRANSPORT_DATA = Microsoft.Quic.QUIC_CONNECTION_EVENT._Anonymous_e__Union._SHUTDOWN_INITIATED_BY_TRANSPORT_e__Struct;
@@ -180,6 +186,40 @@ public X509Certificate? RemoteCertificate
180186
}
181187
}
182188

189+
/// <summary>
190+
/// Gets the <see cref="SslProtocols" /> corresponding to the TLS version used during the connection handshake.
191+
/// </summary>
192+
public SslProtocols SslProtocol { get; private set; }
193+
194+
/// <summary>
195+
/// Gets the cipher suite which was negotiated for this connection.
196+
/// </summary>
197+
[CLSCompliant(false)]
198+
public TlsCipherSuite NegotiatedCipherSuite { get; private set; }
199+
200+
/// <summary>
201+
/// Gets a value that identifies the bulk encryption algorithm used by this connection.
202+
/// </summary>
203+
public CipherAlgorithmType CipherAlgorithm { get; private set; }
204+
205+
/// <summary>
206+
/// Gets a value that identifies the strength of the cipher algorithm used by this connection.
207+
/// </summary>
208+
public int CipherStrength { get; private set; }
209+
210+
//
211+
// defined in SslStream but we don't need it as QUIC uses AEAD which don't use the hash algorithm
212+
// from the cipher suite
213+
//
214+
public HashAlgorithmType HashAlgorithm { get; private set; }
215+
public int HashStrength { get; private set; }
216+
217+
//
218+
// based on SslConnectionInfo.Unix.cs it would return 0/None in all cases
219+
//
220+
public ExchangeAlgorithmType KeyExchangeAlgorithm { get; private set; }
221+
public int KeyExchangeStrength { get; private set; }
222+
183223
/// <summary>
184224
/// Final, negotiated application protocol.
185225
/// </summary>
@@ -467,6 +507,45 @@ private unsafe int HandleEventConnected(ref CONNECTED_DATA data)
467507
QuicAddr localAddress = MsQuicHelpers.GetMsQuicParameter<QuicAddr>(_handle, QUIC_PARAM_CONN_LOCAL_ADDRESS);
468508
_localEndPoint = MsQuicHelpers.QuicAddrToIPEndPoint(&localAddress);
469509

510+
QUIC_HANDSHAKE_INFO handshakeInfo = MsQuicHelpers.GetMsQuicParameter<QUIC_HANDSHAKE_INFO>(_handle, QUIC_PARAM_TLS_HANDSHAKE_INFO);
511+
512+
SslProtocol = handshakeInfo.TlsProtocolVersion switch
513+
{
514+
QUIC_TLS_PROTOCOL_VERSION.TLS_1_3 => SslProtocols.Tls13,
515+
_ => SslProtocols.None,
516+
};
517+
518+
CipherAlgorithm = handshakeInfo.CipherAlgorithm switch
519+
{
520+
QUIC_CIPHER_ALGORITHM.AES_128 => CipherAlgorithmType.Aes128,
521+
QUIC_CIPHER_ALGORITHM.AES_256 => CipherAlgorithmType.Aes256,
522+
QUIC_CIPHER_ALGORITHM.CHACHA20 => CipherAlgorithmType.None, // TODO: CipherAlgorithmType.ChaCha20,
523+
_ => CipherAlgorithmType.None,
524+
};
525+
CipherStrength = handshakeInfo.CipherStrength;
526+
527+
HashAlgorithm = handshakeInfo.Hash switch
528+
{
529+
QUIC_HASH_ALGORITHM.SHA_256 => HashAlgorithmType.Sha256,
530+
QUIC_HASH_ALGORITHM.SHA_384 => HashAlgorithmType.Sha384,
531+
_ => HashAlgorithmType.None,
532+
};
533+
HashStrength = handshakeInfo.HashStrength;
534+
535+
KeyExchangeAlgorithm = handshakeInfo.KeyExchangeAlgorithm switch
536+
{
537+
_ => ExchangeAlgorithmType.None,
538+
};
539+
KeyExchangeStrength = handshakeInfo.KeyExchangeStrength;
540+
541+
NegotiatedCipherSuite = handshakeInfo.CipherSuite switch
542+
{
543+
QUIC_CIPHER_SUITE.TLS_AES_128_GCM_SHA256 => TlsCipherSuite.TLS_AES_128_GCM_SHA256,
544+
QUIC_CIPHER_SUITE.TLS_AES_256_GCM_SHA384 => TlsCipherSuite.TLS_AES_256_GCM_SHA384,
545+
QUIC_CIPHER_SUITE.TLS_CHACHA20_POLY1305_SHA256 => TlsCipherSuite.TLS_CHACHA20_POLY1305_SHA256,
546+
_ => TlsCipherSuite.TLS_AES_128_GCM_SHA256,
547+
};
548+
470549
if (NetEventSource.Log.IsEnabled())
471550
{
472551
NetEventSource.Info(this, $"{this} Connection connected {LocalEndPoint} -> {RemoteEndPoint} for {_negotiatedApplicationProtocol} protocol");

0 commit comments

Comments
 (0)