3

I've been working on a lab setting up a two-tier PKI using a Linux (Debian 9 with OpenSSL) root certificate authority and a Windows server 2012 R2 subordinate certificate authority.

When I attempt to install the the signed subordinate certificate on the Windows server I first get a warning stating that the root ca can not be verified. I click OK to ignore the warning after which the ADCS does not start. When I manually start the ADCS I get the Error message;

"The revocation function was unable to check revocation because the revocation server was offline"

I believe the issue is with how I am pointing to the CRL distribution point and AIA on the Linux root CA or how I am setting up IIS on the Windows server (possibly both).

Setup

  • rootca: Linux Debain 9 as root certificate authority
  • testpki: Windows Server 2012 R2 as subordinate certificate authority/IIS
  • dc0: Windows Server 2012 R2 as domain controller

Linux

I set up a custom OpenSSL config file on rootca adding the lines;

authorityInfoAccess = caIssuer;URI:http://testpki.example.com/crld/root.cer
crlDistributionPoints = URI:http://testpki.example.com/crld/root.crl

to the v3_ca and v3_intermediate_ca sections of the config file.

Windows

I set up a DNS record for "testpki.example.com" for name resolution on dc0.

The root certificate from the Linux box is imported to the Trusted Root Certificate Authority directory in the Certificate Authority snap-in on testpki.

After installing IIS on testpki, I set up a virtual directory with the alias crld and copy the root certificate and CRL to this directory.

I am able to connect to IIS when entering the URL "testpki.example.com/crld", but if I enter the URL "testpki.example.com/crld/root.cer" I get a 404 error even though "root.cer" is shown in the "../crld" page index.

the rest of the setup was done following this guide: Using openssl as a root ca for windows

Any insight would be appreciated.

-thanks

certutil -verify -urlfetch ..\subca.cer Output

 Issuer:
    CN=example-TESTPKI-CA
  Name Hash(sha1): e6c59398cbed5b994ff33c6e6380312fe2ad9a4a
  Name Hash(md5): b0f8c7beb298a3ba230f71fbc927b386
Subject:
    CN=example-TESTPKI-CA-Xchg
  Name Hash(sha1): 86f6ae3e12a21350005b9d70b1229ecb1b78dd0b
  Name Hash(md5): dd1324e864c4233d2f87e9c0c342dfcd
Cert Serial Number: 4b0000000478b909e350cb7280000000000004

dwFlags = CA_VERIFY_FLAGS_CONSOLE_TRACE (0x20000000)
dwFlags = CA_VERIFY_FLAGS_DUMP_CHAIN (0x40000000)
ChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT (0x40000000)
HCCE_LOCAL_MACHINE
CERT_CHAIN_POLICY_BASE
-------- CERT_CHAIN_CONTEXT --------
ChainContext.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
ChainContext.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
ChainContext.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)

SimpleChain.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
SimpleChain.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
SimpleChain.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)

CertContext[0][0]: dwInfoStatus=102 dwErrorStatus=0
  Issuer: CN=example-TESTPKI-CA
  NotBefore: 2/7/2018 3:37 PM
  NotAfter: 2/14/2018 3:47 PM
  Subject: CN=example-TESTPKI-CA-Xchg
  Serial: 4b0000000478b909e350cb7280000000000004
  Template: CAExchange
  a13e6c1703f95408910d21dc380818b23c76e79f
  Element.dwInfoStatus = CERT_TRUST_HAS_KEY_MATCH_ISSUER (0x2)
  Element.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
  ----------------  Certificate AIA  ----------------
  Wrong Issuer "Certificate (0)" Time: 0
    [0.0] ldap:///CN=example-TESTPKI-CA,CN=AIA,CN=Public%20Key%20Services,
Services,CN=Configuration,DC=example,DC=com?cACertificate?base?objectCla
certificationAuthority

  Revocation Check Failed "Certificate (1)" Time: 0
    [0.1] ldap:///CN=example-TESTPKI-CA,CN=AIA,CN=Public%20Key%20Services,
