Understanding and Implementing PKI with OpenSSL

Contents

Introduction

This post will aim to give an overview of TLS and public key infrastructure (PKI). This first part of this post will give a theoretical overview of how it works. The second part of the post will demonstrate how to setup a CA with OpenSSL and create certificates for web servers and code singing purposes. Furthermore, the code signing certificate will be used to sign a binary on a Windows machine. For more detailed information about TLS and PKI I recommend the Bulletproof SSL and TLS book, there are some diagrams in this post that are actually from this book.

PKI in Theory

TLS

Transport Layer Security (TLS) is a cryptographic protocol that has the goal of securing a line of communication between two parties. There are a few components of TLS, two of the most important are the authentication and encryption components.

Usually when checking the cipher suite of a website using TLS you may see a string such as the following: Cipher Suite Construction (Bulletproof SSL and TLS Book)

Cipher Suite Construction (Bulletproof SSL and TLS Book)

From this cipher suite we can figure out which cryptographic primitives are being used for what task. RSA is being used for authentication, there are some websites that use ECDSA for this task. The authentication mechanism relies on public key cryptography. During the beginning stages of the TLS handshake the client will send the server a message encrypted with the servers public key. The only way the server can read the message is by having in its possession the private key, this will prove to the user the identity of the server. If the server is unsuccessful at decrypting the message the TLS connection cannot move forward to the next phase.

The second important component is encryption, this is handled by the symmetric cipher AES with a key size of 128 bits using the GCM mode. Its important to understand that AES will take a preshared secret that both parties must be in possession of, this is where the key exchange phase comes into play. Diffie Hellmen (DHE), or in this case Elliptic-Curve Diffie Hellman (ECDHE), is used to create a shared secret between two parties communicating over an unsecure medium. Once this shared secret is created it can be fed into AES which will encrypt the data. After a set time the key exchange process will renegotiate a new shared secret.

Now, there is a very important concept called Perfect Forward Secrecy. What this allows us to achieve is the separation between the key used by the server for authentication and the key used for encryption. This extremely important as the key used for authentication is stored on the web servers disk, if it is compromised it is impossible to decrypt any intercepted TLS traffic as that is not the key used for encryption. The key used for encryption was generated using the DHE algorithm and is considered ephemeral, which means it only exists for a specific period of time during a TLS session.

In TLS 1.2 a user has the ability to pick the cipher suite, one of the options is to use the RSA key for authentication as the encryption key. This will not provide any Perfect Forward Secrecy, a shared secret will be generated and encrypted with the RSA key which will be used for encryption by both parties. This will allow an attacker in possession of the RSA private key to decrypt TLS traffic on the fly, this can be dangerous if in the hands of an attacker but at the same time useful if used by a company to inspect TLS traffic for signs of malicious intent. One interesting thing to note is that ECDHE is made mandatory in TLS 1.3, this means that it will not be possible to intercept TLS traffic using this method.

Certificates

People connect to websites every day using TLS, as stated in the previous section on important component is authentication. A user has to know if the website they are connecting to is legitimate or an imposter website. This is done by checking the websites certificate using the X.509 certificate provided by the website and the public key. Below can be seen an outline of the contents of a X.509 certificate:

X.509 Public Key Certificates (Microsoft Docs)

The X.509 certificate contains important information about the entity, such as a website or user. It may contain information such as the domain of a website, when the certificate expires, and who issued the certificate. This certificate also contains the public key of the entity, which is used during the TLS negotiation phase.

One interesting problem revolves around how a user can confirm that a certificate is a legitimate certificate associated with a specific entity. For example, how can you know that the certificate provided by your banks website is actually from the bank and not from a attacker siting in a coffee shop. This issue is solved by using certificate authorities, which are discussed in the next section. For this section the most important thing to understand is that entities, such as websites or users, can be represented using certificates.

Certificate Authority

A certificate authority (CA) is used as a central root of trust that users inherently trust. Now lets go back to the problem at hand, how can we know if a certificate is trust worthy? We can confirm the legitimacy of a certificate by checking if it is singed by a valid CA. Lets look at the example below of the certificate hierarchy for this website:

