1

When creating my own root CA, intermediate CA and server certificate I would like to add a contentType=X to the subject line of all three x509 certificates.

On the root that appears to be working with:

openssl req -config ./openssl.cnf -key ./private/ca.key.pem -new -x509 -days 7300 -sha256 -extensions v3_ca -out ./certs/ca.cert.pem -subj "/C=SE/ST=Stockholm/L=Stockholm/O=Inhouse/OU=Dev/CN=CA.LAN/[email protected]/contentType=CA"

Checking it with openssl x509 -in ./certs/ca.cert.pem -text I see that indeed the contentType=CA is there. But when generating a intermediate it gets lost after signing with the CA:

openssl req -config ./openssl.cnf -new -sha256 -key /private/intermediate.key.pem -out ./csr/intermediate.csr.pem -subj "/C=SE/ST=Stockholm/L=Stockholm/O=Inhouse/OU=Dev/CN=IntCA.LAN/[email protected]/contentType=Intermediate CA"
openssl ca -config ./openssl.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha256 -in ./csr/intermediate.csr.pem -out ./certs/intermediate.cert.pem

In the CSR I have:

Subject: C = SE, ST = Stockholm, L = Stockholm, O = Inhouse, OU = Dev, CN = IntCA.LAN, emailAddress = [email protected], contentType = Intermediate CA

But the cert gets:

Issuer: C = SE, ST = Stockholm, L = Stockholm, O = Inhouse, OU = Dev, CN = CA.LAN, emailAddress = [email protected], contentType = CA
Subject: C = SE, ST = Stockholm, O = Inhouse, OU = Dev, CN = IntCA.LAN

Same issue happens on server type certificates generated with:

openssl req -config ./openssl.cnf -new -sha256 -key ./private/server.key.pem -out ./csr/server.csr.pem -subj "/C=SE/ST=Stockholm/L=Stockholm/O=Inhouse/OU=Dev/CN=server/[email protected]/contentType=Server" -addext "subjectAltName = server.dev.lan" -addext "certificatePolicies = 1.2.3.4"
openssl ca -config ./openssl.cnf -extensions server_cert -days 3650 -notext -md sha256 -in ./csr/server.csr.pem -out ./certs/server.cert.pem

For the root CA I use this openssl.cnf:

# OpenSSL root CA configuration file.
# Copy to `/root/ca/openssl.cnf`.

