I've been stuck on a problem for 2 days regarding certificates where some clients connect and some other fails the certificate validation.
I'm working on CentOS 7.3 and Nginx 1.15.4. I have 3 levels of certificates that I create:
- Root CA, ECDSA on secp384r1 + sha256
- Intermediate CA, RSA 2048 + sha256
- Server certificate, RSA 2048 + sha256
- Intermediate CA, RSA 2048 + sha256
The Root CA has been trusted on the system, the intermediate CA and the server certificates are bundled in one file and Nginx configured to used them:
ssl_certificate /etc/nginx/ssl_certs/server-chain.crt; ssl_certificate_key /etc/nginx/ssl_certs/server.key; ssl_protocols TLSv1.2 ; ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!SSLv3; ssl_prefer_server_ciphers on; ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off;
Now, Nginx is happy to start with this configuration and I can troubleshoot with openssl:
$ openssl s_client -connect www.example.com:39200 < /dev/null 2>&1 CONNECTED(00000003) depth=2 C = GB, ST = London, L = London, O = Example Ltd, OU = Example Hosting Team, CN = Example Root Certificate Authority, emailAddress = info@Example.com verify return:1 depth=1 C = GB, ST = London, L = London, O = Example Ltd, OU = Example Hosting Team, CN = Example Intermediate CA for project example, emailAddress = info@Example.com verify return:1 depth=0 C = GB, ST = London, L = London, O = Example Ltd, OU = Example Hosting Team, CN = www.example.com, emailAddress = info@Example.com verify return:1 --- Certificate chain 0 s:/C=GB/ST=London/L=London/O=Example Ltd/OU=Example Hosting Team/CN=www.example.com/emailAddress=info@Example.com i:/C=GB/ST=London/L=London/O=Example Ltd/OU=Example Hosting Team/CN=Example Intermediate CA for project example/emailAddress=info@Example.com 1 s:/C=GB/ST=London/L=London/O=Example Ltd/OU=Example Hosting Team/CN=Example Intermediate CA for project example/emailAddress=info@Example.com i:/C=GB/ST=London/L=London/O=Example Ltd/OU=Example Hosting Team/CN=Example Root Certificate Authority/emailAddress=info@Example.com --- Server certificate -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- subject=/C=GB/ST=London/L=London/O=Example Ltd/OU=Example Hosting Team/CN=www.example.com/emailAddress=info@Example.com issuer=/C=GB/ST=London/L=London/O=Example Ltd/OU=Example Hosting Team/CN=Example Intermediate CA for project example/emailAddress=info@Example.com --- No client certificate CA names sent Peer signing digest: SHA512 Server Temp Key: ECDH, P-256, 256 bits --- SSL handshake has read 2630 bytes and written 415 bytes --- New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: EEE677FB7C38DF8AEBEF68D22E67499D8D05710D819D5AB92BEF1B0A009DD818 Session-ID-ctx: Master-Key: E423843C77F304B5D1D384DEA115AA2320128BCC824EC2B1C2F02D63A4F7B1671602F96C50DFFB9B7674C25466CF6162 Key-Arg : None Krb5 Principal: None PSK identity: None PSK identity hint: None Start Time: 1538060858 Timeout : 300 (sec) Verify return code: 0 (ok) --- DONE
Verify return code: 0 (ok) and the fact that openssl is using the system trust store to validate my chain.
I tested the certificates also in Microsoft Edge and it works, no problems with the certificate.
But other clients complain heavily like curl and Firefox and I can't make it work. Here is curl:
curl -v --cacert Example_root_ca.crt https://example-elastic-data-vm.Example.com:39200 * About to connect() to example-elastic-data-vm.Example.com port 39200 (#0) * Trying 192.168.0.123... * Connected to example-elastic-data-vm.Example.com (192.168.0.123) port 39200 (#0) * Initializing NSS with certpath: sql:/etc/pki/nssdb * CAfile: Example_root_ca.crt CApath: none * Server certificate: * subject: E=info@Example.com,CN=example-elastic-data-vm.Example.com,OU=Example Hosting Team,O=Example Ltd,L=London,ST=London,C=GB * start date: Sep 27 14:53:14 2018 GMT * expire date: Sep 26 14:53:14 2020 GMT * common name: example-elastic-data-vm.Example.com * issuer: E=info@Example.com,CN=Example Intermediate CA for project example,OU=Example Hosting Team,O=Example Ltd,L=London,ST=London,C=GB * NSS error -8182 (SEC_ERROR_BAD_SIGNATURE) * Peer's certificate has an invalid signature. * Closing connection 0 curl: (60) Peer's certificate has an invalid signature. ...
while Firefox entertains me with this error:
An error occurred during a connection to example-elastic-data-vm.example.com:39200. security library: improperly formatted DER-encoded message. Error code: SEC_ERROR_BAD_DER
To me this looks like a compatibility problems. I did a lot of research and tests:
- MS Windows happily verifies the whole chain
- OpenSSL happily verifies the whole chain
- Tested using all RSA certificates: works! But in my company we prefer ECDSA
- Tested on different browsers/clients: as already mentioned it works with openssl and Edge, it doesn't with curl and Firefox
- Researched compatibility guidelines and bugs
- Tested different curves like secp256r1, secp384r1 and prime256v1 but no chance
- Tried different signature algorithms, key usage, extended key usage, basic constraings on the certificate. Same results.
- Explicitly pointing to the CA when using curl
I don't know where to hit my head anymore, anyone that can point me in the right direction?
UPDATE: I created test sanitized certificates so that I can upload them here:
NOTE: The output of the commands have been sanitized with "Example", so some names might be off