TLS 1.2 and .NET Support: How to Avoid Connection Errors

I recently ran into an interesting issue when developing a connector for a third-party API. When trying to connect to the API endpoint, I received the following error message:“An error occurred while making the HTTP request to https://<API endpoint>. This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server.” Inner exception was “Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.”
Not very informative at first glance, right?
However, after some digging around I realized that the error message was correct, at least in the following part: “This could also be caused by a mismatch of the security binding between the client and the server.” I checked my SOAP bindings, and everything seemed to be correct: server required SSL connection, and I had TransportLevelSecurity specified in my binding:

var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);

After I read more about SSL and Transport Level Security (TLS), I understood that “not all HTTPSs are created equal.” HTTPS relies on a family of lower level security protocol implementations called transport level security (TLS), each using different cryptographic algorithms. TLS standards keep developing and improving. At the moment TLS 1.2 is a latest encryption standard powering SSL and TLS 1.3 is in works. In general, anything that is using TLS standard below TLS 1.2 is considered to be non secure because these older encryption algorithms are known to be cracked.
Apparently, the provider of the API I was trying to call disabled all other security protocols except for TLS 1.2. That was reason I was getting the error.
So, why didn’t .NET framework support TLS 1.2 in my case? Well, that was because my application was using .NET 4.0. In .NET 4.0 default transport level security standard is TLS 1.1. The solution for my problem was to upgrade my application to the latest .NET framework: 4.6.1. In this framework version TLS 1.2 is a default cryptographic standard.
But what if you can’t upgrade your application to latest .NET framework and still want to use TLS 1.2? Solutions exist, but they vary depending on the framework version:

.NET 4.6 and above. You don’t need to do any additional work to support TLS 1.2, it’s supported by default.

.NET 4.5. TLS 1.2 is supported, but it’s not a default protocol. You need to opt-in to use it. The following code will make TLS 1.2 default, make sure to execute it before making a connection to secured resource:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

.NET 4.0. TLS 1.2 is not supported, but if you have .NET 4.5 (or above) installed on the system then you still can opt in for TLS 1.2 even if your application framework doesn’t support it. The only problem is that SecurityProtocolType in .NET 4.0 doesn’t have an entry for TLS1.2, so we’d have to use a numerical representation of this enum value:

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

.NET 3.5 or below. TLS 1.2 is not supported (*) and there is no workaround. Upgrade your application to more recent version of the framework.

This is very helpful information!
Is it possible to get the TLS 1.2 connections to work on older environments?
I’m trying to run a .net app which makes client calls on a Windows Server 2008 SP2 machine. The machine has .net 4.5 and I’m following the above instructions but couldn’t get connection to an api.

You saved my bacon today… upgraded the component that was making web service calls to a vendors web service who turned off TLS 1.1 (and didn’t bother to communicate it) to version 4.6 and fixed it. Thanks!

First of all thank you so much for this suggestion. I have did the same but my server service is throwing an error called, Service cannot be started. System.NotSupportedException: The requested security protocol is not supported. What am i suppose to do for clearing this error.

Hello,
Thank you for the article!
Regarding “.NET 3.5 or below. TLS 1.2 is not supported and there is no workaround. Upgrade your application to more recent version of the framework.”:
We have recently added a feature for .Net 3.5 allowing applications to optionally use system-default SSL and TLS versions, including the deprecated TLS 1.2, rather than the versions of TLS now used by default in .Net 3.5.
To use this feature, you must first install a patch that is specific to each version of Windows, as described in the KB articles below, and then modify the registry as described in each KB article.
KB3154518 – Reliability Rollup HR-1605 – NDP 2.0 SP2 – Win7 SP1/Win 2008 R2 SP1
KB3154519 – Reliability Rollup HR-1605 – NDP 2.0 SP2 – Win8 RTM/Win 2012 RTM
KB3154520 – Reliability Rollup HR-1605 – NDP 2.0 SP2 – Win8.1RTM/Win 2012 R2 RTM
KB3156421 -1605 HotFix Rollup through Windows Update for Windows 10.
Cristian Pop, Microsoft (MSFT)

