In the previous post we explored the techniques used to create a common revocation configuration for use with Enterprise CA.

Today we will discover another option, when you create revocation configuration for external (Standalone or 3rd party) CA. Steps to create such configurations are almost the same and differ only in certain parts.

Creating revocation configuration for Standalone CA

Consider the following scenario: you have a Standalone CA which is not connected to a network. You need to create revocation configuration for this CA. Signing certificate is issued (out of band) from that CA.

First step here is to enroll a signing certificate. Since, CA is Standalone, there is no way to enroll for a certificate directly from CA server. Instead, you have to manually generate certificate request, submit it to CA, issue certificate and install it back to OCSP server. For this operation you can follow the following article: Online Responder Installation, Configuration, and Troubleshooting Guide, section “Enrolling for an OCSP Response Signing certificate against a stand-alone CA”.

Do not forget to grant Network Service read permissions on private key.

Once certificate is enrolled and installed, we are ready to create revocation configuration. Here are steps which are common for any type of configuration:

# instantiate IOCSPAdmin COM interface
$ocsp = New-Object -ComObject CertAdm.OCSPAdmin
# connect to Online Responder service
$ocsp.GetConfiguration("dc2", $true)
# instantiate CA certificate object. Specify your own path to a file
$cacert = New-Object Security.Cryptography.X509Certificates.X509Certificate2 "c:\certs\root1.cer"
# get signing certificate from local machine store by thumbprint
$sigcert = gi cert:\ĻocalMachine\My\91FDF227D52E62C071DAB538D01AF3E8036C1180
$revconfig = $ocsp.OCSPCAConfigurationCollection.CreateCAConfiguration("Contoso CA (1)", $cacert.RawData)
# set hash and signing algorithm to SHA1
$revconfig.HashAlgorithm = "sha1"
$revconfig.SigningCertificate = $sigcert.RawData
# set provider ID. It must be "{4956d17f-88fd-4198-b287-1e6e65883b19}"
$revconfig.ProviderCLSID = "{4956d17f-88fd-4198-b287-1e6e65883b19}"

We do not use CAConfig and SigningCertificateTemplate properties because we use dedicated signing certificate and will renew it manually. Now we need to decide which flags to use:

  • OCSP_SF_SILENT
  • OCSP_SF_MANUAL_ASSIGN_SIGNINGCERT
  • OCSP_SF_RESPONDER_ID_KEYHASH

No other flags are required:

$revconfig.SigningFlags = 97

Now we need to create and configure revocation provider – just provide an URL to a Base CRL (and Delta if it is used):

# instantiate and initialize IOCSPPropertyCollection interface:
$OCSPPropCollection = New-Object -ComObject CertAdm.OCSPPropertyCollection
[void]$OCSPPropCollection.InitializeFromProperties($null)
# create property that will store Base CRL URL. URL must be explicitly casted
# to a string array (rather than default object array)
[void]$OCSPPropCollection.CreateProperty("BaseCrlUrls",[String[]]"http://www.contoso.com/pki/contoso_RCA.crl")
# write property collection to ProviderProperties property
$revconfig.ProviderProperties = $OCSPPropCollection.GetAllProperties()

In a given example, only Base CRL is used, so we do not bother ourselves with other properties. Should be enough. Check our $revconfig variable whether all properties are set properly:

PS C:\> $revconfig


