Advanced PKI

The Advanced PKI consists of a root CA and a layer of subordinate CAs.

Overview

We assume a company named Green AS, controlling the domain green.no. The company runs a three-pronged PKI to serve its security needs.

../_images/AdvancedPKILayout.png

To implement the PKI, we first create the Green Root CA and its CA certificate. We then use the Root CA to create the three signing CAs: Green Email CA, Green TLS CA, and Green Software CA. With the CAs in place we proceed to show them in operation, issuing user certificates for email-protection, TLS-authentication, and code-signing purposes respectively.

All commands are ready to be copy/pasted into a terminal session. When you have reached the end of this page, you will have built a PKI with multiple signing CAs and issued 4 different types of user certificates.

To get started, fetch the Advanced PKI example files and change into the new directory:

git clone https://bitbucket.org/stefanholek/pki-example-2
cd pki-example-2

Configuration Files

We use one configuration file per CA:

And one configuration file per CSR type:

Please study the configuration files before you continue.

1. Create Root CA

1.1 Create directories

mkdir -p ca/root-ca/private ca/root-ca/db crl certs
chmod 700 ca/root-ca/private

The ca directory holds CA resources, the crl directory holds CRLs, and the certs directory holds user certificates. The directory layout stays the same throughout the tutorial.

1.2 Create database

cp /dev/null ca/root-ca/db/root-ca.db
echo 01 > ca/root-ca/db/root-ca.crt.srl
echo 01 > ca/root-ca/db/root-ca.crl.srl

The files must exist before the openssl ca command can be used. Also see Appendix B: CA Database.

1.3 Create CA request

openssl req -new \
    -config etc/root-ca.conf \
    -out ca/root-ca.csr \
    -keyout ca/root-ca/private/root-ca.key

With the openssl req -new command we create a private key and a CSR for the Root CA. The configuration is taken from the [req] section of the configuration file.

1.4 Create CA certificate

openssl ca -selfsign \
    -config etc/root-ca.conf \
    -in ca/root-ca.csr \
    -out ca/root-ca.crt \
    -extensions root_ca_ext \
    -days 7305

With the openssl ca -selfsign command we create a self-signed root certificate from the CSR. The configuration is taken from the [ca] section of the configuration file.

1.5 Create initial CRL

openssl ca -gencrl \
    -config etc/root-ca.conf \
    -out crl/root-ca.crl

With the openssl ca -gencrl command we create an initial, empty CRL.

2. Create Email CA

2.1 Create directories

mkdir -p ca/email-ca/private ca/email-ca/db crl certs
chmod 700 ca/email-ca/private

2.2 Create database

cp /dev/null ca/email-ca/db/email-ca.db
echo 01 > ca/email-ca/db/email-ca.crt.srl
echo 01 > ca/email-ca/db/email-ca.crl.srl

2.3 Create CA request

openssl req -new \
    -config etc/email-ca.conf \
    -out ca/email-ca.csr \
    -keyout ca/email-ca/private/email-ca.key

We create a private key and a CSR for the Email CA. The configuration is taken from the [req] section of the configuration file.

2.4 Create CA certificate

openssl ca \
    -config etc/root-ca.conf \
    -in ca/email-ca.csr \
    -out ca/email-ca.crt \
    -extensions signing_ca_ext

We use the Root CA to issue the Email CA certificate. Points if you noticed that -extensions could have been omitted.

2.5 Create initial CRL

openssl ca -gencrl \
    -config etc/email-ca.conf \
    -out crl/email-ca.crl

We create an initial, empty CRL. A new CRL must be issued at regular intervals.

2.6 Create PEM bundle

cat ca/email-ca.crt ca/root-ca.crt > \
    ca/email-ca-chain.pem

We create a certificate chain file from the Email CA and Root CA certificates. It will come handy later as input for the openssl pkcs7 and openssl pkcs12 commands.

3. Create TLS CA

3.1 Create directories

mkdir -p ca/tls-ca/private ca/tls-ca/db crl certs
chmod 700 ca/tls-ca/private

3.2 Create database

cp /dev/null ca/tls-ca/db/tls-ca.db
echo 01 > ca/tls-ca/db/tls-ca.crt.srl
echo 01 > ca/tls-ca/db/tls-ca.crl.srl

3.3 Create CA request

openssl req -new \
    -config etc/tls-ca.conf \
    -out ca/tls-ca.csr \
    -keyout ca/tls-ca/private/tls-ca.key

