From d275fdbe6a1d027bc2ef4b688261216bcd910fb7 Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Mon, 8 Apr 2024 09:53:34 +0200 Subject: [PATCH] Avoid frequent calls to CertificateValidationPal.IsLocalCertificateUsed (#100513) * Avoid frequent calls to CertificateValidationPal.IsLocalCertificateUsed * Code review feedback --- .../src/System/Net/Security/SslStream.IO.cs | 3 +++ .../System/Net/Security/SslStream.Protocol.cs | 22 ++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.IO.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.IO.cs index 43e9a42050d3b..5a01ee065c2b5 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.IO.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.IO.cs @@ -360,6 +360,9 @@ private async Task ForceAuthenticationAsync(bool receiveFirst, byte[ } token.ReleasePayload(); + + // reset the cached flag which has potentially outdated value. + _localClientCertificateUsed = -1; } if (NetEventSource.Log.IsEnabled()) diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Protocol.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Protocol.cs index a3b8b29144045..1fee2be053af5 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Protocol.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Protocol.cs @@ -57,6 +57,9 @@ internal static bool DisableTlsResume private X509Certificate2? _remoteCertificate; private bool _remoteCertificateExposed; + // -1 for uninitialized, 0 for false, 1 for true, should be accessed via IsLocalClientCertificateUsed property + private int _localClientCertificateUsed = -1; + // These are the MAX encrypt buffer output sizes, not the actual sizes. private int _headerSize = 5; //ATTN must be set to at least 5 by default private int _trailerSize = 16; @@ -82,11 +85,28 @@ internal X509Certificate? LocalServerCertificate } } + // IsLocalCertificateUsed is expensive, but it does not change during the lifetime of the SslStream except for renegotiation, so we + // can cache the value. + private bool IsLocalClientCertificateUsed + { + get + { + if (_localClientCertificateUsed == -1) + { + _localClientCertificateUsed = CertificateValidationPal.IsLocalCertificateUsed(_credentialsHandle, _securityContext!) + ? 1 + : 0; + } + + return _localClientCertificateUsed == 1; + } + } + internal X509Certificate? LocalClientCertificate { get { - if (_selectedClientCertificate != null && CertificateValidationPal.IsLocalCertificateUsed(_credentialsHandle, _securityContext!)) + if (_selectedClientCertificate != null && IsLocalClientCertificateUsed) { return _selectedClientCertificate; }