Services,CN=Configuration,DC=example,DC=com?cACertificate?base?objectCla
certificationAuthority

  ----------------  Certificate CDP  ----------------
  Verified "Base CRL (02)" Time: 0
    [0.0] ldap:///CN=example,CN=com,CN=CDP,CN=Public%20Key%
ervices,CN=Services,CN=Configuration,DC=example,DC=com?certificateRevoca
nList?base?objectClass=cRLDistributionPoint

  Verified "Delta CRL (02)" Time: 0
    [0.0.0] ldap:///CN=example-TESTPKI-CA,CN=testpki,CN=CDP,CN=Public%20Ke
0Services,CN=Services,CN=Configuration,DC=example,DC=com?deltaRevocation
t?base?objectClass=cRLDistributionPoint

  ----------------  Base CRL CDP  ----------------
  OK "Delta CRL (02)" Time: 0
    [0.0] ldap:///CN=example-TESTPKI-CA,CN=testpki,CN=CDP,CN=Public%20Key%
ervices,CN=Services,CN=Configuration,DC=example,DC=com?deltaRevocationLi
base?objectClass=cRLDistributionPoint

  ----------------  Certificate OCSP  ----------------
  No URLs "None" Time: 0
  --------------------------------
    CRL 02:
    Issuer: CN=example-TESTPKI-CA
    ThisUpdate: 2/7/2018 3:52 PM
    NextUpdate: 2/15/2018 4:12 AM
    7f6e7f6f4d13cd98164e53d35ce406e2dde3dd3a
    Delta CRL 02:
    Issuer: CN=example-TESTPKI-CA
    ThisUpdate: 2/7/2018 3:52 PM
    NextUpdate: 2/9/2018 4:12 AM
    07de3204292fbc0ab4a42cfef02b6b4837a78529
  Application[0] = 1.3.6.1.4.1.311.21.5 Private Key Archival

CertContext[0][1]: dwInfoStatus=102 dwErrorStatus=1000040
  Issuer: CN=rootca
  NotBefore: 2/7/2018 1:17 PM
  NotAfter: 2/6/2023 1:17 PM
  Subject: CN=example-TESTPKI-CA
  Serial: 1000
  d74fdf7e86c80171e91dd72a16a1f8f72c9666a3
  Element.dwInfoStatus = CERT_TRUST_HAS_KEY_MATCH_ISSUER (0x2)
  Element.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
  Element.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
  Element.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)
  ----------------  Certificate AIA  ----------------
  Failed "AIA" Time: 0
    Error retrieving URL: The request is not supported. 0x80070032 (WIN32: 50
ROR_NOT_SUPPORTED)
    testpki.example.com/crld/root.cer

  ----------------  Certificate CDP  ----------------
  Failed "CDP" Time: 0
    Error retrieving URL: Not found (404). 0x80190194 (-2145844844 HTTP_E_STA
_NOT_FOUND)
    http://testpki.example.com/crld/rootca.crl

  ----------------  Certificate OCSP  ----------------
  No URLs "None" Time: 0
  --------------------------------

CertContext[0][2]: dwInfoStatus=10a dwErrorStatus=0
  Issuer: CN=rootca
  NotBefore: 2/7/2018 12:54 PM
  NotAfter: 2/6/2023 12:54 PM
  Subject: CN=rootca
  Serial: 94cb4df27b1cb5a3
  99a30cec9d5dbc21afe5e4b679e5db844f7a9dd0
  Element.dwInfoStatus = CERT_TRUST_HAS_KEY_MATCH_ISSUER (0x2)
  Element.dwInfoStatus = CERT_TRUST_IS_SELF_SIGNED (0x8)
  Element.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
  ----------------  Certificate AIA  ----------------
  Failed "AIA" Time: 0
    Error retrieving URL: The request is not supported. 0x80070032 (WIN32: 50
ROR_NOT_SUPPORTED)
    testpki.example.com/crld/root.cer

  ----------------  Certificate CDP  ----------------
  Failed "CDP" Time: 0
    Error retrieving URL: Not found (404). 0x80190194 (-2145844844 HTTP_E_STA
_NOT_FOUND)
    http://testpki.example/crld/rootca.crl

  ----------------  Certificate OCSP  ----------------
  No URLs "None" Time: 0
  --------------------------------