We create a private key and a CSR for the TLS CA. The configuration is taken from the [req] section of the configuration file.

3.4 Create CA certificate

openssl ca \
    -config etc/root-ca.conf \
    -in ca/tls-ca.csr \
    -out ca/tls-ca.crt \
    -extensions signing_ca_ext

We use the Root CA to issue the TLS CA certificate.

3.5 Create initial CRL

openssl ca -gencrl \
    -config etc/tls-ca.conf \
    -out crl/tls-ca.crl

We create an initial CRL. A new CRL must be issued at regular intervals.

3.6 Create PEM bundle

cat ca/tls-ca.crt ca/root-ca.crt > \
    ca/tls-ca-chain.pem

We create a certificate chain file.

4. Create Software CA

4.1 Create directories

mkdir -p ca/software-ca/private ca/software-ca/db crl certs
chmod 700 ca/software-ca/private

4.2 Create database

cp /dev/null ca/software-ca/db/software-ca.db
echo 01 > ca/software-ca/db/software-ca.crt.srl
echo 01 > ca/software-ca/db/software-ca.crl.srl

4.3 Create CA request

openssl req -new \
    -config etc/software-ca.conf \
    -out ca/software-ca.csr \
    -keyout ca/software-ca/private/software-ca.key

We create a private key and a CSR for the Software CA. The configuration is taken from the [req] section of the configuration file.

4.4 Create CA certificate

openssl ca \
    -config etc/root-ca.conf \
    -in ca/software-ca.csr \
    -out ca/software-ca.crt \
    -extensions signing_ca_ext

We use the Root CA to issue the Software CA certificate.

4.5 Create initial CRL

openssl ca -gencrl \
    -config etc/software-ca.conf \
    -out crl/software-ca.crl

We create an initial CRL. A new CRL must be issued at regular intervals.

4.6 Create PEM bundle

cat ca/software-ca.crt ca/root-ca.crt > \
    ca/software-ca-chain.pem

We create a certificate chain file.

5. Operate Email CA

5.1 Create email request

openssl req -new \
    -config etc/email.conf \
    -out certs/fred.csr \
    -keyout certs/fred.key

We create the private key and CSR for an email-protection certificate using a request configuration file. When prompted enter these DN components: C=NO, O=Green AS, CN=Fred Flintstone, emailAddress=fred@green.no. Leave other fields empty.

5.2 Create email certificate

openssl ca \
    -config etc/email-ca.conf \
    -in certs/fred.csr \
    -out certs/fred.crt \
    -extensions email_ext

We use the Email CA to issue Fred’s email-protection certificate. A copy of the certificate is saved in the certificate archive ca/email-ca under a name derived from the certificate’s serial number.

5.3 Create PKCS#12 bundle

openssl pkcs12 -export \
    -name "Fred Flintstone (Email Security)" \
    -in certs/fred.crt \
    -inkey certs/fred.key \
    -certfile ca/email-ca-chain.pem \
    -out certs/fred.p12

We pack the private key, the certificate, and the CA chain into a PKCS#12 bundle. This format (often with a .pfx extension) is used to distribute keys and certificates to end users.

5.4 Revoke certificate

openssl ca \
    -config etc/email-ca.conf \
    -revoke ca/email-ca/0D37E6503E773B0977B6311423451E5A6918235C.pem \
    -crl_reason keyCompromise

When Fred’s laptop goes missing, we revoke his certificate.

Note

Certificate serial numbers are assigned randomly and the serial number will be different in your case. To find the correct serial number query the CA database:

grep fred@green.no ca/email-ca/db/email-ca.db | cut -f4,6

5.5 Create CRL

openssl ca -gencrl \
    -config etc/email-ca.conf \
    -out crl/email-ca.crl

The next CRL contains the revoked certificate.

6. Operate TLS CA

6.1 Create TLS server request

SAN=DNS:green.no,DNS:www.green.no \
openssl req -new \
    -config etc/server.conf \
    -out certs/green-no.csr \
    -keyout certs/green-no.key

We create the private key and CSR for a TLS-server certificate using the server request configuration file. When prompted enter these DN components: C=NO, O=Green AS, CN=www.green.no. The subjectAltName cannot be prompted for and must be passed as environment variable.

6.2 Create TLS server certificate

openssl ca \
    -config etc/tls-ca.conf \
    -in certs/green-no.csr \
    -out certs/green-no.crt \
    -extensions server_ext

