Error HRESULT: 0x80070520 when adding SSL binding in IIS

Today I will be discussing the very infamous error that is seen while adding a SSL binding in IIS 7 & higher. Below is a snapshot of the error message while trying to add the SSL binding in IIS.

image

Well, the error is definitely not descriptive enough, neither does it provide any vital information to troubleshoot the issue. However, if you look at the Event logs, you will find the clue and the reason why the error is seen.

Log Name: System Source: Schannel Date: 07-10-2012 02:13:15 Event ID: 36870 Task Category: None Level: Error Keywords: User: SYSTEM Computer: xxxxxxxxx Description: A fatal error occurred when attempting to access the SSL server credential private key. The error code returned from the cryptographic module is 0x8009030d. The internal error state is 10001.

Event message logged in the system event logs on failure.

The event logs should give you some clue regarding the problem. The primary reason for the above error is the problem in accessing the “Private Key” of the certificate due to a broken keyset.

For those who may not be following, Public Key Cryptography deals with “Public Key” & “Private Key”. The Public key is distributed to the clients, while only the Server has access to the Private key as it is used for decrypting the SSL Request. So “Private Key” is of utmost importance here.

There are few scenarios where we could see a problem accessing the “Private Key” of the SSL Cert. I will discuss a few in this article:


SCENARIO 1

The most common scenario is when the users use the IIS MMC to import a certificate and they uncheck the option “Allow this certificate to be exported”. This results in a broken keyset and thus results in the problem.

image

Solution:

There are 2 ways to fix this problem. Before we start off, delete/remove the existing certificate from the store.

  1. If using IIS MMC to import the certificate, then ensure that the “Allow this certificate to be exported” is checked.
  2. If making the private key exportable is not an option, then use the Certificates MMC to import the certificate. Please go through the following KB on how to import a certificate using the MMC: https://support.microsoft.com/kb/232137

SCENARIO 2

Another reason which can result in a broken keyset is due to missing permissions on the MachineKeys folder. This is the location where all the private keys are stored. The folder path (IIS 7 & higher) is as shown below: C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys

The default permissions on this folder are described in the following articles:

https://support.microsoft.com/kb/278381

https://msdn.microsoft.com/en-us/library/ee248638(v=vs.100).aspx

Solution:

Firstly, delete/remove the broken certificate from the store. Ensure the permissions are as per the articles mentioned above. So we need to permissions to the Administrators and Everyone account. Do remember to select the

image

 

NOTE: There might be a possibility that the issue might be seen even after ensuring right permissions. In this case, use the procmon.exe tool and fix the access denied error on the specific file inside the machinekeys folder. You may also try giving the System account Full Permissions on the MachineKeys folder.

After giving the necessary permissions, re-import the certificate as described in SCENARIO 1.


SCENARIO 3

There is another possibility, that the issue might occur even after ensuring the both mentioned above. I have observed this behavior typically on Windows Server 2008. This depends on the KeySpec property of the certificate.

The KeySpec property specifies whether the private key can be used for encryption, or signing, or both.

The following MSDN article describes KeySpec property:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa379020%28v=vs.85%29.aspx

In order to examine the KeySpec property of the certificate, use the following command:

certutil –v –store my <thumbprint>

NOTE: In the above command the thumbprint information can be found in the details tab of the certificate. The following are valid commands:

certutil -v -store my "32 b5 39 8e d3 c9 c6 f1 a3 50 bc d4 b5 14 eb b5 a4 5d 1f c6"

certutil -v -store my "32b5398ed3c9c6f1a350bcd4b514ebb5a45d1fc6"

certutil -v -store my 32b5398ed3c9c6f1a350bcd4b514ebb5a45d1fc6

Get the output of the above command in a notepad and then search for KeySpec, which is part of the CERT_KEY_PROV_INFO_PROP_ID section. The KeySpec is represented as a hexadecimal value.

certutil -v -store my 32b5398ed3c9c6f1a350bcd4b514ebb5a45d1fc6