Certificate Hierarchy

We can see that there are three entities, DST Root CA, Let’s Encrypt Authority, and thinkbox.dev. Lets start from the bottom. When you initially connect to this website you will receive a certificate from the webserver, this is the certificate that identifies the thinkbox.dev entity. In order to confirm this is a legitimate certificate you check that it is singed by the Let’s Encrypt Authority intermediate CA. After a check will be performed on the Let’s Encrypt Authority intermediate CA certificate to confirm that it is singed by DST Root CA. If all these checks pass we know that thinkbox.dev is a legitimate certificate.

DST Root CA is the Root CA, it is self singed. This CA’s certificate is stored on a machine and is not transferred over the network. The root of trust lies with the Root CA. Lets Encrypt Authority is considered an intermediate CA as it is used to sign certificates for websites. The Root CA key is considered important and is stored offline most of the time.

Through this mechanism we now have a method of verifying the identity of an entity before establishing a secure connection. Just to clarify quickly take a look at the diagram below:

Certificate Chain Bulletproof SSL and TLS Book

The Root CA is stored on the system, either with the operating system or the browser. It is never transferred over the network. The intermediate CA and the end entity certificate are bundled together, for example the thinkbox.dev and Lets Encrypt Authority CA certificates are bundled into a single file referred to as the certificate chain. There is no real reason to hold the intermediate CA certificate on a system as its identity can also be verified through the Root CA. Furthermore, the validity time of the intermediate certificate is usually much less that the Root CA and will need to be changed more often over a long period of time.

Security Features

HSTS

HTTP Strict Transport Security (HSTS) is a mechanism that informs the browser it should interact with a website using TLS. You can think of this as caching which sites use TLS in a way, however, this is done for security reasons to prevent downgrade attacks and cookies being transferred over plaintext. This is a feature that needs to be configured on the web server serving a TLS connection in order to server the HSTS in the HTTP answer, the following shows an example of a Nginx HSTS configatiton setting:

1
Strict-Transport-Security: max-age=31536000; includeSubDomains

As can be seen HSTS is enabled for all a domain and all of its subdomains for 31536000 seconds, which is around 1 year.

There also exists HSTS preloading where a browser already knows it should connect using TLS from a list. All .dev domains are included in this HSTS list, and there are methods of adding your own domain to this list. More information about be found in these two blog posts .

CSP

Content Security Policy is a mechanism that aims to dictate what content can load on a web page, for example it is possible to prevent inline Javascript from running and control which sources Javascript code can load from. Such a feature can mitigate the effects of a Cross Site Scripting attack. It is also possible to control where other forms of content load from, such as limiting images to a single domain. For more information please view this blog post .

Certificate Pinning

Certificate pinning aims to make a connection between a service and the certificate it provides. For example, when you load your browser and go to a website there will be a check made in order to confirm that the certificate really does belong to the service you are connecting to. Google used to do this with their websites on the Chrome browser, however, they seem to have backed away from this feature. Certificate pinning is not widely adopted by browsers and is not commonly used.

Revocation

Revoking certificates is useful in a few scenarios, one of which is if the private key of your certificate is leaked. There are two revocation methods that can be used depending on the application.

CRL

A Certificate Revocation List (CRL) is generated from a list that holds all the certificates that have been revoked. Modern browsers do not support CRL files, however, there are applications such as OpenVPN which do support it. If a user of a OpenVPN server lost their private key the administrator can revoke the certificate so an attacker cannot connect to it.

OCSP

Online Certificate Status Protocol (OCSP) is a protocol that works over HTTP which can tell a client if a specific certificate is revoked or not. A client connects to a server called the OCSP responded, it sends a query for a specfic certificate and receives a reply. This is the method that modern browsers use.

PKI in Practice

Overview

This section will aim to create a set of CA’s and certificates for some services using OpenSSL. The following diagram shows the PKI layout overview:

PKI Diagram

We will be generating a RootCA first. Next we will create two intermediate CA’s for web services and code singing. Lastly, we will create a certificate for two web services and sign them with the Sub CA.

The first web service will be a simple static web page. The second will be a OCSP responder, this needs a certificate because it works over HTTP in plain text and needs to be singed to prevent tampering.

