The server sends the same chain certificates to firefox and s_client:
- CN=.s3.amazonaws.com SAN=DNS:.s3.amazonaws.com,DNS:s3.amazonaws.com
- CN=VeriSign Class 3 Secure Server CA - G3
- CN=VeriSign Class 3 Public Primary Certification Authority - G5
But the way the certificates will be verified differs depending on the SSL stack and the trusted root certificates of the client. And in case of curl you run into an old OpenSSL validation problem. Details:
- Firefox has a trusted root certificate similar to the certificate#3 send by the client. This means that it is a different certificate but it contains the same public key, so that the signature for certificate#2 is still valid. Since Firefox underlying TLS stack (NSS) thus has found a usable trust anchor it will consider the chain as verified and ignore the certificate#3 sent by the server.
- But the version of curl you have uses OpenSSL as the TLS library. OpenSSL tries to get the longest match, that it it will try to find a trusted root certificate which signed certificate#3. If it fails it will not try with a shorter trust chain but simply fail. This is a long-standing bug which is the cause of many many strange problems like this and it looks like the issue is for now only fixed in the latest development branch (not released).
The solution is probably to use a CA store for curl which still includes the old deprecated 1024bit CA's so that it contains the trust anchor "/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority"
For even more details about this problem see
- more detailed writeup
- OpenSSL bug #2732 from 2012
- workarounds with patch
- newer Bug reports which indicate a bug fix for current development branch (after 1.0.2)