@@ -35,35 +35,54 @@ private sealed class SafeSslContextCache : SafeHandleCache<SslContextCacheKey, S
35
35
36
36
internal readonly struct SslContextCacheKey : IEquatable < SslContextCacheKey >
37
37
{
38
+ private const int ThumbprintSize = 64 ; // SHA512 size
39
+
38
40
public readonly bool IsClient ;
39
- public readonly byte [ ] ? CertificateThumbprint ;
41
+ public readonly ReadOnlyMemory < byte > CertificateThumbprints ;
40
42
public readonly SslProtocols SslProtocols ;
41
43
42
- public SslContextCacheKey ( bool isClient , SslProtocols sslProtocols , byte [ ] ? certificateThumbprint )
44
+ public SslContextCacheKey ( bool isClient , SslProtocols sslProtocols , SslStreamCertificateContext ? certContext )
43
45
{
44
46
IsClient = isClient ;
45
47
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
+ }
47
69
}
48
70
49
71
public override bool Equals ( object ? obj ) => obj is SslContextCacheKey key && Equals ( key ) ;
50
72
51
73
public bool Equals ( SslContextCacheKey other ) =>
74
+
52
75
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 ;
56
78
57
79
public override int GetHashCode ( )
58
80
{
59
81
HashCode hash = default ;
60
82
61
83
hash . Add ( IsClient ) ;
84
+ hash . AddBytes ( CertificateThumbprints . Span ) ;
62
85
hash . Add ( SslProtocols ) ;
63
- if ( CertificateThumbprint != null )
64
- {
65
- hash . AddBytes ( CertificateThumbprint ) ;
66
- }
67
86
68
87
return hash . ToHashCode ( ) ;
69
88
}
@@ -172,7 +191,7 @@ internal static SafeSslContextHandle GetOrCreateSslContextHandle(SslAuthenticati
172
191
var key = new SslContextCacheKey (
173
192
sslAuthenticationOptions . IsClient ,
174
193
sslAuthenticationOptions . IsClient ? protocols : serverProtocolCacheKey ,
175
- sslAuthenticationOptions . CertificateContext ? . TargetCertificate . GetCertHash ( HashAlgorithmName . SHA512 ) ) ;
194
+ sslAuthenticationOptions . CertificateContext ) ;
176
195
return s_sslContexts . GetOrCreate ( key , static ( args ) =>
177
196
{
178
197
var ( sslAuthOptions , protocols , allowCached ) = args ;
0 commit comments