Exclude leaf cert:
  a7b797168cbc0ff36636479d8cd2de6f2b184355
Full chain:
  7e1caac607a7a5b087b491accf72df2f8d4cf06e
  Issuer: CN=example-TESTPKI-CA
  NotBefore: 2/7/2018 3:37 PM
  NotAfter: 2/14/2018 3:47 PM
  Subject: CN=example-TESTPKI-CA-Xchg
  Serial: 4b0000000478b909e350cb7280000000000004
  Template: CAExchange
  a13e6c1703f95408910d21dc380818b23c76e79f
The revocation function was unable to check revocation because the revocation
rver was offline. 0x80092013 (-2146885613 CRYPT_E_REVOCATION_OFFLINE)
------------------------------------
Revocation check skipped -- server offline
Leaf certificate revocation check passed
CertUtil: -verify command completed successfully.
7
  • run the following command (on Windows CA machine): certutil -verify -urlfetch path\subCAcert.cer and examine errors in URL download section. If you are unsure how to interpret them, put them in your original question so we can assist you.
    – Crypt32
    Feb 7, 2018 at 20:52
  • Your initial test for root.cer is testing you can access the Root CA via HTTP, which is irrelevant to revocation checking. However, the fact that you can't, even though you believe you've uploaded it, suggests your IIS isn't configured correctly. If that's the case, you most probably can't access the CRL (root.crl) via HTTP neither, which is why you get the error message. You won't make progress until you can access testpki.example.com/crld/root.crl and retrieve the CRL (not 404 error) Feb 7, 2018 at 20:56
  • @Crypt32 I ran the command you suggested and added the output to my original question.
    – 0B51D14N
    Feb 7, 2018 at 21:18
  • I asked to run the command against SubCA certificate, not anything else. But certutil error clearly says NotFound (HTTP404). This means that there is no CRL at specified path.
    – Crypt32
    Feb 7, 2018 at 21:27
  • Sorry that was a typo I ran it against root.cer not root.crl
    – 0B51D14N
    Feb 7, 2018 at 21:31

3 Answers 3

4

Ok, that's better now. You have a number of issues here:

  Wrong Issuer "Certificate (0)" Time: 0
    [0.0] ldap:///CN=example-TESTPKI-CA,CN=AIA,CN=Public%20Key%20Services,
Services,CN=Configuration,DC=example,DC=com?cACertificate?base?objectCla
certificationAuthority

This error indicates that wrong subCA certificate is published in Active Directory. You will have to republish subCA certificate to Active Directory by running the following command:

certutil -dspublish -f SubCA.cer SubCA

Now your root CA:

  Failed "AIA" Time: 0
    Error retrieving URL: The request is not supported. 0x80070032 (WIN32: 50
ROR_NOT_SUPPORTED)
    testpki.example.com/crld/root.cer

you mistyped the URL in OpenSSL config. Protocol prefix is missing. You need to add http:// prefix and reissue SubCA certificate.

  Failed "CDP" Time: 0
    Error retrieving URL: Not found (404). 0x80190194 (-2145844844 HTTP_E_STA
_NOT_FOUND)
    http://testpki.example.com/crld/rootca.crl

This URL seems correct (at least, it includes protocol prefix), CA server can access web server, but web server responds with 404, indicating that there is nothing at requested path.


TBH, your setup is not good at all. Too many issues you have, because (as it seems), the design wasn't planned or plan wasn't verified.