We use the TLS CA to issue the server certificate. A copy of the certificate is saved in the certificate archive ca/tls-ca.

6.3 Create PKCS#12 bundle

openssl pkcs12 -export \
    -name "green.no (Network Component)" \
    -in certs/green-no.crt \
    -inkey certs/green-no.key \
    -certfile ca/tls-ca-chain.pem \
    -out certs/green-no.p12

We pack the private key, the certificate, and the CA chain into a PKCS#12 bundle for distribution.

6.4 Create TLS client request

openssl req -new \
    -config etc/client.conf \
    -out certs/barney.csr \
    -keyout certs/barney.key

We create the private key and CSR for a TLS-client certificate using the client request configuration file. When prompted enter these DN components: C=NO, O=Telenor AS, OU=Support, CN=Barney Rubble, emailAddress=barney@telenor.no.

6.5 Create TLS client certificate

openssl ca \
    -config etc/tls-ca.conf \
    -in certs/barney.csr \
    -out certs/barney.crt \
    -extensions client_ext \
    -policy extern_pol

We use the TLS CA to issue Barney’s client certificate. Note that we specify the extern_pol naming policy because the DN would not satisfy the default match_pol policy.

6.6 Create PKCS#12 bundle

openssl pkcs12 -export \
    -name "Barney Rubble (Network Access)" \
    -in certs/barney.crt \
    -inkey certs/barney.key \
    -certfile ca/tls-ca-chain.pem \
    -out certs/barney.p12

We pack everything into a PKCS#12 bundle for distribution.

6.7 Revoke certificate

openssl ca \
    -config etc/tls-ca.conf \
    -revoke ca/tls-ca/3A1BD42F9DF964D7196A9207C7E99BA72A34F7A5.pem \
    -crl_reason affiliationChanged

When the support contract ends, we revoke Barney’s certificate.

Note

The serial number will be different in your case. To find the correct serial number query the CA database:

grep barney@telenor.no ca/tls-ca/db/tls-ca.db | cut -f4,6

6.8 Create CRL

openssl ca -gencrl \
    -config etc/tls-ca.conf \
    -out crl/tls-ca.crl

The next CRL contains the revoked certificate.

7. Operate Software CA

7.1 Create code-signing request

openssl req -new \
    -config etc/codesign.conf \
    -out certs/software.csr \
    -keyout certs/software.key

We create the private key and CSR for a code-signing certificate using the codesign request configuration file. When prompted enter these DN components: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green Software Certificate (B356TG), and UID=B356TG.

7.2 Create code-signing certificate

openssl ca \
    -config etc/software-ca.conf \
    -in certs/software.csr \
    -out certs/software.crt \
    -extensions codesign_ext

We use the Software CA to issue the code-signing certificate.

7.3 Create PKCS#12 bundle

openssl pkcs12 -export \
    -name "Green Software Certificate (B356TG)" \
    -in certs/software.crt \
    -inkey certs/software.key \
    -certfile ca/software-ca-chain.pem \
    -out certs/software.p12

We create a PKCS#12 bundle for distribution.

7.4 Revoke certificate

openssl ca \
    -config etc/software-ca.conf \
    -revoke ca/software-ca/1AEDEEA18BBE3635266A0A558F53FE17E6C46CBD.pem \
    -crl_reason superseded

To complete the example, we revoke the software certificate.

Note

The serial number will be different in your case. To find the correct serial number query the CA database:

grep B356TG ca/software-ca/db/software-ca.db | cut -f4,6

7.5 Create CRL

openssl ca -gencrl \
    -config etc/software-ca.conf \
    -out crl/software-ca.crl

The next CRL contains the revoked certificate.

8. Publish Certificates

8.1 Create DER certificate

openssl x509 \
    -in ca/root-ca.crt \
    -out ca/root-ca.cer \
    -outform der

All published certificates must be in DER format. MIME type: application/pkix-cert. [RFC 2585#section-4.1]

8.2 Create DER CRL

openssl crl \
    -in crl/email-ca.crl \
    -out crl/email-ca.crl \
    -outform der

All published CRLs must be in DER format. MIME type: application/pkix-crl. [RFC 2585#section-4.2]

8.3 Create PKCS#7 bundle

openssl crl2pkcs7 -nocrl \
    -certfile ca/email-ca-chain.pem \
    -out ca/email-ca-chain.p7c \
    -outform der

PKCS#7 is used to bundle one or more certificates. MIME type: application/pkcs7-mime. [RFC 5273#page-3]

References