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.
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 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
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,
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
$ 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
To issue a server certificate, process a CSR while specifying
server_ext in the
$ 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
$ 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
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.