Lets begin by setting up a directory structure as seen below in the code snippet. We are going to have 5 folders for all the entities we want to represent.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[user@CAServer ~]$ cd ~

[user@CAServer ~]$ mkdir RootCA SubCA CodeSignCA IssuedWebCerts
[user@CAServer ~]$ mkdir RootCA/certs RootCA/conf RootCA/db RootCA/issued RootCA/private

[user@CAServer ~]$ mkdir SubCA/certs SubCA/conf SubCA/db SubCA/issued SubCA/private
[user@CAServer ~]$ mkdir CodeSignCA/conf CodeSignCA/issued CodeSignCA/private

[user@CAServer ~]$ mkdir OCSPCert
[user@CAServer ~]$ mkdir OCSPCert/private OCSPCert/issued


[user@CAServer ~]$ mkdir IssuedWebCerts/webserver.test.net
[user@CAServer ~]$ mkdir IssuedWebCerts/webserver.test.net/conf IssuedWebCerts/webserver.test.net/issued IssuedWebCerts/webserver.test.net/private

You must also make sure that you have the configuration files for OpenSSL on the system and in the proper location, if not the commands that follow in the next section will not work.

Scroll down to the appendix in order to view the configuration files and place then into the correct location as seen in the code snippet below.

1
2
3
4
[user@CAServer ~]$ cp root-ca.conf RootCA/conf/root-ca.conf
[user@CAServer ~]$ cp subca-ca.conf SubCA/conf/subca-ca.conf
[user@CAServer ~]$ cp codesign-ca.conf CodeSignCA/conf/codesign-ca.conf
[user@CAServer ~]$ cp webcert.conf IssuedWebCerts/webserver.test.net/conf/webcert.conf

Create Root CA

In this section we will generate the Root CA key pair and create a certificate. The following shows the directory structure you should have setup.

1
2
3
4
5
6
7
8
[user@CAServer RootCA]$ ls -l
total 0
drwxr-xr-x. 2 user user 6 Nov  9 22:12 certs
drwxr-xr-x. 2 user user 26 Nov  9 22:10 conf
drwxr-xr-x. 2 user user  6 Nov  9 22:11 db
drwxr-xr-x. 2 user user  6 Nov  9 22:12 issued
drwxr-xr-x. 2 user user  6 Nov  9 22:11 private
[user@CAServer RootCA]$

Begin by creating three files, root-ca.db, root-ca.db.attr, and root-ca-crt-srl. The following list shows a short description of each file created.

  • root-ca.db: This text database will hold a list of issued certificates and there state of validity, that is whether they where revoked or not.
  • root-ca.db.attr: A file with attribute set, for example it can allow a CA to issue multiple certificates with the same subject field.
  • root-ca-crt.srl: This contains the serial number that will be used by the CA, this is supposed to be a unique number among all CA’s. There are standards that dictate this value should have 64 bits of entropy .
1
2
3
[user@CAServer RootCA]$  touch db/root-ca.db
[user@CAServer RootCA]$  touch db/root-ca.db.attr
[user@CAServer RootCA]$ openssl rand -hex 16 > db/root-ca.crt.srl

Now the Root CA certificate can be created. The first command below will create a Certificate Signing Request (CSR), which is a file that contains a certificate which needs to be signed by a CA. Since the Root CA is a self signed CA the second command will create a self singed certificate from the CSR.

1
2
[user@CAServer RootCA]$  openssl req -new -config conf/root-ca.conf -out root-ca.csr -keyout private/root-ca.key
[user@CAServer RootCA]$  openssl ca -selfsign -config conf/root-ca.conf -in root-ca.csr -out issued/root-ca.crt -extensions root_ca_ext -days 3650

Create Intermediate CA

In this section we will generate the Intermediate CA key pair for Sub CA and create a certificate. The following shows the directory structure you should have setup.

