A simple installer which enables Transport Layer Security (TLS) 1.2 on Microsoft Windows Vista Service Pack 2 or later.
The patcher is designed to make .NET 4.x applications use TLS 1.2 without needing any code changes. It may also work for some applications targeting lower version of .NET.
The latest version can be downloaded here.
To install, simply run the installer and accept the license agreement. You must have administrative privileges. You may be prompted to restart your computer in order for the changes to take effect.
Minimum system requirements:
- For one-click install with no other prerequisites: Windows 7 with Service Pack 1
- Windows Vista SP2 and Windows Server 2008 SP2 are supported after installing Microsoft Update KB4019276.
The installer:
- Detects whether .NET 4.6 or higher is present on the system, and if not, downloads and installs the .NET 4.6 Redistributable.
- Writes a registry value which makes .NET 4.x code select the strongest enabled security protocol by default.
- Writes registry values to explicitly enable TLS 1.2 for WinSSL.
The patcher will appear in Add/Remove Programs. Uninstalling the patcher will not delete the registry values it created (in v1.1.0 and prior it will delete them, and could disable TLS 1.2 as a result). Uninstalling the patcher will not uninstall .NET 4.6.
For the rationale behind these changes, see the in-depth section below.
Some exceptions may apply. See the limitations section below.
See the table below for a list of systems verified to be compatible/incompatible with this utility. Cells which do not have an X or ✓ have not yet been tested, but we expect them to be compatible unless otherwise noted. N/A indicates that the Windows version does not have a release with the specified architecture.
Windows OS | x86 | x64 | Notes |
---|---|---|---|
Windows XP & Windows Server 2003 | X | X | Does not support .NET 4.6 |
Windows Embedded Point of Sale 1.0 | X | X | Does not support .NET 4.6 |
Windows Embedded POSReady 2009 | X | N/A | Does not support .NET 4.6 |
Windows Vista with Service Pack 2 (SP2) | ✓ | Requires KB4019276 | |
Windows Server 2008 with Service Pack 2 (SP2) | N/A | ✓ | Requires KB4019276 |
Windows 7/Windows Server 2008 R2 with Service Pack 1 (SP1) | ✓ | ✓ | |
Windows Embedded POSReady 7 | ✓ | ||
Windows 8/Windows Server 2012 | ✓ | ✓ | |
Windows Embedded 8 Industry | |||
Windows 8.1/Windows Server 2012 R2 | ✓ | ✓ | |
Windows Embedded 8.1 Industry | ✓ | ||
Windows 10 & Windows Server 2016 | ✓ | ✓ |
This section outlines in more detail what changes are made.
The option of using TLS 1.2 was introduced in .NET 4.5, however, it is not enabled as a communication protocol by default in 4.5. Beginning with .NET 4.6, it is enabled as a communication protocol by default. Thus, in conjunction with the appropriate registry changes, .NET 4.6+ makes it possible to use TLS 1.2 without having to make code changes to explicitly enable it.
In order to make .NET 4.x code select the strongest available protocol by default (i.e. when a protocol is not explicitly specified in code), the following registry keys are set:
On 32-bit versions of Windows:
Registry Key | Value Name | DWORD Data |
---|---|---|
HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 | SchUseStrongCrypto | 0x00000001 |
On 64-bit versions of Windows:
Registry Key | Value Name | DWORD Data |
---|---|---|
HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 | SchUseStrongCrypto | 0x00000001 |
HKLM\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319 | SchUseStrongCrypto | 0x00000001 |
The following registry values may enable TLS 1.2 for apps targeting lower versions of .NET on some systems in conjunction with certain updates (see Limitations for details)
On 32-bit versions of Windows:
Registry Key | Value Name | DWORD Data |
---|---|---|
HKLM\SOFTWARE\Microsoft\.NETFramework\v2.0.50727 | SystemDefaultTlsVersions | 0x00000001 |
On 64-bit versions of Windows:
Registry Key | Value Name | DWORD Data |
---|---|---|
HKLM\SOFTWARE\Microsoft\.NETFramework\v2.0.50727 | SystemDefaultTlsVersions | 0x00000001 |
HKLM\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v2.0.50727 | SystemDefaultTlsVersions | 0x00000001 |
The WOW6432Node values are used by 32-bit applications when run on a 64-bit system. If you happened to run the .msi generated by the Installer.x86 project on a 64-bit system, then only the WOW6432Node values would be added to the registry. In this case, 32-bit .NET 4.x applications would show the expected change in behavior and use TLS 1.2, but 64-bit applications would not. For this reason, we provide only the .exe file generated by the Bootstrapper project as a download. The bootstrapper is bundled with both x86 and x64 .msi files. It will detect whether the system is 32-bit or 64-bit and run the appropriate .msi.
The following registry keys/values are set to enable the TLS 1.2 for SChannel.dll (aka WinSSL). If these values do not exist, the default behavior when using the SchUseStrongCrypto key with .NET 4.6+ should still select TLS 1.2. However, we explicitly set the keys in order to avoid any issues which may arise if any of the keys already exist with contradictory values.
Registry Key | Value Name | DWORD Data |
---|---|---|
HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client | Enabled | 0x00000001 |
HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client | DisabledByDefault | 0x00000000 |
HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server | Enabled | 0x00000001 |
HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server | DisabledByDefault | 0x00000000 |
To build this Visual Studio solution (.sln
) you must have the following components installed:
- Visual Studio 2017/MSBuild 15.0
- Powershell
- NuGet CLI - The nuget command must be available from your command line.
- WiX Toolset v3.11
.\build.ps1 -Configuration=<Debug/Release>
For convenience, the build process will create a folder named artifacts
in the root directory, and the outputted files will be copied there.
If you wish to include the TLS Patcher as part of an installer, you can include it as part of a WiX Bootstrapper.
To facilitate this, beginning with v1.1.0, the patcher writes a set of registry values which can be used to detect what version, if any, is currently installed on a system. The version information can be used in the DetectCondition
of the ExePackage definition so that the patcher installation will be suppressed if the same or higher version already exists on the system.
The following code snippet shows how you could include v1.1.0 of the TLS Patcher in a bootstrapper project, assuming that the .exe is placed in a folder named "Dependencies" within the bootstraper project.
<Bundle>
<!-- ... -->
<Chain DisableSystemRestore="no">
<PackageGroupRef Id="TlsPatcher" />
<!--Other packages-->
</Chain>
</Bundle>
<Fragment>
<?define BundledTlsPatcherVersion="1.1.0"?>
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\LevelUp" Value="TlsPatcherVersion"
Format="raw" Win64="no" Variable="ExistingTlsPatcherVersion" />
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\LevelUp" Value="TlsPatcherVersion"
Format="raw" Win64="yes" Variable="ExistingTlsPatcherVersion64" />
<Variable Name="BundledTlsPatcherVersion" Value="$(var.BundledTlsVersion)" Type="version"/>
<PackageGroup Id="TlsPatcher">
<ExePackage
Id="TlsPatcher"
Name="TlsPatcher-$(var.BundledTlsPatcherVersion).exe"
SourceFile="$(var.ProjectDir)Dependencies\TlsPatcher-$(var.BundledTlsPatcherVersion).exe"
DetectCondition="ExistingTlsPatcherVersion >= BundledTlsPatcherVersion AND (NOT VersionNT64 OR ExistingTlsPatcherVersion64 >= BundledTlsPatcherVersion)"
InstallCommand="/q"
RepairCommand="/q /repair"
PerMachine="yes"
Vital="yes"
Permanent="yes"
Compressed="yes" />
</PackageGroup>
</Fragment>
The patcher is expected to work for .NET 4.x code provided that the current code is not overriding the defaults by explicitly specifying a different protocol. If this is not the case, code changes will be necessary. If you wish to make use of this patcher, you can simply remove any lines where you set the value of ServicePointManager.SecurityProtocol
.
The Schannel registry keys described may also work for non-.NET code that uses WinSSL and does not explicitly specify a non-TLS 1.2 protocol.
The following are some resources for other scenarios which we have not tested, but may be useful:
-
If you wish to continue explicitly setting the protocol in code this stackoverflow thread offers guidance for .NET 4.0/4.5
-
If you are targeting an older version of .NET, Microsoft has provided the following updates to support the SystemDefaultTlsVersions registry key:
This project is licensed under the Apache 2.0 License - see the LICENSE.txt file for details.