1.5.3 Creating a Subordinate CA
The process of subordinate CA generation largely mirrors the root CA process. In this section, I will only highlight the differences where appropriate. For everything else, refer to the previous section.
1.5.3.1 Subordinate CA Configuration
To generate a configuration file (sub-ca.conf
) for the subordinate CA, start with the file we used for the root CA and make the changes listed in this section. We’ll change the name to sub-ca
and use a different distinguished name. We’ll put the OCSP responder on a different port, but only because the ocsp
command doesn’t understand virtual hosts. If you used a proper web server for the OCSP responder, you could avoid using special ports altogether. The default lifetime of new certificates will be 365 days, and we’ll generate a fresh CRL once every 30 days.
The change of copy_extensions
to copy
means that extensions from the CSR will be copied into the certificate, but only if they are not already set in our configuration. With this change, whoever is preparing the CSR can put the required alternative names in it, and the information from there will be picked up and placed in the certificate. This feature is somewhat dangerous (you’re allowing someone else to have limited direct control over what goes into a certificate), but I think it’s fine for smaller environments:
[default]
name = sub-ca
ocsp_url = http://ocsp.$name.$domain_suffix:9081
[ca_dn]
countryName = "GB"
organizationName = "Example"
commonName = "Sub CA"
[ca_default]
default_days = 365
default_crl_days = 30
copy_extensions = copy
At the end of the configuration file, we’ll add two new profiles, one each for client and server certificates. The only difference is in the keyUsage
and extendedKeyUsage
extensions. Note that we specify the basicConstraints
extension but set it to false
. We’re doing this because we’re copying extensions from the CSR. If we left this extension out, we might end up using one specified in the CSR:
[server_ext]
authorityInfoAccess = @issuer_info
authorityKeyIdentifier = keyid:always
basicConstraints = critical,CA:false
crlDistributionPoints = @crl_info
extendedKeyUsage = clientAuth,serverAuth
keyUsage = critical,digitalSignature,keyEncipherment
subjectKeyIdentifier = hash
[client_ext]
authorityInfoAccess = @issuer_info
authorityKeyIdentifier = keyid:always
basicConstraints = critical,CA:false
crlDistributionPoints = @crl_info
extendedKeyUsage = clientAuth
keyUsage = critical,digitalSignature
subjectKeyIdentifier = hash
After you’re happy with the configuration file, create a directory structure following the same process as for the root CA. Just use a different directory name, for example, sub-ca
.
1.5.3.2 Subordinate CA Generation
As before, we take two steps to create the subordinate CA. First, we generate the key and the CSR. All the necessary information will be picked up from the configuration file when we use the -config
switch.
$ openssl req -new \
-config sub-ca.conf \
-out sub-ca.csr \
-keyout private/sub-ca.key
In the second step, we get the root CA to issue a certificate. The -extensions
switch points to the sub_ca_ext
section in the configuration file, which activates the extensions that are appropriate for the subordinate CA.
$ openssl ca \
-config root-ca.conf \
-in sub-ca.csr \
-out sub-ca.crt \
-extensions sub_ca_ext
1.5.3.3 Subordinate CA Operations
To issue a server certificate, process a CSR while specifying server_ext
in the -extensions
switch:
$ openssl ca \
-config sub-ca.conf \
-in server.csr \
-out server.crt \
-extensions server_ext
To issue a client certificate, process a CSR while specifying client_ext
in the -extensions
switch:
$ openssl ca \
-config sub-ca.conf \
-in client.csr \
-out client.crt \
-extensions client_ext
When a new certificate is requested, all its information will be presented to you for verification before the operation is completed. You should always ensure that everything is in order, but especially if you’re working with a CSR that someone else prepared. Pay special attention to the certificate distinguished name and the basicConstraints
and subjectAlternativeName
extensions.
CRL generation and certificate revocation are the same as for the root CA. The only thing different about the OCSP responder is the port; the subordinate CA should use 9081
instead. It’s recommended that the responder uses its own certificate, which avoids keeping the subordinate CA on a public server.