1
2
3
4
5
6
7
8
[user@CAServer SubCA]$ ls -l
total 0
drwxr-xr-x. 2 user user  6 Nov  9 23:23 certs
drwxr-xr-x. 2 user user 27 Nov  9 23:37 conf
drwxr-xr-x. 2 user user  6 Nov  9 23:23 db
drwxr-xr-x. 2 user user  6 Nov  9 23:23 issued
drwxr-xr-x. 2 user user  6 Nov  9 23:23 private
[user@CAServer SubCA]$

Just like with the Root CA the initial setup files must be created, for a description of each reference the previous section.

1
2
3
[user@CAServer SubCA]$ touch db/subca-ca.db
[user@CAServer SubCA]$ touch db/subca-ca.db.attr
[user@CAServer SubCA]$ openssl rand -hex 16 > db/subca-ca.crt.srl

Once again we begin by creating a CSR for the Sub CA in the first command. This time we head over to the RootCA directory and use the Root CA certificate and key in order to sign the CSR. Lastly, we create a certificate chain which will contain the RootCA and the SubCA, this will be used as input for our OCSP responder in a later section.

1
2
3
4
5
[user@CAServer SubCA]$ openssl req -new -config conf/subca-ca.conf -out subca-ca.csr -keyout private/subca-ca.key

[user@CAServer RootCA]$ openssl ca -config conf/root-ca.conf -in ../SubCA/subca-ca.csr -out ../SubCA/issued/subca-ca.crt -extensions signing_ca_ext

[user@CAServer SubCA]$ cat issued/subca-ca.crt ../RootCA/issued/root-ca.crt > subca-ca_chain.crt

Create Code Signing CA

In this section we will generate the code signing CA. The following shows the directory structure you should have setup.

1
2
3
4
5
6
[user@CAServer CodeSignCA]$ ls -l
total 0
drwxr-xr-x. 2 user user 30 Nov  9 23:56 conf
drwxr-xr-x. 2 user user  6 Nov  9 23:52 issued
drwxr-xr-x. 2 user user  6 Nov  9 23:52 private
[user@CAServer CodeSignCA]$

Just as before we begin by generating a CSR. We go to the RootCA directory in order to sign the Code Signing CA CSR with the RootCA key. Once this is finished we package the Code Signing certificate and private key in a PKCS12 format file. We do this in order to reference a single file on a Windows machine we will use to sign application in a later section.

1
2
3
4
5
[user@CAServer CodeSignCA]$ openssl req -new -config conf/codesign-ca.conf -out codesign-ca.csr -keyout private/codesign-ca.key

[user@CAServer RootCA]$ openssl ca -config conf/root-ca.conf -in ../CodeSignCA/codesign-ca.csr -out ../CodeSignCA/issued/codesign-ca.crt -extensions codesign_ca_ext

[user@CAServer CodeSignCA]$ openssl pkcs12 -export -out codesignca.pfx -in issued/codesign-ca.crt -inkey private/codesign-ca.key

Web Server Certificate

Since we will have a website with TLS we will create a certificate for it. The following shows a directory structure that should match yours.

1
2
3
4
5
6
[user@CAServer webserver.test.net]$ ls -l
total 0
drwxr-xr-x. 2 user user 6 Nov 10 00:35 conf
drwxr-xr-x. 2 user user 6 Nov 10 00:35 issued
drwxr-xr-x. 2 user user 6 Nov 10 00:35 private
[user@CAServer webserver.test.net]$

We begin by generating the key and CSR for the certificate in the first command. After, we go to SubCA in order to sign the CSR of the web server. Lastly, we create a certificate chain file which will contain the web server certificate and the Sub CA certificate.

1
2
3
4
5
[user@CAServer webserver.test.net]$ openssl req -new -config conf/webcert.conf -out webserver.test.net.csr -keyout private/webserver.test.net.key

[user@CAServer SubCA]$ openssl ca -config conf/subca-ca.conf -in ../IssuedWebCerts/webserver.test.net/webserver.test.net.csr -out ../IssuedWebCerts/webserver.test.net/issued/webserver.test.net.crt -extensions server_ext

[user@CAServer webserver.test.net]$ cat issued/webserver.test.net.crt ../../SubCA/issued/subca-ca.crt > webserver.test.net_chain.crt

Create OCSP Certificate

