Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix null reference exception in SslStream.Protocol #113606

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

rzikm
Copy link
Member

@rzikm rzikm commented Mar 17, 2025

Fixes #110804.

While at it, I also mad sure we are using SHA512 of the certificate during lookup as we do in other parts of the area.

@Copilot Copilot bot review requested due to automatic review settings March 17, 2025 10:52
@rzikm
Copy link
Member Author

rzikm commented Mar 17, 2025

/azp run runtime-libraries-coreclr outerloop

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@rzikm rzikm requested review from bartonjs and wfurt March 17, 2025 10:52

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes a null reference exception in SslStream.Protocol by ensuring that an invalid certificate conversion is handled correctly and improves the certificate lookup by switching from the thumbprint string to a SHA512-based hash.

  • Return early from the method when the certificate conversion fails (null certificate).
  • Update the certificate hash retrieval to use GetCertHash with SHA512.
  • Adjust the certificate store lookup to use the new FindByThumbprint API with the SHA512 hash.
Comments suppressed due to low confidence (2)

src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Protocol.cs:197

  • With the updated null check returning early, please ensure there are unit tests covering cases where certificate conversion fails, so that the early return behavior is validated.
if (certEx is null)

src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Protocol.cs:210

  • Verify that using GetCertHash with SHA512 produces the correct hash format needed for the FindByThumbprint lookup to avoid mismatches with certificate store entries.
byte[] certHash = certEx!.GetCertHash(HashAlgorithmName.SHA512);
@rzikm
Copy link
Member Author

rzikm commented Mar 17, 2025

/azp run runtime-libraries-coreclr outerloop

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Member

@ManickaP ManickaP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks.

Copy link
Member

@wfurt wfurt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

}

string certHash = certEx!.Thumbprint;
byte[] certHash = certEx.GetCertHash(HashAlgorithmName.SHA512);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember well the Thumbprint was cached inside X509 e.g. calling it again would not allocate new array. I'm wondering we can use stack here to avoid allocation...?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f I remember well the Thumbprint was cached inside X509 e.g. calling it again would not allocate new array.

Thumbprint allocates a string every time it is accessed.

I'm wondering we can use stack here to avoid allocation.

Something like

Span<byte> thumbprint = stackalloc byte[SHA512.HashSizeInBytes];
bool ret = certEx.TryGetCertHash(HashAlgorithmName.SHA512, thumbprint, out int written);
Debug.Assert(ret && written == SHA512.HashSizeInBytes);

@@ -227,7 +229,7 @@ internal void CloseContext()
if (CertificateValidationPal.EnsureStoreOpened(isServer) is X509Store store)
{
X509Certificate2Collection certs = store.Certificates;
X509Certificate2Collection found = certs.Find(X509FindType.FindByThumbprint, certHash, false);
X509Certificate2Collection found = certs.FindByThumbprint(HashAlgorithmName.SHA512, certHash);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that FindByThumbprint has different lifetime semantics than Find. Find would return an up-refed certificate, independent from the store. FindByThumbprint does not.

Since you iterate through all of the certs on line 261-264, found will get disposed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit worried that this did not cause any of the existing tests to fail.

@rzikm
Copy link
Member Author

rzikm commented Mar 21, 2025

/ba-g wasm build failure is unrelated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Possible null reference exception in SslStream.Protocol
4 participants