Apart from explicit issues, your root CA itself includes CRL Distribution Points (CDP) and Authority Information Access (AIA) extensions, which are redundant. You should remove them from root certificate. AIA is not used in order to avoid cycles during path building. CDP in root certificates is not used, because you can't revoke root (self-signed) certificate, because of chicken-egg issue. But they (CDP and AIA extensions) must be included in issued certificate (i.e. subordinate CA).

I would recommend to roll back all you have done here and start from scratch.

First of all, you need to design your solution, plan all aspects.

  1. Identify applications which will use certificates.
  2. Describe certificate requirements and plan the scope of certificates.
  3. Based on [2] identify certificate templates and their configuration you will use.
  4. Design CA placement diagram and create certificate flow diagram (certificate enrollment, validation by client applications).
  5. Design disaster recovery plan, which will include backup and restore plan.

Otherwise, your solution will worth nothing. Even if this is test deployment, you still have to pass all these steps.

Properly plan CRT/CRL publishing and download URLs. You will need to check it twice, because these issues can't be fixed easily without having to re-deploy all certificates. General suggestions on this subject:

  1. do not use LDAP URLs in CDP/AIA. Consider to use HTTP only.
  2. use dedicated web server to serve CRT/CRL files (do not combine SubCA with web server roles).
  3. do not use CDP/AIA extensions in root certificate
  4. make sure that CRT/CRL files are accessible by all clients (which will use your certificates)

On CDP/AIA extension planning I would suggest to check my blog post: Designing CRL Distribution Points and Authority Information Access locations. Although, the article was written against Microsoft CA, the same principles apply to any other CA implementation, because these are best practices.

1
  • Thanks for the thorough explanation. I noticed the missing prefix as well in the url and checked my config which does contain the http prefix. Not sure what that's about, maybe has something to do with the caIssuers bit. I did a fair bit of planning before starting these test but as I'm fairly new to designing and implementing PKIs it possible my planning was not good at all. I'm done for the day so I'll bookmark your link and get started tomorrow. --Thanks again.
    – 0B51D14N
    Feb 8, 2018 at 0:03
1

I managed to get my test intermediate CA up and running. The issue was more than likely in my OpenSSL config file, specifically the CDP and AIA bits. But, for any one else who might be trying to accomplish something similar I'll describe what I did that ended up working.


You should have a look at the link provided by Crypt32 before starting, it can be found here.