Lastly, since OCSP works over HTTP we need to sign the message with ac certificate. Within the OCSP directory create a new CSR for the OCSP certificate. Next, go into the SubCA and sign the CSR.

1
2
3
[user@CAServer OCSPCert]$ openssl req -new -config ../SubCA/conf/subca-ca.conf -out oscp.csr -keyout private/oscp.key

[user@CAServer SubCA]$ openssl ca -config conf/subca-ca.conf -in ../OCSPCert/oscp.csr -out ../OCSPCert/issued/ocsp.crt -extensions ocsp_ext

PKI in Action

This section will aim to demonstrate the PKI in action by showing it working within the browser on a website, and signing Windows applications with the Code Signing CA.

Using Website Certificate

A web server was configured along with DNS for the webserver.test.net domain. On a Windows machine the Root CA was imported into the root CA store. As can be seen below Firefox tells us we have a secure connection to the web server.

Website Secured with TLS

Upon further inspection we can see a familiar certificates hierarchy. We have the Root CA on the system and received the Sub CA and web server certificate from the web server. The certificates all validates and Firefox tells us we have a secure connection.

Certificate Hierarchy

Revoking Website Certificate

Since we connected succesfully to the web server we will now revboke the certificate. Below is the command used to revoke the certificate.

1
[user@CAServer SubCA]$ openssl ca -config /root/SubCA/conf/subca-ca.conf -revoke /root/IssuedWebCerts/webserver.test.net/issued/webserver.test.net.crt

The following command will run a OCSP responder for clients to query.

1
[root@CAServer ~]$ openssl ocsp -port 10.0.0.2:80 -text -sha256 -index SubCA/db/subca-ca.db -CA SubCA/subca-ca_chain.crt -rkey OCSPCert/private/oscp.key -rsigner OCSPCert/issued/ocsp.crt

Now before connecting one thing should be pointed out. OCSP is by default set to soft fail, this means even if the certificate is invalid the connection will be allowed. A hard fail can cause issues if the OCSP responder cannot be reached, for example if the CA’s infrastructure goes down. In order to set it to hard fail in Firefox set the security.OCSP.require option to true in the about:config settings.

After this is done browsing to the website greets us with an error preventing us from getting access.

OCSP Browser Error

Looking in Wireshark we can see a request was sent, in the reply within the red rectangle we can see that the OCSP responder notifes us that the certificate is revoked.

OCSP Wireshark Traffic

Signing an Windows Applications

In order to sign Windows applications a Windows machine is needed, I used Windows Server 2019 for this task. In order to sign applications the signtool program is needed, this can be downloaded thought he Windows SDK kit. As seen below you only need to select the “Windows SDK Signing Tools for Desktop Apps”.

Installing Windows SDK Signing Tools

Transfer the Code Sign CA PKCS12 format file created onto the Windows machine. Below is a command shown which will sign a executable file. We need to specfy the PKCS12, the password, and a timestamp server. The timestamp server is used to allow ‘signatures to be verifiable even after the certificates used for signature have expired‘ .

1
2
3
4
5
C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64>signtool sign /f "C:\Users\Admin\Downloads\codesign-ca.p12" /p supersecretpassword /tr http://timestamp.digicert.com /td sha256 /fd sha256 /a "C:\Users\Admin\Downloads\main.exe"
Done Adding Additional Store
Successfully signed: C:\Users\Admin\Downloads\main.exe

C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64>

Below can be seen a PowerShell Cmdlet is being used to sign a PowerShell script. The same idea applies as to the binary executable file.

1
Set-AuthenticodeSignature -Certificate (Get-PfxCertificate -FilePath .\codesignca.pfx) -TimestampServer "http://timestamp.digicert.com" -HashAlgorithm SHA256 -FilePath .\MyScript.ps1

Now we can see that the executable file has a signature.

Signed Binary

The PowerShell script also has a signature.

Signed PowerShell Script

Looking at the certificate path we can see these files have been signed with the Code Sign CA, which has been verified by the Root CA.

Certificate Path

References

Appendix