[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir               = /home/test/ca
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
RANDFILE          = $dir/private/.rand

# The root key and root certificate.
private_key       = $dir/private/ca.key.pem
certificate       = $dir/certs/ca.cert.pem

# For certificate revocation lists.
crlnumber         = $dir/crlnumber
crl               = $dir/crl/ca.crl.pem
crl_extensions    = crl_ext
default_crl_days  = 30

# SHA-1 is deprecated, so use SHA-2 instead.
default_md        = sha256

name_opt          = ca_default
cert_opt          = ca_default
default_days      = 375
preserve          = no
policy            = policy_strict
email_in_dn       = no

[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
# Options for the `req` tool (`man req`).
default_bits        = 4096
distinguished_name  = req_distinguished_name
string_mask         = utf8only

# SHA-1 is deprecated, so use SHA-2 instead.
default_md          = sha256

# Extension to add when the -x509 option is used.
x509_extensions     = v3_ca

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit Name
commonName                      = Common Name
emailAddress                    = Email Address

# Optionally, specify some defaults.
countryName_default             = $ENV::COUNTRY
stateOrProvinceName_default     = $ENV::STATE
localityName_default            = $ENV::CITY
0.organizationName_default      = $ENV::COMPANY
organizationalUnitName_default  = $ENV::DEPARTMENT
emailAddress_default            = $ENV::EMAIL

[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:1
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

And for the intermediate CA I use:

# OpenSSL intermediate CA configuration file.
# Copy to `/root/ca/intermediate/openssl.cnf`.

[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir               = /home/test/ca/intermediate
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
RANDFILE          = $dir/private/.rand

# The root key and root certificate.
private_key       = $dir/private/intermediate.key.pem
certificate       = $dir/certs/intermediate.cert.pem

# For certificate revocation lists.
crlnumber         = $dir/crlnumber
crl               = $dir/crl/intermediate.crl.pem
crl_extensions    = crl_ext
default_crl_days  = 30

# SHA-1 is deprecated, so use SHA-2 instead.
default_md        = sha256

name_opt          = ca_default
cert_opt          = ca_default
default_days      = 375
preserve          = no
policy            = policy_loose
copy_extensions   = copy 

[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
# Options for the `req` tool (`man req`).
default_bits        = 4096
distinguished_name  = req_distinguished_name
string_mask         = utf8only

# SHA-1 is deprecated, so use SHA-2 instead.
default_md          = sha256

# Extension to add when the -x509 option is used.
x509_extensions     = v3_intermediate_ca

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit Name
commonName                      = Common Name
emailAddress                    = Email Address

# Optionally, specify some defaults.
countryName_default             = $ENV::COUNTRY
stateOrProvinceName_default     = $ENV::STATE
localityName_default            = $ENV::CITY
0.organizationName_default      = $ENV::COMPANY
organizationalUnitName_default  = $ENV::DEPARTMENT
emailAddress_default            = $ENV::EMAIL

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
# https://stackoverflow.com/questions/70522062/create-an-intermediate-ca-with-openssl
# https://superuser.com/questions/738612/openssl-ca-keyusage-extension
# https://www.openssl.org/docs/manmaster/man5/x509v3_config.html
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
subjectAltName = email:copy
issuerAltName = issuer:copy

[ server_cert ]
# Extension used when signing server certificates
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment, keyAgreement, dataEncipherment, keyCertSign
extendedKeyUsage = serverAuth

[ client_cert ]
# Extension used when signing client/user certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection

The config files are not perfect as they're taken from a mix of examples while I play around and try to learn all the mechanics. The commands have appropriate ENV variables during execution and they work in the sense that the correct config is used in the different steps and the certs/csr/keys are created at the right location.

Any pointers would be welcome but the end goal is to get a server certificate with contentType = Server in the certificate.

1 Answer 1

2

Lack of understanding and a mistake in the policy section. Reading the ca.html#POLICY FORMAT more thoroughly and adding contentType = optional to [ policy_loose ] did the trick.

# OpenSSL intermediate CA configuration file.
# Copy to `/root/ca/intermediate/openssl.cnf`.

[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir               = /home/test/ca/intermediate
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
RANDFILE          = $dir/private/.rand

# The root key and root certificate.
private_key       = $dir/private/intermediate.key.pem
certificate       = $dir/certs/intermediate.cert.pem

# For certificate revocation lists.
crlnumber         = $dir/crlnumber
crl               = $dir/crl/intermediate.crl.pem
crl_extensions    = crl_ext
default_crl_days  = 30

# SHA-1 is deprecated, so use SHA-2 instead.
default_md        = sha256

name_opt          = ca_default
cert_opt          = ca_default
default_days      = 375
preserve          = no
policy            = policy_loose
copy_extensions   = copy 

[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
contentType             = optional

[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
contentType             = optional

[ req ]
# Options for the `req` tool (`man req`).
default_bits        = 4096
distinguished_name  = req_distinguished_name
string_mask         = utf8only

# SHA-1 is deprecated, so use SHA-2 instead.
default_md          = sha256

# Extension to add when the -x509 option is used.
x509_extensions     = v3_intermediate_ca

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit Name
commonName                      = Common Name
emailAddress                    = Email Address

# Optionally, specify some defaults.
countryName_default             = $ENV::COUNTRY
stateOrProvinceName_default     = $ENV::STATE
localityName_default            = $ENV::CITY
0.organizationName_default      = $ENV::COMPANY
organizationalUnitName_default  = $ENV::DEPARTMENT
emailAddress_default            = $ENV::EMAIL

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
# https://stackoverflow.com/questions/70522062/create-an-intermediate-ca-with-openssl
# https://superuser.com/questions/738612/openssl-ca-keyusage-extension
# https://www.openssl.org/docs/manmaster/man5/x509v3_config.html
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
subjectAltName = email:copy
issuerAltName = issuer:copy

[ server_cert ]
# Extension used when signing server certificates
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment, keyAgreement, dataEncipherment, keyCertSign
extendedKeyUsage = serverAuth

[ client_cert ]
# Extension used when signing client/user certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
1
  • 1
    Alternatively using preserve=yes or commandline -preserveDN as described on the same man page would keep all Subject attributes, including locality/L which you (also) dropped in the intermediate cert due to the root policy_strict May 16, 2023 at 0:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .