@@ -35,35 +35,54 @@ private sealed class SafeSslContextCache : SafeHandleCache<SslContextCacheKey, S
3535
3636 internal readonly struct SslContextCacheKey : IEquatable < SslContextCacheKey >
3737 {
38+ private const int ThumbprintSize = 64 ; // SHA512 size
39+
3840 public readonly bool IsClient ;
39- public readonly byte [ ] ? CertificateThumbprint ;
41+ public readonly ReadOnlyMemory < byte > CertificateThumbprints ;
4042 public readonly SslProtocols SslProtocols ;
4143
42- public SslContextCacheKey ( bool isClient , SslProtocols sslProtocols , byte [ ] ? certificateThumbprint )
44+ public SslContextCacheKey ( bool isClient , SslProtocols sslProtocols , SslStreamCertificateContext ? certContext )
4345 {
4446 IsClient = isClient ;
4547 SslProtocols = sslProtocols ;
46- CertificateThumbprint = certificateThumbprint ;
48+
49+ CertificateThumbprints = ReadOnlyMemory < byte > . Empty ;
50+
51+ if ( certContext != null )
52+ {
53+ int certCount = 1 + certContext . IntermediateCertificates . Count ;
54+ byte [ ] certificateThumbprints = new byte [ certCount * ThumbprintSize ] ;
55+
56+ bool success = certContext . TargetCertificate . TryGetCertHash ( HashAlgorithmName . SHA512 , certificateThumbprints . AsSpan ( 0 , ThumbprintSize ) , out _ ) ;
57+ Debug . Assert ( success ) ;
58+
59+ certCount = 1 ;
60+ foreach ( X509Certificate2 intermediate in certContext . IntermediateCertificates )
61+ {
62+ success = intermediate . TryGetCertHash ( HashAlgorithmName . SHA512 , certificateThumbprints . AsSpan ( certCount * ThumbprintSize , ThumbprintSize ) , out _ ) ;
63+ Debug . Assert ( success ) ;
64+ certCount ++ ;
65+ }
66+
67+ CertificateThumbprints = certificateThumbprints ;
68+ }
4769 }
4870
4971 public override bool Equals ( object ? obj ) => obj is SslContextCacheKey key && Equals ( key ) ;
5072
5173 public bool Equals ( SslContextCacheKey other ) =>
74+
5275 IsClient == other . IsClient &&
53- SslProtocols == other . SslProtocols &&
54- ( CertificateThumbprint == null && other . CertificateThumbprint == null ||
55- CertificateThumbprint != null && other . CertificateThumbprint != null && CertificateThumbprint . AsSpan ( ) . SequenceEqual ( other . CertificateThumbprint ) ) ;
76+ CertificateThumbprints . Span . SequenceEqual ( other . CertificateThumbprints . Span ) &&
77+ SslProtocols == other . SslProtocols ;
5678
5779 public override int GetHashCode ( )
5880 {
5981 HashCode hash = default ;
6082
6183 hash . Add ( IsClient ) ;
84+ hash . AddBytes ( CertificateThumbprints . Span ) ;
6285 hash . Add ( SslProtocols ) ;
63- if ( CertificateThumbprint != null )
64- {
65- hash . AddBytes ( CertificateThumbprint ) ;
66- }
6786
6887 return hash . ToHashCode ( ) ;
6988 }
@@ -172,7 +191,7 @@ internal static SafeSslContextHandle GetOrCreateSslContextHandle(SslAuthenticati
172191 var key = new SslContextCacheKey (
173192 sslAuthenticationOptions . IsClient ,
174193 sslAuthenticationOptions . IsClient ? protocols : serverProtocolCacheKey ,
175- sslAuthenticationOptions . CertificateContext ? . TargetCertificate . GetCertHash ( HashAlgorithmName . SHA512 ) ) ;
194+ sslAuthenticationOptions . CertificateContext ) ;
176195 return s_sslContexts . GetOrCreate ( key , static ( args ) =>
177196 {
178197 var ( sslAuthOptions , protocols , allowCached ) = args ;
0 commit comments