Correction:
“We have recently added a feature for .Net 3.5 allowing applications to optionally use system-default SSL and TLS versions, including TLS 1.2, rather than the versions of TLS now used by default in .Net 3.5.”
TLS 1.2 is obviously not deprecated.

I have a .NET app written against framework 3.5 and then the same app written against .NET 4.5.2. In Win 7, I can get the 4.5.2 one to connect to a TLS 1.2 only server, but I cannot get the 3.5 one to work despite the suggested patches above. On Win 10 both versions of the app work as expected.
Is there some other thing I’m missing that might provide some guidance?

Great article! I do have a question:
– we have an app running in .NET 4.5, using Tls 1.2, everything works ok
– we have a similar app running in .NET 2.0 that needed to use Tls 1.2. And we got it working using this line of code: ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
So my question is, how can this work in the .NET 2.0 version of the application?

Hi,
I have my application in .net 4.5 , I want to enable TLS 1.2 in this application. I have upgrade application version from v4.5 to v4.6 after I checked my connection with the salesforce its giving error “UNSUPPORTED_CLIENT: TLS 1.0 has been disabled in this organization.Please use TLS 1.1 or higher when connecting to Salesforce using https.”.
If I stay on the v4.5 and used the line “ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;” then it work fine.
My client want to enable tls1.2 with upgrade v4.5 to v4.6 and we know .net v4.6 support tls 1.2 by default meand no need to extra work.
but in my case its tls1.2 not working even I change my framework version with v4.6.
I am using visual studio 2015 updated 2 version.

I have a VB project (part of a Visual Studio 2013 solution) which targets .NET 4. The remote server to which the app sends a web request has stopped supporting TLS 1.0 (which is the default in .NET 4) so the app stopped working, with exactly the same error message expressed at the top of this article. Rather than change the .NET target, I added the line of code as follows:-
System.Net.ServicePointManager.SecurityProtocol = DirectCast(3072, System.Net.SecurityProtocolType)
This appears to have done the trick.
Huge thanks!

Great article. This shed some decent light on a current situation. Obviously, I’m a little late to the game here, but, if I upgrade to 4.6+ will the framework automatically switch to the lowest common denominator (maybe they currently only support 1.1, etc…) or am I back to square one with now having to explicitly state Tls1.1?

I have .net 4.6.2. As per this artical – .NET 4.6 and above. You don’t need to do any additional work to support TLS 1.2, it’s supported by default. but this is not working in our case, we found this is working only on .NET 4.7 and above.
So we set following code
ServicePointManager.SecurityProtocol = (SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12);
and its working. But we need to add this code in different assemblies, and our architect don’t want this. This should be global and if future TLS 1.3 come we don’t need to change code , we just need to change settings or something.
Please suggest.
Thanks in advance.

As per the Microsoft site https://docs.microsoft.com/en-us/dotnet/api/system.net.servicepointmanager.securityprotocol?view=netframework-4.7#System_Net_ServicePointManager_SecurityProtocol:
Starting with the .NET Framework 4.7, the default value of this property is SecurityProtocolType.SystemDefault. This allows .NET Framework networking APIs based on SslStream (such as FTP, HTTP, and SMTP) to inherit the default security protocols from the operating system or from any custom configurations performed by a system administrator. For information about which SSL/TLS protocols are enabled by default on each version of the Windows operating system, see Protocols in TLS/SSL (Schannel SSP).
For versions of the .NET Framework through the .NET Framework 4.6.2, no default value is listed for this property. This suggests that for .Net 4.6.2 and earlier, you would need to set the TLs version in code using ServicePointManager, etc.

.NET 4.7 will use the system default for TLS, but there is a gotcha: If you are running Win7 SP1 or Server 2008 SP1, the system default for TLS 1.2 is: disabled.
To get around this you can update the registry on the machine or use the same codefix required for pre-4.5 .NET versions (see Sandesh’s comment below).