Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Add support for OCSP on Linux, overhaul X509Chain processing #35367

Merged
merged 31 commits into from
Feb 22, 2019

Conversation

bartonjs
Copy link
Member

The primary motivator for this change is to enable support for validating certificates with the On-line Certificate Status Protocol (OCSP) in addition to Certificate Revocation Lists (CRLs).

OCSP requests can't be done speculatively, as the issuer public key is used as part of the request payload; so the chain building can't just be done as a big data dump.

While tinkering with the chain building, move a lot of the processing to the native side to cut down on the number of P/Invokes that are required. In particular, loading CurrentUser\My no longer has 3 P/Invokes per entry (File.Open, interpret the contents, add to the chain build context), but just one call for the whole store (the fopen/interpret/add are all done in the same iterated function).

Additionally, move some allocating things to rent from the array pool, or do one-time lookups and save the result in statics.

Fixes #3034.

The vast majority of cert handles don't cross the P/Invoke boundary,
reducing the GC load of creating and releasing SafeHandle objects.
@bartonjs bartonjs added this to the 3.0 milestone Feb 16, 2019
@bartonjs bartonjs self-assigned this Feb 16, 2019
{
// While the IntPtrs aren't secret, clearing them helps prevent
// accidental use-after-free because of pooling.
ArrayPool<IntPtr>.Shared.Return(tempChainRent, clearArray: true);
Copy link
Member

Choose a reason for hiding this comment

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

tempChain.Clear();
ArrayPool<IntPtr>.Shared.Return(tempChainRent);

?

{
st.Item1.AsSpan().CopyTo(buf);
st.Item2.Span.CopyTo(buf.Slice(st.Item1.Length));
});
Copy link
Member

Choose a reason for hiding this comment

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

Nit: you could instead write this as:

return string.Create(count, (baseUri, resource), (buf, st) =>
{
    st.baseUri.AsSpan().CopyTo(buf);
    st.resource.Span.CopyTo(buf.Slice(st.baseUri.Length));
});

avoiding both the direct use of ValueTuple as well as using Item1/Item2.