First off, for DNS name resolution, set up A records on a server running the DNS service that is joined to the domain, you'll need records both for the sub CA and the IIS server. Also ensure that the Windows server that is to be used as the intermediate CA is configured to use this DNS server for resolving addresses.



    On the Linux root CA
  • Create a directory to hold your CA
    mkdir -p ./ca/{certs,private}  
    
    chmod 700 ./ca/private  
    
    touch index.txt  
    
    echo 0001 > serial  
    
    echo 0001 > crlnumber
    
  • copy this config file modifying were needed to the ca directory on the Linux root CA
      
    #
    # OpenSSL configuration file.
    #
    
    # Establish working directory.
    
    ROOT_CA_FILENAME                        = rootca           #example ca filename
    HTTP_HOST                               = pki.example.local #example URL for CDP
    
    dir                                     = .
    
    default_ca                              = CA_Default
    
    [ CA_Default ]
    serial                                  = $dir/serial
    database                                = $dir/index.txt
    new_certs_dir                           = $dir/certs
    crlnumber                               = $dir/crlnumber
    default_crl_days                        = 213
    default_md                              = sha256
    preserve                                = no
    email_in_dn                             = no
    nameopt                                 = default_ca
    certopt                                 = default_ca
    policy                                  = policy_any
    private_key                             = $dir/private/$ROOT_CA_FILENAME.key.pem
    certificate                             = $dir/certs/$ROOT_CA_FILENAME.cert.pem
    
    # SET in script: default_days                            = 7305 
    
    
    [ policy_any ]
    countryName                             = optional
    stateOrProvinceName                     = optional
    localityName                            = optional
    organizationName                        = optional
    organizationalUnitName                  = optional
    commonName                              = supplied
    emailAddress                            = optional
    
    [ req ]
    # Options for the `req` tool (`man req`).
    default_bits        = 4096
    distinguished_name  = req_distinguished_name
    string_mask         = utf8only
    
    # SHA-1 is deprecated, so use SHA-2 instead.
    default_md          = sha256
    
    # Extension to add when the -x509 option is used.
    x509_extensions     = v3_ca
    
    [ req_distinguished_name ]
    # See .
    countryName                     = Country Name (2 letter code)
    stateOrProvinceName             = State or Province Name
    localityName                    = Locality Name
    0.organizationName              = Organization Name
    organizationalUnitName          = Organizational Unit Name
    commonName                      = Common Name
    emailAddress                    = Email Address
    
    # Optionally, specify some defaults.
    countryName_default             = 
    stateOrProvinceName_default     = 
    localityName_default            =
    0.organizationName_default      = 
    organizationalUnitName_default  =
    emailAddress_default            =
    
    [ v3_ca ]
    # Extensions for a typical CA (`man x509v3_config`).
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer
    basicConstraints = critical, CA:true
    keyUsage = critical, digitalSignature, cRLSign, keyCertSign
    
    [ v3_intermediate_ca ]
    # Extensions for a typical intermediate CA (`man x509v3_config`).
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer
    basicConstraints = critical, CA:true, pathlen:0
    keyUsage = critical, digitalSignature, cRLSign, keyCertSign
    crlDistributionPoints = URI:http://$HTTP_HOST/crldist/$ROOT_CA_FILENAME.crl
    authorityInfoAccess = caIssuers;URI:http://$HTTP_HOST/crldist/$ROOT_CA_FILENAME.crt
    
    [ usr_cert ]
    # Extensions for client certificates (`man x509v3_config`).
    basicConstraints = CA:FALSE
    nsCertType = client, email
    nsComment = "OpenSSL Generated Client Certificate"
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid,issuer
    keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
    extendedKeyUsage = clientAuth, emailProtection
    
    [ server_cert ]
    # Extensions for server certificates (`man x509v3_config`).
    basicConstraints = CA:FALSE
    nsCertType = server
    nsComment = "OpenSSL Generated Server Certificate"
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid,issuer:always
    keyUsage = critical, digitalSignature, keyEncipherment
    extendedKeyUsage = serverAuth
    
    [ crl_ext ]
    # Extension for CRLs (`man x509v3_config`).
    authorityKeyIdentifier=keyid:always
    
    [ ocsp ]
    # Extension for OCSP signing certificates (`man ocsp`).
    basicConstraints = CA:FALSE
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid,issuer
    keyUsage = critical, digitalSignature
    extendedKeyUsage = critical, OCSPSigning
    
    
  • Generate a key pair
     
    openssl genrsa -aes256 -out private/rootca.key.pem 4096  
    chmod 400 private/rootca.key.pem  
    openssl req -config /path/to/config \  
    -key private/rootca.key.pem \  
    -new -x509 -days 1825 -sha256 -extensions v3_ca \  
    -out certs/rootca.cert.pem  
    
    Enter pass phrase for ca.key.pem: secretpassword
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    -----
    Country Name (2 letter code) [XX]:.
    State or Province Name []:.
    Locality Name []:.
    Organization Name []:.
    Organizational Unit Name []:.
    Common Name []:Test Root CA
    Email Address []:.
    
    chmod 444 certs/rootca.cert.pem
    
  • On a Windows server running IIS
  • Open the IIS manager
  • Expand the directory in the left hand pane, and right click "Default Site". Select add virtual directory
  • In the add virtual directory dialog under "Alias", enter what ever you used for your CDP and AIA URLs in the OpenSSL config file above
  • Under "Physical Path", enter the path to the directory you are going to use for certificate enrollment, press enter and click ok
  • Back in IIS manager, while your new virtual directory is selected in the left pane, in the middle pane select directory browsing . In the details pane to the right select enable
  • With the virtual directory still selected in the left pane, select configuration editor
  • In the configuration editor, in the drop down menu navigate to system.webServer\security\requestFiltering and set "Double Escaping" to True
  • Apply changes
  • You may need to mess with the permissions of the virtual directory. Also, you can now import the rootca certificate to the IIS server's local computer Trusted Root Certificate Authority directory in the MMC certificates snap-in on the IIS server

  • On the Windows server to be used as the intermediate CA
  • Install the Active Directory Certificate Services via server manager (note: that this computer must be joined to a domain)
  • Make sure to install the management features, select Enterprise CA for role service, and Subordinate CA for the CA type in the role installation wizard.
  • For the private key setup select new private key, leave the MS-RSA selected in the drop down menu, for the hash algorithm select sha256, and set the key length to 4096. This will generate a CSR that will be copied to the Linux root CA
  • You can now import the rootca certificate to the mmc certificates snap-in

  • Back on the Linux CA
  • After copying your CSR to the directory on the root CA you created earlier run:
    openssl ca -config /path/to/config -extensions v3_intermediate_ca -days 1825 -notext -md sha256  -in ca/"CSR File" -out ca/certs/subca.cer
  • You now have a signed intermediate CA certificate in the ca/certs directory that can be copied to the Windows sub CA
  • Before installing the subca certificate to ADCS generate a CRL with the following command:
    openssl ca -gencrl -out rootca.crl.pem -config /path/to/config
    and copy the generated crl and root certifiate to the virtual directory that was created on the IIS server earlier

  • Back on the Windows Intermediate server
  • Ensure that the FQDN of the IIS server is resolvable form the intermediate CA, enter the URL used for the CDP in the config file above if you used the CA_FILENAME and HTTP_HOST examples in the config file you would enter "http://pki.example.local/crldist/rootca.crl" in your browser's URL bar and you should be prompted to download or open the crl file. If you get a 404 error check the permissions on the virtual directory used for the CDP and if you get a 401 error check what the authentication settings are for the IIS server
  • Open the "Certificate Authority" application from the server manager and right click the subca in the left pane, select import
  • Browse to the location of the subca.cer file you copied over from the Linux root CA. Click ok