...

...

CERT_KEY_PROV_INFO_PROP_ID(2): Key Container = {00F81886-5F70-430A-939C-BB7DD58ECE2A} Unique container name: 99247943bd018ca78ef945b82652598d_3ade29bb-f050-41f3-b0db-f2b69957a1d7 Provider = Microsoft Strong Cryptographic Provider ProviderType = 1 Flags = 20 KeySpec = 2 -- AT_SIGNATURE

...

As described above it can take three values:

Numerical Value

Value

Description

0

AT_NONE

The intended use is not identified. This value should be used if the provider is a Cryptography API: Next Generation (CNG) key storage provider (KSP).

1

AT_KEYEXCHANGE

The key can be used for encryption or key exchange.

2

AT_SIGNATURE

The key can be used for signing.

So the issue is seen if the KeySpec value is set to anything other than 1. The issue is more likely to be occur when the CSR is generated using a custom template and the KeySpec is not specified.

Whenever the KeySpec attribute is not explicitly specified, it takes the default value of 2 i.e., it can be used for signing purposes only.

Solution:

So one thing that you need to remember is that the KeySpec attribute has to be specified explicitly.

  1. If you are generating a certificate via the code, then ensure you are explicitly setting the KeySpec attribute to 1.
  2. If using certreq.exe utility along with an inf file to submit a request to SAN, ensure that you explicitly specify the KeySpec attribute to be 1.
  3. Remember the KeySpec attribute is specified while creating the Certificate Signing Request. This cannot be modified once the certificate has been issued. So remember to set the value appropriately.
  4. Also compare the KeySpec with the Key Usage attribute and make sure that both match logically.
    For example, for a certificate whose KeySpec equals to AT_KEYEXCHANGE, the Key Usage should be
    XCN_NCRYPT_ALLOW_DECRYPT_FLAG | XCN_NCRYPT_ALLOW_KEY_AGREEMENT_FLAG.

XCN_NCRYPT_ALLOW_USAGES_NONE

The permitted uses are not defined.

XCN_NCRYPT_ALLOW_DECRYPT_FLAG

The key can be used to decrypt content. This maps to the following X509KeyUsageFlags values:

  • XCN_CERT_DATA_ENCIPHERMENT_KEY_USAGE
  • XCN_CERT_DECIPHER_ONLY_KEY_USAGE
  • XCN_CERT_ENCIPHER_ONLY_KEY_USAGE
  • XCN_CERT_KEY_ENCIPHERMENT_KEY_USAGE

XCN_NCRYPT_ALLOW_SIGNING_FLAG

The key can be used for signing. This maps to the following X509KeyUsageFlags values:

  • XCN_CERT_CRL_SIGN_KEY_USAGE
  • XCN_CERT_DIGITAL_SIGNATURE_KEY_USAGE
  • XCN_CERT_KEY_CERT_SIGN_KEY_USAGE

XCN_NCRYPT_ALLOW_KEY_AGREEMENT_FLAG

The key can be used to establish key agreement between entities.

XCN_NCRYPT_ALLOW_ALL_USAGES

All of the uses defined for this enumeration are permitted.

     More Information: 

For further read on KeyUsage refer the below 2 links:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa379021%28v=vs.85%29.aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/aa379417%28v=vs.85%29.aspx

Configuring and Troubleshooting Certificate Services Client–Credential Roaming: https://technet.microsoft.com/en-us/library/dd277392.aspx

How to create a certificate request with CertEnroll (JavaScript): https://blogs.msdn.com/b/alejacma/archive/2009/01/28/how-to-create-a-certificate-request-with-certenroll-javascript.aspx

Generating a certificate (self-signed) using PowerShell and CertEnroll interfaces: https://blogs.technet.com/b/vishalagarwal/archive/2009/08/22/generating-a-certificate-self-signed-using-powershell-and-certenroll-interfaces.aspx

Hope this helps. Smile