root-ca.conf

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
[ default ]
ca                      = root-ca               # CA name
dir                     = .                     # Top dir
base_url                = http://pki.test.net  # CA base URL
aia_url                 = $base_url/$ca.cer     # CA certificate URL
crl_url                 = $base_url/$ca.crl     # CRL distribution point
name_opt                = multiline,-esc_msb,utf8 # Display UTF-8 characters
openssl_conf            = openssl_init          # Library config section

# CA certificate request

[ req ]
default_bits            = 4096                  # RSA key size
encrypt_key             = yes                   # Protect private key
default_md              = sha2                  # MD to use
utf8                    = yes                   # Input is UTF-8
string_mask             = utf8only              # Emit UTF-8 strings
prompt                  = no                    # Don't prompt for DN
distinguished_name      = ca_dn                 # DN section
req_extensions          = ca_reqext             # Desired extensions

[ ca_dn ]
countryName             = "TE"
organizationName        = "TestPKI Root"
organizationalUnitName  = "testPKI Root CA"
commonName              = "TestPKI Root"

[ ca_reqext ]
keyUsage                = critical,keyCertSign,cRLSign
basicConstraints        = critical,CA:true
subjectKeyIdentifier    = hash

# CA operational settings

[ ca ]
default_ca              = root_ca               # The default CA section

[ root_ca ]
certificate             = $dir/issued/$ca.crt       # The CA cert
private_key             = $dir/private/$ca.key # CA private key
new_certs_dir           = $dir/certs           # Certificate archive
serial                  = $dir/db/$ca.crt.srl # Serial number file
crlnumber               = $dir/db/$ca.crl.srl # CRL number file
database                = $dir/db/$ca.db # Index file
unique_subject          = no                    # Require unique subject
default_days            = 3652                  # How long to certify for
default_md              = sha1                  # MD to use
policy                  = match_pol             # Default naming policy
email_in_dn             = no                    # Add email to cert DN
preserve                = no                    # Keep passed DN ordering
name_opt                = $name_opt             # Subject DN display options
cert_opt                = ca_default            # Certificate display options
copy_extensions         = none                  # Copy extensions from CSR
x509_extensions         = signing_ca_ext        # Default cert extensions
default_crl_days        = 30                    # How long before next CRL
crl_extensions          = crl_ext               # CRL extensions

