Getting TLS 1.2 Support in .NET 2.0 and Later

How to use TLS 1.2 with HttpClient in .NET 2.0 - .NET 4.0

To enable your .NET application to use the built-in OS support for TLS 1.2, you need to change the global SecurityProtocol setting on the ServicePointManager. Unfortunately, the enumeration doesn’t have the appropriate values until .NET 4.5 so if your application targets an older version of .NET you need to add these values. For code clarity, You can create a new constant class in the same namespace as the SecurityProtocolType enumeration, like this:

namespace System.Net
{
    internal static class SecurityProtocolTypeExtensions
    {
        public const SecurityProtocolType Tls12 = (SecurityProtocolType)3072;
        public const SecurityProtocolType Tls11 = (SecurityProtocolType)768;
    }
}

Then, anywhere in your application before you need SSL support you can configure the mode you want, like this:

ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol 
                                        | SecurityProtocolTypeExtensions.Tls12;

In this case we’re adding TLS 1.2 support to whatever is already enabled. The client should then contact the server and negotiate the highest mutually supported TLS version.

How to require TLS 1.2 with HttpClient in .NET 2.0 through .NET 4.0

To ensure your application doesn’t fall back to any older version of TLS regardless of OS settings, specify the new enumeration value as the only allowed security protocol, like this:

ServicePointManager.SecurityProtocol = SecurityProtocolTypeExtensions.Tls12;

How to use TLS 1.2 with HttpClient in .NET 4.5 - .NET 4.6.2

To enable your .NET application to use the built-in OS support for TLS 1.2, you need to change the global SecurityProtocol setting on the ServicePointManager. Anywhere in your application before you need SSL support you can configure the mode you want, like this:

ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol 
                                        | SecurityProtocolType.Tls12;

In this case we’re adding TLS 1.2 support to whatever is already enabled. The client should then contact the server and negotiate the highest mutually supported TLS version.

How to require TLS 1.2 with HttpClient in .NET 4.5 through .NET 4.6.2

To ensure your application doesn’t fall back to any older version of TLS regardless of OS settings, specify the new enumeration value as the only allowed security protocol, like this:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

How to use TLS 1.2 with SslStream in .NET 2.0 - .NET 4.0

If you are using TCP Sockets directly and want to wrap them in SSL for security, getting TLS 1.2 to work is a bit more challenging. We needed this with Loupe because the Live Stream data runs over a TCP Socket separately from the HTTPS communication with the Loupe Server. To make it work we had to do two things:

  1. Define constants for TLS 1.1 and 1.2: These values don’t exist in the SslProtocols Enumeration prior to .NET 4.5.
  2. Specify allowed TLS versions when establishing the Connection: Use relevant client and server method overrides when establishing the secure connection that support specifying the allowed TLS versions and include the TLS 1.2 value.

For the first point, we added the following as suggested by this KB article by Microsoft -

namespace System.Security.Authentication
{
    //Since .NET 4.0 and older don't have the constants for TLS 1.1 and 1.2 we add them ourselves
    internal static class SslProtocolsExtensions
    {
        public const SslProtocols Tls12 = (SslProtocols)0x00000C00;
        public const SslProtocols Tls11 = (SslProtocols)0x00000300;
    }
}

And then to complete the fix, we modified our client code to specify the protocols in AuthenticateAsClient:

//create an SslStream, wrapping an open NetworkStream
var sslStream = new SslStream(rawStream, false);

//Define the allowed TLS versions.  In this example, we're allowing TLS 1.0 -> 1.2.
var sslProtocols = SslProtocols.Tls | SslProtocolsExtensions.Tls11 |
                    SslProtocolsExtensions.Tls12;

//establish the SSL connection.  This will negotiate for the highest mutual version
sslStream.AuthenticateAsClient("server.dns.name", null, sslProtocols, true);

The server side is the same except you call AuthenticateAsServer:

//create an SslStream, wrapping an open NetworkStream
var sslStream = new SslStream(rawStream, false);

//Define the allowed TLS versions.  In this example, we're allowing TLS 1.0 -> 1.2.
var sslProtocols = SslProtocols.Tls | SslProtocolsExtensions.Tls11 |
                    SslProtocolsExtensions.Tls12;

//establish the SSL connection.  This will negotiate for the highest mutual version
sslStream.AuthenticateAsServer(serverX509Certificate, false, sslProtocols, false );

(How to get the X509 Certificate on the server is left out for brevity)

How to use TLS 1.2 with SslStream in .NET 4.5 - .NET 4.6.2

To use TLS 1.2 in .NET 4.5 up to 4.6.2 is a bit simpler because the enumeration values are there, it’s just a matter that the default action doesn’t allow for TLS 1.2. So, we just need to use the relevant client and server method overrides when establishing the secure connection that support specifying the allowed TLS versions and include the TLS 1.2 value.

Creating an SslStream Client Connection using TLS 1.2

//create an SslStream, wrapping an open NetworkStream
var sslStream = new SslStream(rawStream, false);

//Define the allowed TLS versions.  In this example, we're allowing TLS 1.0 -> 1.2.
var sslProtocols = SslProtocols.Tls | SslProtocols.Tls11 |
                    SslProtocols.Tls12;

//establish the SSL connection.  This will negotiate for the highest mutual version
sslStream.AuthenticateAsClient("server.dns.name", null, sslProtocols, true);

Creating an SslStream Server Connection using TLS 1.2

The server side is the same except you call AuthenticateAsServer:

//create an SslStream, wrapping an open NetworkStream
var sslStream = new SslStream(rawStream, false);

//Define the allowed TLS versions.  In this example, we're allowing TLS 1.0 -> 1.2.
var sslProtocols = SslProtocols.Tls | SslProtocols.Tls11 |
                    SslProtocols.Tls12;

//establish the SSL connection.  This will negotiate for the highest mutual version
sslStream.AuthenticateAsServer(serverX509Certificate, false, sslProtocols, false );

(How to get the X509 Certificate on the server is left out for brevity)

Comprehensive Guide to TLS in .NET Framework (all versions)

If you want to dig through all the variations - HttpClient, SslStream, and WCF Transports on .NET 2.0 through 4.7 Microsoft has a complete reference document available.
It took us some verification to get the right results but once we were successful we went back and re-read the documentation and were able to confirm our approaches.

Rock solid centralized logging

Unlimited applications, unlimited errors, scalable from solo startup to enterprise.