Identifier                 : Contoso CA (1)
CACertificate              : {48, 130, 4, 14...}
HashAlgorithm              : sha1
SigningFlags               : 97
SigningCertificate         : {48, 130, 3, 212...}
ReminderDuration           :
ErrorCode                  : 2147483658
CSPName                    :
KeySpec                    :
ProviderCLSID              : {4956d17f-88fd-4198-b287-1e6e65883b19}
ProviderProperties         : {BaseCrlUrls, http://www.contoso.com/pki/contoso_RCA.crl}
Modified                   : True
LocalRevocationInformation :
SigningCertificateTemplate :
CAConfig                   :



PS C:\>

we already set configuration name, binding to CA certificate, hash algorithm, explicit signing certificate and revocation provider (Base CRL URL). If everything is correct, then we can save new configuration:

$ocsp.SetConfiguration("dc2", $true)

Open OCSP.msc console to check the status in visual:

image

Everything is green, so our configuration succeeded.

Bonus stuff

Alternatively, you can use IOCSPAdmin interface to get the status of all revocation configurations:

$ocsp = New-Object -ComObject CertAdm.OCSPAdmin
$ocsp.GetConfiguration("dc2", $true)
$ocsp.OCSPCAConfigurationCollection | Format-Table Identifier, ErrorCode -AutoSize

You cannot call GetConfiguration method twice to connect to Online Responder. If you want to refresh the interface, you have to re-instantiate IOCSPAdmin interface.

PS C:\> $ocsp = New-Object -ComObject CertAdm.OCSPAdmin
PS C:\> $ocsp.GetConfiguration("dc2", $true)
PS C:\> $ocsp.OCSPCAConfigurationCollection | Format-Table Identifier, ErrorCode -AutoSize

Identifier          ErrorCode
----------          ---------
Contoso CA (1)              0
Contoso SHA2 CA (0)         0


PS C:\>

If error code is set to zero, then the configuration is fully working. Any non-zero value means error. As a simple solution you can use the following trick to convert Win32 status code:

[ComponentModel.Win32Exception]0x80070005

Cast error code (in hex or as integer) to Win32Exception class. Win32Exception class translates common (though, not all) Win32 native errors to it’s text representation. Win32 errors are Int32 usually, however, ErrorCode property return unsigned integer (UInt32). Therefore, you should convert UInt32 to hex and then convert it to signed integer and only then bind it to Win32Exception class. Here is an improved example:

$ocsp = New-Object -ComObject CertAdm.OCSPAdmin
$ocsp.GetConfiguration("dc2", $true)
$ocsp.OCSPCAConfigurationCollection | Format-Table Identifier, ErrorCode,
    @{l="Text";e={
        ([ComponentModel.Win32Exception](iex ("0x" + ("{0:x2}" -f $_.ErrorCode)))).Message}
    } -AutoSize
PS C:\> $ocsp.OCSPCAConfigurationCollection | Format-Table Identifier, ErrorCode,
>> @{l="Text";e={
>> ([ComponentModel.Win32Exception](iex ("0x" + ("{0:x2}" -f $_.ErrorCode)))).Message}
>> } -AutoSize
>>

Identifier          ErrorCode Text
----------          --------- ----
Contoso CA (1)              0 The operation completed successfully
Contoso SHA2 CA (0)         0 The operation completed successfully


PS C:\>

HTH


Share this article:

Comments:

Istvan

Is it possible to replace the SigningCertificate from powershell if it's expired without recreating the existing revocation configuration?

Roman

Good article.

Randall Cohen

when an OCSP server reboots an Application event 23 is written and states "The Online Responder Service could not locate a signing certificate for configuration <ServerConfiguration>.(An internal error occurred. 0x80090020 (-2146893792 NTE_FAIL))".  the simple fix is to select "Refresh Configuration Data" from the Array configuration in the OCSP console.  Is there a powershell command to execute the refresh?

Vadims Podāns

No, there is no such equivalent in PowerShell or CLI tools. This functionality exist only in MMC. It is strange, but that's is.

Yoji Tamura

Japanese is translated into English by Google Translate.
hello.
Is there a sample script that assigns a new signing certificate to a registered OCSP revocation configuration?

 

Yoji Tamura

Added to comments.
There are multiple additions to the revocation configuration, each with a corresponding signing certificate.

damien

Hello, 

Thanks for the article.

Should be nice if you can explain how to do with template from domain CA and not local certificate from store.

Thanks


Post your comment:

Please, solve this little equation and enter result below. Captcha