Your Windows intermediate CA should now be up and running.

Sources

  • Using OpenSSL as The Root CA For Windows
  • Create a Certificate Revocation List Distribution Point
  • Create a CRL
    0

    You may want to try disabling the CRL check per the following:

    https://social.technet.microsoft.com/wiki/contents/articles/964.certificate-revocation-list-crl-verification-an-application-choice.aspx

    certutil –setreg ca\CRLFlags +CRLF_REVCHECK_IGNORE_OFFLINE
    
    8
    • 1
      Disabling revocation checking is not the smartest solution.
      – Crypt32
      Feb 7, 2018 at 20:50
    • This does allow ADCS to start, but does this mean that CRL is disabled all together if it comes back offline?
      – 0B51D14N
      Feb 7, 2018 at 20:56
    • @lscanni: It means you need to fix the communication issues between your sub and root CA. If it works with that setting, that means your CRL isn't accessible from the sub CA. A packet capture on the sub CA should confirm. If the CRL accessibility may be an issue or not robust, or you cannot host a local copy of the CRL, it may need to be left disabled.
      – Greg Askew
      Feb 7, 2018 at 21:02
    • 1
      ADCS will start, but end application will fail anyway, so this setting barely solves anything. This is why I'm against it. You have to ensure that your CRL is available to all clients 24/7/365.
      – Crypt32
      Feb 7, 2018 at 21:03
    • you need to fix the communication issues between your sub and root CA -- SubCA and RootCA shouldn't communicate to each other. RootCA doesn't communicate to anyone. SubCA communicates with CRL provided by root (in a given case).
      – Crypt32
      Feb 7, 2018 at 21:05

    You must log in to answer this question.

    Not the answer you're looking for? Browse other questions tagged .