I've been playing with x509 certificates to better understand them and I've hit a strange issue which makes me think I have a misunderstanding. Initially I tested everything with libressl 2.8.3 and things work as expected, however when testing against openssl 1.1.1d things fall apart.
First I've created a root key and certificate with
libressl ecparam -out root.pem -name secp384r1 -genkey
libressl req -new -key root.pem -out root.csr
libressl x509 -in root.csr -out root.crt -req -signkey root.pem -days 30
then the intermediate
libressl ecparam -out inter.pem -name secp384r1 -genkey
libressl req -new -key inter.pem -out inter.csr
libressl x509 -in inter.csr -out inter.crt -req -signkey root.pem -days 30
and a leaf
libressl ecparam -out leaf.pem -name secp384r1 -genkey
libressl req -new -key leaf.pem -out leaf.csr
libressl x509 -in leaf.csr -out leaf.crt -req -signkey inter.pem -days 30
The issue I'm hitting is that libressl will verify the intermediate cert while openssl will not
>>> libressl verify -CAfile root.crt inter.crt
inter.crt: C = US, ST = CA, L = SF, O = Inter
error 18 at 0 depth lookup:self signed certificate
OK
>>> openssl verify -CAfile root.crt inter.crt
C = US, ST = CA, L = SF, O = Inter
error 18 at 0 depth lookup: self signed certificate
error inter.crt: verification failed
Am I missing something or is openssl exposing that I have a misunderstanding of x509 certs and libre/openssl? Similarly validating the leaf cert with a bundle of the root and intermediate succeeds with libressl and fails with openssl.
Edit:
Thanks to Mike Ounsworth pointing out the issue. My intermediate cert was being generated as a self signed cert using the
openssl x509 -req -signkey root.pem -days 30 -in inter.csr -out inter.crt
command. Which resulted in a certificate which read
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 14260606495133371304 (0xc5e7da0d280d8ba8)
Signature Algorithm: ecdsa-with-SHA1
Issuer: C=US, ST=CA, L=SF, O=Test, OU=Test, CN=Intermediate
Validity
Not Before: Jan 21 20:45:34 2020 GMT
Not After : Feb 20 20:45:34 2020 GMT
Subject: C=US, ST=CA, L=SF, O=Test, OU=Test, CN=Intermediate
Swapping the command above to
openssl x509 -req -days 30 -in inter.csr -CA root.crt -CAkey root.pem -CAcreateserial -out inter.crt
Resulted in a certificate with the issuer set to root.
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 14926915319265390371 (0xcf270e658d266f23)
Signature Algorithm: ecdsa-with-SHA1
Issuer: C=US, ST=CA, L=SF, O=Test, OU=Test, CN=Root
Validity
Not Before: Jan 21 20:51:07 2020 GMT
Not After : Feb 20 20:51:07 2020 GMT
Subject: C=US, ST=CA, L=SF, O=Test, OU=Test, CN=Intermediate
The intermediate cert now passes verification
However on verification the leaf certificate I get an error with
❯❯❯ libressl verify -verbose -CAfile root.crt -untrusted inter.crt leaf.crt
leaf.crt: C = CA, ST = CA, L = SF, O = Test, OU = Test, CN = Intermediate
error 24 at 1 depth lookup:invalid CA certificate
OK
To Answer my own question. I had to add the CA:true x509v3 extension to my intermediate certificate. This gave me the cert generation line
openssl x509 -req -sha256 -days 30 -in inter.csr -CA root.crt -CAkey root.pem -extfile extensions.txt -out inter.crt
With extensions.txt
reading
basicConstraints=critical,@bs_section
[bs_section]
CA=true
pathlen=1
copied directly from https://www.openssl.org/docs/manmaster/man5/x509v3_config.html
I'm unclear about what critical
means as openssl simply states If critical is present then the extension will be critical.
on their man page, but whatever.
error 18 at 0 depth lookup
, and for some reason openssl considers that a fatal error while libressl does not. If you posted a text dump / pretty print of the root and inter certs, that might help us spot the problem. – Mike Ounsworth Jan 21 '20 at 20:10req
command. This SO answer suggests that you might get this error if the root and intermediate have the same DN / CN, which is not allowed. (x509 is full of pesky little rules, and it often takes me a few tries to generate valid certs with openssl) – Mike Ounsworth Jan 21 '20 at 20:13