[ match_pol ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied

[ any_pol ]
domainComponent         = optional
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = optional
emailAddress            = optional

# Extensions

[ root_ca_ext ]
keyUsage                = critical,keyCertSign,cRLSign
basicConstraints        = critical,CA:true
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always

[ signing_ca_ext ]
keyUsage                = critical,keyCertSign,cRLSign
basicConstraints        = critical,CA:true,pathlen:0
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always
authorityInfoAccess     = @issuer_info
crlDistributionPoints   = @crl_info
authorityInfoAccess     = OCSP;URI:http://ocsp.test.net:80

[ codesign_ca_ext ]
keyUsage                = critical,digitalSignature
extendedKeyUsage        = critical,codeSigning
subjectKeyIdentifier    = hash
authorityInfoAccess     = @issuer_info
crlDistributionPoints   = @crl_info
authorityInfoAccess     = OCSP;URI:http://ocsp.test.net:80

[ ocsp_ca_ext ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning

[ crl_ext ]
authorityKeyIdentifier  = keyid:always
authorityInfoAccess     = @issuer_info

[ issuer_info ]
caIssuers;URI.0         = $aia_url

[ crl_info ]
URI.0                   = $crl_url

# Policy OIDs

[ openssl_init ]
oid_section             = additional_oids

[ additional_oids ]

subca-ca.conf

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
[ default ]
ca                      = subca-ca                # CA name
dir                     = .                     # Top dir
base_url                = http://subca.test.net/ca    # CA base URL
aia_url                 = $base_url/$ca.cer     # CA certificate URL
crl_url                 = $base_url/$ca.crl     # CRL distribution point
name_opt                = multiline,-esc_msb,utf8 # Display UTF-8 characters

# CA certificate request

[ req ]
default_bits            = 4096                  # RSA key size
encrypt_key             = yes                   # Protect private key
default_md              = sha2                  # MD to use
utf8                    = yes                   # Input is UTF-8
string_mask             = utf8only              # Emit UTF-8 strings
prompt                  = no                    # Don't prompt for DN
distinguished_name      = ca_dn                 # DN section
req_extensions          = ca_reqext             # Desired extensions

[ ca_dn ]
countryName             = "TE"
organizationName        = "TestPKI Sub"
organizationalUnitName  = "test.net Sub CA"
commonName              = "TestPKI Sub"

[ ca_reqext ]
keyUsage                = critical,keyCertSign,cRLSign
basicConstraints        = critical,CA:true,pathlen:0
subjectKeyIdentifier    = hash

# CA operational settings

[ ca ]
default_ca              = subca_ca                # The default CA section

[ subca_ca ]
certificate             = $dir/issued/$ca.crt       # The CA cert
private_key             = $dir/private/$ca.key
new_certs_dir           = $dir/certs           # Certificate archive
serial                  = $dir/db/$ca.crt.srl # Serial number file
crlnumber               = $dir/db/$ca.crl.srl # CRL number file
database                = $dir/db/$ca.db # Index file
unique_subject          = no                    # Require unique subject
default_days            = 365                   # How long to certify for
default_md              = sha256                # MD to use
policy                  = match_pol             # Default naming policy
email_in_dn             = no                    # Add email to cert DN
preserve                = no                    # Keep passed DN ordering
name_opt                = $name_opt             # Subject DN display options
cert_opt                = ca_default            # Certificate display options
copy_extensions         = copy                  # Copy extensions from CSR
x509_extensions         = server_ext            # Default cert extensions
default_crl_days        = 1                     # How long before next CRL
crl_extensions          = crl_ext               # CRL extensions

[ match_pol ]
countryName             = optional                 # Must match 'NO'
stateOrProvinceName     = optional              # Included if present
localityName            = optional              # Included if present
organizationName        = optional                 # Must match 'Green AS'
organizationalUnitName  = optional              # Included if present
commonName              = supplied              # Must be present

[ extern_pol ]
countryName             = supplied              # Must be present
stateOrProvinceName     = optional              # Included if present
localityName            = optional              # Included if present
organizationName        = supplied              # Must be present
organizationalUnitName  = optional              # Included if present
commonName              = supplied              # Must be present

[ any_pol ]
domainComponent         = optional
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = optional
emailAddress            = optional

# Extensions

[ server_ext ]
keyUsage                = critical,digitalSignature,keyEncipherment
basicConstraints        = CA:false
extendedKeyUsage        = serverAuth,clientAuth
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always
authorityInfoAccess     = @issuer_info
crlDistributionPoints   = @crl_info
authorityInfoAccess     = OCSP;URI:http://ocsp.test.net:80

[ client_ext ]
keyUsage                = critical,digitalSignature
basicConstraints        = CA:false
extendedKeyUsage        = clientAuth
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always
authorityInfoAccess     = @issuer_info
crlDistributionPoints   = @crl_info

[ ocsp_ext ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning

[ crl_ext ]
authorityKeyIdentifier  = keyid:always
authorityInfoAccess     = @issuer_info

[ issuer_info ]
caIssuers;URI.0         = $aia_url

[ crl_info ]
URI.0                   = $crl_url

codesign-ca.conf

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
[ default ]
ca                      = codesign-ca                # CA name
dir                     = .                     # Top dir
base_url                = http://codesign.test.net/ca    # CA base URL
aia_url                 = $base_url/$ca.cer     # CA certificate URL
crl_url                 = $base_url/$ca.crl     # CRL distribution point
name_opt                = multiline,-esc_msb,utf8 # Display UTF-8 characters

# CA certificate request

[ req ]
default_bits            = 4096                  # RSA key size
encrypt_key             = yes                   # Protect private key
default_md              = sha2                  # MD to use
utf8                    = yes                   # Input is UTF-8
string_mask             = utf8only              # Emit UTF-8 strings
prompt                  = no                    # Don't prompt for DN
distinguished_name      = ca_dn                 # DN section
req_extensions          = ca_reqext             # Desired extensions

[ ca_dn ]
countryName             = "TE"
organizationName        = "TestPKI CodeSign"
organizationalUnitName  = "test.net CodeSign"
commonName              = "TestPKI CodeSign"

[ ca_reqext ]
keyUsage                = critical,digitalSignature
extendedKeyUsage        = critical,codeSigning
subjectKeyIdentifier    = hash

# CA operational settings

[ ca ]
default_ca              = codesign_ca                # The default CA section

[ codesign_ca ]
certificate             = $dir/issued/$ca.crt       # The CA cert
private_key             = $dir/private/$ca.key # CA private key
new_certs_dir           = $dir/certs           # Certificate archive
serial                  = $dir/db/$ca.crt.srl # Serial number file
crlnumber               = $dir/db/$ca.crl.srl # CRL number file
database                = $dir/db/$ca.db # Index file
unique_subject          = no                    # Require unique subject
default_days            = 365                   # How long to certify for
default_md              = sha256                # MD to use
policy                  = match_pol             # Default naming policy
email_in_dn             = no                    # Add email to cert DN
preserve                = no                    # Keep passed DN ordering
name_opt                = $name_opt             # Subject DN display options
cert_opt                = ca_default            # Certificate display options
copy_extensions         = copy                  # Copy extensions from CSR
x509_extensions         = server_ext            # Default cert extensions
default_crl_days        = 1                     # How long before next CRL
crl_extensions          = crl_ext               # CRL extensions

[ match_pol ]
countryName             = match                 # Must match 'NO'
stateOrProvinceName     = optional              # Included if present
localityName            = optional              # Included if present
organizationName        = match                 # Must match 'Green AS'
organizationalUnitName  = optional              # Included if present
commonName              = supplied              # Must be present

[ extern_pol ]
countryName             = supplied              # Must be present
stateOrProvinceName     = optional              # Included if present
localityName            = optional              # Included if present
organizationName        = supplied              # Must be present
organizationalUnitName  = optional              # Included if present
commonName              = supplied              # Must be present

[ any_pol ]
domainComponent         = optional
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = optional
emailAddress            = optional

# Extensions

[ server_ext ]
keyUsage                = critical,digitalSignature,keyEncipherment
basicConstraints        = CA:false
extendedKeyUsage        = serverAuth,clientAuth
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always
authorityInfoAccess     = @issuer_info
crlDistributionPoints   = @crl_info

[ client_ext ]
keyUsage                = critical,digitalSignature
basicConstraints        = CA:false
extendedKeyUsage        = clientAuth
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always
authorityInfoAccess     = @issuer_info
crlDistributionPoints   = @crl_info

[ crl_ext ]
authorityKeyIdentifier  = keyid:always
authorityInfoAccess     = @issuer_info

[ issuer_info ]
caIssuers;URI.0         = $aia_url

[ crl_info ]
URI.0                   = $crl_url

webcert.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[ default ]
SAN                     = DNS:webserver.test.net    # Default value / [S]ubject[A]lt[N]ame

[ req ]
default_bits            = 4096                  # RSA key size
encrypt_key             = no                    # Protect private key
default_md              = sha2                  # MD to use
utf8                    = yes                   # Input is UTF-8
string_mask             = utf8only              # Emit UTF-8 strings
prompt                  = yes                   # Prompt for DN
distinguished_name      = server_dn             # DN template
req_extensions          = server_reqext         # Desired extensions

[ server_dn ]
countryName             = "1. Country Name (2 letters) (eg, US)       "
countryName_max         = 2
stateOrProvinceName     = "2. State or Province Name   (eg, region)   "
localityName            = "3. Locality Name            (eg, city)     "
organizationName        = "4. Organization Name        (eg, company)  "
organizationalUnitName  = "5. Organizational Unit Name (eg, section)  "
commonName              = "6. Common Name              (eg, FQDN)     "
commonName_max          = 64

[ server_reqext ]
keyUsage                = critical,digitalSignature,keyEncipherment
extendedKeyUsage        = serverAuth,clientAuth
subjectKeyIdentifier    = hash
subjectAltName          = @alt_names

[alt_names]
DNS.1 = webserver.test.net
IP.1 = 10.0.0.3