Is the alert “SSL3_READ_BYTES:sslv3 alert bad certificate” indicating that the SSL failed

While running the below command openssl s_client -host example.xyz -port 9093

I get the following error:

139810559764296:error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate:s3_pkt.c:1259:SSL alert number 42
39810559764296:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:184:

But at the end i get "Verify return code: 0 (ok)" message.

My question is what does the above alert signify, and if the SSL was actually successful.

SSL handshake has read 6648 bytes and written 354 bytes
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol  : TLSv1.2
Cipher    : AES128-SHA
Session-ID: xx
Session-ID-ctx:
Master-Key: xx
Key-Arg   : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
Start Time: 1475096098
Timeout   : 300 (sec)
**Verify return code: 0 (ok)**

Solution 1:

"Handshake failure" means the handshake failed, and there is no SSL/TLS connection. You should see that openssl exits to the shell (or CMD etc) and does not wait for input data to be sent to the server. "Verify return code 0" means that no problem was found in the server's certificate, either because it wasn't checked at all or because it was checked and was good (as far as OpenSSL's checks go, which doesn't cover everything); in this case by knowing the protocol we can deduce the latter case applies.

Receiving alert bad certificate (code 42) means the server demands you authenticate with a certificate, and you did not do so, and that caused the handshake failure. A few lines before the line SSL handshake has read ... and written ... you should see a line Acceptable client certificate CA names usually followed by several lines identifying CAs, possibly followed by a line beginning Client Certificate Types and maybe some about Requested Signature Algorithms depending on your OpenSSL version and the negotiated protocol.

Find a certificate issued by a CA in the 'acceptable' list, or if it was empty look for documentation on or about the server saying which CAs it trusts or contact the server operators or owners and ask them, plus the matching private key, both in PEM format, and specify them with -cert $file -key $file; if you have both in one file, as is possible with PEM, just use -cert $file. If you have them in a different format, either specify it, or search here and perhaps superuser and security.SX; there are already many Q&As about converting various certificate and privatekey formats. If your cert needs a "chain" or "intermediate" cert (or even more than one) to be verified, as is often the case for a cert from a public CA (versus an inhouse one) depending on how the server is configured, s_client requires a trick: either add the chain cert(s) to your system truststore, or create a local/temporary truststore containing the CA cert(s) you need to verify the server PLUS the chain cert(s) you need to send.

If you don't have such a certificate you either need to get one, which is a different question that requires much more detail to answer, or you need to find a way to connect to the server without using certificate authentication; again check the documentation and/or ask the operators/owners.

EDIT: It appears from comment you may have the client key and cert chain as well as server anchor(s?) in Java. On checking I don't see a good existing answer fully covering that case, so even though this probably won't search well:

# Assume Java keystore is type JKS (the default but not only possibility)
# named key.jks and the privatekey entry is named mykey (ditto)
# and the verify certs are in trust.jks in entries named trust1 trust2 etc.

# convert Java key entry to PKCS12 then PKCS12 to PEM files
keytool -importkeystore -srckeystore key.jks -destkeystore key.p12 -deststoretype pkcs12 -srcalias mykey 
openssl pkcs12 -in key.p12 -nocerts -out key.pem
openssl pkcs12 -in key.p12 -nokeys -clcerts -out cert.pem
openssl pkcs12 -in key.p12 -nokeys -cacerts -out chain.pem
# extract verify certs to individual PEM files
# (or if you 'uploaded' PEM files and still have them just use those)
keytool -keystore trust.jks -export -alias trust1 -rfc -file trust1.pem
keytool -keystore trust.jks -export -alias trust2 -rfc -file trust2.pem
... more if needed ...
# combine for s_client 
cat chain.pem trust*.pem >combined.pem
openssl s_client -connect host:port -key key.pem -cert cert.pem -CAfile combined.pem

Solution 2:

In my case I got this error when the private key did not match the cert. I had updated the cert when mine expired and needed to create a new private key. However, I forgot to reference that in my app. When I pointed to the new private key - this error went away.

Solution 3:

I got that same error when running ssl_test from the testsuite on an embedded target with the wrong date and time setting. The target time was set to the year 2000, which was older than the supplied test certificates. Setting the target time/year to 2020 fixed the problem.