Related to this (too broad) question: How to implement my PKI?

I have a self-signed CA (ca0)

I would like to create a CA (ca1) with limited power derived from that first CA. ca1 should only be able to sign certificates for *.foo.com and for foo.com.

From this question, I found out that the Name Constraints extension is probably what I want.

The key for ca1 already exists and is ca1.foo.key.pem.

I already have an incomplete command for creating the request:

libressl req -new -sha512 -key ca1.foo.key.pem -out ca1.foo.csr.pem

What should I add to that line to limit ca1's power?


You'll need to add the NameConstraints extension to the request using LibreSSL's config file. The following example is an extract - you'll need to add the various sections to your current config file and tweak the constraints:

[ req ]

# Don't prompt for the DN, use configured values instead
# This saves having to type in your DN each time.

prompt             = no
string_mask        = default
distinguished_name = req_dn

# The size of the keys in bits:
default_bits       = 4096

# The extensions added when generating a CSR
req_extensions     = req_ext

[ req_dn ]

countryName            = GB
stateOrProvinceName    = Somewhere
organizationName       = Example
organizationalUnitName = PKI
commonName             = Example CA

[ req_ext ]

# Extensions added to the request

subjectKeyIdentifier    = hash

basicConstraints            = critical, CA:TRUE
# basicConstraints          = critical, CA:TRUE, pathlen:1

keyUsage = critical, keyCertSign, cRLSign

# Policies and constraints are not recommended for Root CAs
# But could be enforced on subordinate CAs

nameConstraints        = @name_constraints

#policyConstraints = requireExplicitPolicy:1

#inhibitAnyPolicy = 1

#certificatePolicies = @CertPol

[ name_constraints ]
permitted;DNS.1 = example.org
permitted;DNS.2 = example.com
permitted;dirName.1 = style_1
permitted;dirName.2 = style_2

[ style_1 ]
1.OU=head office

[ style_2 ]

[ CertPol ]
policyIdentifier =
CPS = http://pki.example.org/cps.html

If you're not using the default configuration file you'll need to add -config <config file> to your command line.

Note: I've not tried this on LibreSSL - only on OpenSSL but I believe both use the same syntax.

  • Where are number.field (1.OU, 1.DC), and the DC field documented? I haven't found that documentation anywhere. – alx May 14 '20 at 9:18
  • The numbering in that man page goes after the field, not before. Is it the same? – alx May 14 '20 at 11:16
  • I'm guessing that n.DC is the domain levels. Am I right? For example for foo.bar.org it would be 1.DC=org 2.DC=bar 3.DC=foo. If not, what is DC exactly for? – alx May 14 '20 at 11:50
  • I tried openssl req -new -sha512 -key ca1.key.pem -out ca1.csr.pem (I edited /etc/ssl/openssl.cnf directly) and got: – alx May 14 '20 at 12:00
  • 1
    You're correct re the DC elements. I've added a full example that should work with a few tweaks. – garethTheRed May 14 '20 at 13:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.