private unsafe struct ErrorCollection
{
// As of OpenSSL 1.1.1 there are 74 defined X509_V_ERR values.
private const int BucketCount = 3;
Copy link
Member

Choose a reason for hiding this comment

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

How does 74 relate to 3?

Copy link
Member

Choose a reason for hiding this comment

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

Ah, 32 bits per int * 3 == 96, which is > 74.

private static int FindBucket(Interop.Crypto.X509VerifyStatusCode statusCode, out int bitValue)
{
int val = (int)statusCode;
Debug.Assert(val < 32 * BucketCount);
Copy link
Member

Choose a reason for hiding this comment

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

What happens if OpenSSL releases a new version that we bind to and it ends up having > 96 errors defined?

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 added an overflow state, and verified behavior by having the shim report 94 / 95 / 96 as the value instead of CERT_EXPIRED

@stephentoub
Copy link
Member

I was really hoping / expecting based on previous profiling that this would make a dent in https://github.com/dotnet/corefx/issues/35086.

Good news and bad news...

The good news is it makes a great impact on allocation / GCs. Creating a thousand SslStream client/server pairs over a NetworkStream and doing an AuthenticateAsClient/ServerAsync for each, before this change I would see Gen0/1/2 GC numbers like this:

GC: 26 / 4 / 1

and with this PR I see numbers like this:

GC: 3 / 0 / 0

That's excellent.

Unfortunately, for my test, this barely makes an impact on throughput, maybe around a 5% improvement, e.g. before I get numbers like:

Elapsed: 00:00:21.1268228

and after I get numbers like:

Elapsed: 00:00:20.0625565

For comparison, on Windows I get numbers for the same test like:

Elapsed: 00:00:00.7266360       GC: 1 / 0 / 0

@bartonjs
Copy link
Member Author

this barely makes an impact on throughput

Are you comparing apples to apples? e.g. are both sides making connections to trusted endpoints?

@stephentoub
Copy link
Member

Are you comparing apples to apples? e.g. are both sides making connections to trusted endpoints?

Here's the code. If it's not apples-to-apples, what would I need to change to make it so?

using System;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        AppDomain.CurrentDomain.FirstChanceException += (s, e) => Console.WriteLine("****** ERROR *****: " + e.Exception);
        Console.WriteLine("COMPlus_TieredCompilation: " + Environment.GetEnvironmentVariable("COMPlus_TieredCompilation"));
        Console.WriteLine("COMPlus_ZapDisable: " + Environment.GetEnvironmentVariable("COMPlus_ZapDisable"));

        using (var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
        using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
        {
            listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
            listener.Listen(1);

            client.Connect(listener.LocalEndPoint);
            using (Socket server = listener.Accept())
            {
                using (var clientStream = new NetworkStream(client))
                using (var serverStream = new NetworkStream(server))
                using (X509Certificate2 cert = GetServerCertificate())
                {
                    var sw = new Stopwatch();
                    var tasks = new Task[2];

                    var clientOptions = new SslClientAuthenticationOptions
                    {
                        TargetHost = "localhost"
                    };

                    var serverOptions = new SslServerAuthenticationOptions
                    {
                        ServerCertificate = cert,
                        CertificateRevocationCheckMode = X509RevocationMode.NoCheck
                    };

                    for (int trial = 0; trial < 10; trial++)
                    {
                        int gen0 = GC.CollectionCount(0), gen1 = GC.CollectionCount(1), gen2 = GC.CollectionCount(2);
                        sw.Restart();
                        for (int i = 0; i < 1000; i++)
                        {
                            using (var clientSslStream = new SslStream(clientStream, true, delegate { return true; }))
                            using (var serverSslStream = new SslStream(serverStream, true, delegate { return true; }))
                            {
                                tasks[0] = clientSslStream.AuthenticateAsClientAsync(clientOptions, default);
                                tasks[1] = serverSslStream.AuthenticateAsServerAsync(serverOptions, default);
                                Task.WaitAll(tasks);
                            }
                        }
                        sw.Stop();
                        gen0 = GC.CollectionCount(0) - gen0;
                        gen1 = GC.CollectionCount(1) - gen1;
                        gen2 = GC.CollectionCount(2) - gen2;
                        Console.WriteLine($"Elapsed: {sw.Elapsed}\tGC: {gen0} / {gen1} / {gen2}");
                    }
                }
            }
        }
    }

    private static readonly byte[] s_testCertBytes = Convert.FromBase64String(@"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");

    private static X509Certificate2 GetServerCertificate()
    {
        var certCollection = new X509Certificate2Collection();
        certCollection.Import(s_testCertBytes, "testcertificate", X509KeyStorageFlags.DefaultKeySet);
        return certCollection.Cast<X509Certificate2>().First(c => c.HasPrivateKey);
    }
}

Based on previous conversations, I tried a variety of things, like adding the certs into my local store. Didn't seem to make a difference.

@bartonjs
Copy link
Member Author

Regarding the perf only getting a little better: Based on some quick instrumentation (System.Diagnostics.Stopwatch) it looks like a good amount of time is spent reading the user stores as live operations (~60%+ of the time of my builds). There's a fine balance between reading them once ever and reading them hot that I think we can attain to not lose significant fidelity against Windows' fully-hot(-but-fast); but it seems like that will involve some tweaking and tuning that I think makes sense to defer to a followup change.

@stephentoub
Copy link
Member

I think makes sense to defer to a followup change.

That's fine. Thanks.

@bartonjs
Copy link
Member Author

Any other feedback @stephentoub (or @krwq)?

@stephentoub
Copy link
Member

LGTM. Thanks.

@bartonjs bartonjs merged commit 0fbbb68 into dotnet:master Feb 22, 2019
{
X509* leaf = X509_STORE_CTX_get0_cert(ctx);
X509Stack* untrusted = X509_STORE_CTX_get0_untrusted(ctx);
X509_STORE* store = X509_STORE_CTX_get0_store(ctx);
Copy link
Member

Choose a reason for hiding this comment

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

It seems like this change broke our RedHat6 official build:

/__w/1/s/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.c(311,25): error GC97D5F25: implicit declaration of function 'X509_STORE_CTX_get0_store' is invalid in C99 [-Werror,-Wimplicit-function-declaration] [/__w/1/s/src/Native/build-native.proj]
      X509_STORE* store = X509_STORE_CTX_get0_store(ctx);
                          ^
/__w/1/s/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.c(311,17): error G5F2A7227: incompatible integer to pointer conversion initializing 'X509_STORE *' (aka 'struct x509_store_st *') with an expression of type 'int' [-Werror,-Wint-conversion] [/__w/1/s/src/Native/build-native.proj]
      X509_STORE* store = X509_STORE_CTX_get0_store(ctx);
                  ^       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/__w/1/s/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.c(758,21): error G5F2A7227: incompatible integer to pointer conversion initializing 'X509_STORE *' (aka 'struct x509_store_st *') with an expression of type 'int' [-Werror,-Wint-conversion] [/__w/1/s/src/Native/build-native.proj]
          X509_STORE* store = X509_STORE_CTX_get0_store(storeCtx);
                      ^       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3 errors generated.
  make[2]: *** [System.Security.Cryptography.Native/CMakeFiles/objlib.dir/pal_x509.c.o] Error 1
  make[1]: *** [System.Security.Cryptography.Native/CMakeFiles/objlib.dir/all] Error 2
  make: *** [all] Error 2
  Failed to build corefx native components.
/__w/1/s/src/Native/build-native.proj(37,5): error MSB3073: The command ""/__w/1/s/src/Native/build-native.sh" x64 Release Linux outconfig netcoreapp-Linux-Release-x64 stripsymbols" exited with code 1.

Build FAILED.

/__w/1/s/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.c(311,25): error GC97D5F25: implicit declaration of function 'X509_STORE_CTX_get0_store' is invalid in C99 [-Werror,-Wimplicit-function-declaration] [/__w/1/s/src/Native/build-native.proj]
/__w/1/s/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.c(311,17): error G5F2A7227: incompatible integer to pointer conversion initializing 'X509_STORE *' (aka 'struct x509_store_st *') with an expression of type 'int' [-Werror,-Wint-conversion] [/__w/1/s/src/Native/build-native.proj]
/__w/1/s/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.c(758,21): error G5F2A7227: incompatible integer to pointer conversion initializing 'X509_STORE *' (aka 'struct x509_store_st *') with an expression of type 'int' [-Werror,-Wint-conversion] [/__w/1/s/src/Native/build-native.proj]
/__w/1/s/src/Native/build-native.proj(37,5): error MSB3073: The command ""/__w/1/s/src/Native/build-native.sh" x64 Release Linux outconfig netcoreapp-Linux-Release-x64 stripsymbols" exited with code 1.
    0 Warning(s)
    4 Error(s)

https://dev.azure.com/dnceng/internal/_build/results?buildId=104405&view=logs&jobId=7cbf968d-26f0-55c8-fa2c-bd900b311c34&taskId=80b36c5e-5cc3-5f6d-94ed-94388cf0917b&lineStart=1348&lineEnd=1348&colStart=1&colEnd=14

@bartonjs bartonjs removed their assignment Apr 5, 2019
@bartonjs bartonjs deleted the linux-ocsp branch May 20, 2019 15:05
@heng-liu
Copy link

Hi, @bartonjs
May I know if there is any update for the System.Security.Cryptography.X509Certificates.X509Chain.Build on Linux, is it able to check OCSP now? Or only CRL? Thanks!

@bartonjs
Copy link
Member Author

@heng-liu Yes, in .NET Core 3.0 (because of this PR).

@heng-liu
Copy link

@bartonjs Great!
May I know for the X509Chain.Build method, will it check both OCSP and CRL, or only one of them which is available?
If I create a test certificate, only configure OCSP but not CRL, will the chain build get"unable to get certificate CRL" in the X509ChainStatus? Thanks!

@bartonjs
Copy link
Member Author

@heng-liu If a CA only offers one of the two then that's what's used. Otherwise it'll take whichever answer works first.

If you're seeing some sort of problem, please file an issue with details.

@heng-liu
Copy link

@bartonjs I'm not sure if it's an issue, because I'm not clear if there is any other restriction on Linux, which may disable OCSP even if NET Core 3.0 support OCSP.. Do you have any suggestions? Thanks!

@bartonjs
Copy link
Member Author

@heng-liu The CA not offering it, network errors, et cetera. OCSP should "just work" when needed. If you're trying to watch for the network request, it won't be made if the response is already cached.

I just verified against a Let's Encrypt issued certificate with .NET Core 3.0 on a new Linux machine, and it processed the revocation (they're OCSP-only). So the feature works on something other than my dev machine 😄.

@heng-liu
Copy link

heng-liu commented Oct 1, 2019

Thanks for your help! @bartonjs
I send you an offline e-mail for the repro steps.

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

Successfully merging this pull request may close these issues.

Add support for OCSP on Unix
5 participants