0

I generated ca.crt, ica.crt and server.crt. Here gives some details of the certs.

$ openssl x509 -in server.crt -noout -issuer -subject
issuer=CN = my-ica
subject=CN = server

$ openssl x509 -in ica.crt -noout -issuer -subject
issuer=CN = my-ca
subject=CN = my-ica

$ openssl x509 -in ca.crt -noout -issuer -subject
issuer=CN = my-ca
subject=CN = my-ca

I verified that ca issued ica and ica issued server cert.

# Verifies ca issued ica.
$ openssl verify -verbose -CAfile ca.crt ica.crt
ica.crt: OK

# Verifies ica issued server as the error is at depth 1.
$ openssl verify -verbose -CAfile ica.crt server.crt
CN = my-ica
error 2 at 1 depth lookup: unable to get issuer certificate
error server.crt: verification failed

First question: Now when I try to verify the whole chain at once according to this highly upvoted answer, it fails.

$ openssl verify -verbose -CAfile <(cat ica.crt ca.crt) server.crt
CN = my-ica
error 24 at 1 depth lookup: invalid CA certificate
error server.crt: verification failed

Second question: Even when I try to check the partial chain as suggested here, even that fails.

$ openssl verify -verbose -no-CAfile -no-CApath -partial_chain -trusted ica.crt server.crt
CN = my-ica
error 24 at 1 depth lookup: invalid CA certificate
error server.crt: verification failed

What am I doing wrong with the above 2 approaches?
If it helps, this is how generated the certificates:

openssl req \
  -new \
  -x509 \
  -nodes \
  -days 365 \
  -subj '/CN=my-ca' \
  -keyout ca.key \
  -out ca.crt
openssl genrsa \
  -out ica.key 2048
openssl req \
  -new \
  -key ica.key \
  -subj '/CN=my-ica' \
  -out ica.csr
openssl x509 \
  -req \
  -in ica.csr \
  -CA ca.crt \
  -CAkey ca.key \
  -CAcreateserial \
  -days 365 \
  -extfile <(printf "subjectAltName=DNS:localhost,DNS:*.localhost") \
  -out ica.crt
openssl genrsa \
  -out server.key 2048
openssl req \
  -new \
  -key server.key \
  -subj '/CN=server' \
  -out server.csr
openssl x509 \
  -req \
  -in server.csr \
  -CA ica.crt \
  -CAkey ica.key \
  -CAcreateserial \
  -days 365 \
  -extfile <(printf "subjectAltName=DNS:localhost,DNS:*.localhost") \
  -out server.crt
subtleseeker
  • 4,415
  • 5
  • 29
  • 41

1 Answers1

3

The problem is that your intermediate CA ica.crt is no CA at all. It is missing basicConstraints=critical,CA:TRUE as extension. This means ica.crt is only a leaf certificate which should not be used to sign other certificates.

While openssl does not complain when using a certificate without such extension for signing, it will not be able to build the trust chain because ica.crt is not a valid issuer of server.crt due to the missing CA:TRUE constraint.

Adding the constraints make everything work, i.e.

openssl x509 \
  -req \
  -in ica.csr \
  ...
  -extfile <(printf "subjectAltName=DNS:localhost,DNS:*.localhost\nbasicConstraints=critical,CA:TRUE") \
  -out ica.crt

Looking at the certificate shows that it now has the relevant flag:

$ openssl x509 -in ica.crt -text -noout
...
        X509v3 extensions:
            ...
            X509v3 Basic Constraints: critical
                CA:TRUE

And using this certificate in the validation works:

$ openssl verify -verbose -CAfile <(cat ica.crt ca.crt) server.crt
server.crt: OK
Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172