When only secp384r1 is enabled in a server with TLS, 0-RTT doesn't work. Why? - ssl

0-RTT doesn't work when secp384r1 is the only one enabled in a server with TLS.
I am using OpenSSL:
This happens in:
Apache with my own 0-RTT implementation (still in progress)
NGINX
If I add another curve to the list, like secp384r1:prime256v1 or secp384r1:X25519: 0-RTT starts to work.
By not working, I mean, when I connect to the server using s_client in OpenSSL, it says that Early data was rejected, but if I enable another curve like the ones mentioned above: I get Early data was accepted.
I am unable to find about this anywhere online except this https://trac.nginx.org/nginx/ticket/1969

Related

CL+SSL SSL Error: Unsafe legacy renegotiation disabled. How to bypass or resolve?

I'm trying to hit an https endpoint to pull back some data using common-lisp(sbcl). For a while this worked without issue. Then one day I started receiving the following error
SSL error queue:
error:0A000152:SSL routines::unsafe legacy renegotiation disabled
[Condition of type CL+SSL::SSL-ERROR-SSL]
I've tried using both drakma and dexador, but see the same error from both. I've confirmed through openssl that the server I'm trying to connect to does not support renegotiation.
From openssl s_client -connect
New, TLSv1/SSLv3, Cipher is AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
I'm on OSX and my open ssl version is LibreSSL 2.8.3.
So to my understanding my client is trying to initiate renegotiation, but the server is rejecting it. I don't really know where to go from here and at this point I'm not even sure what level the problem is truly at, openSSL, CL+SSL, or the http client libraries built on top of CL+SSL. Is there some way to disable renegotiation, or force a new connection? Is there some setting I'm missing?
In Openssl 1.1.1, the SSL_OP_LEGACY_SERVER_CONNECT flag was turned on by default, but
It is turned off by default as of Openssl 3.0.0.
check the article below
SSL_CTX_set_options(ssl_ctx, SSL_OP_LEGACY_SERVER_CONNECT);
https://www.openssl.org/docs/man3.0/man3/SSL_clear_options.html

OpenSSL connection: alert internal error

I have 100 HTTPS services running on a single server using SNI. (Actually, I don't have access to them. It's an assignment. All I know are their domain names N.xxx.yy where N is in range from 00 to 99.) The goal of the assignment is to evaluate security of every single connection to each of these servers. So some of the servers contain expired certificates, certificates with wrong CN, etc.
My problem is that I cannot get past the handshake on some of the servers. I have written my own application in C++ using OpenSSL, but I've also tried it with openssl s_client. This is how I connect to the server:
openssl s_client -host N.xxx.yy -port 443 -verify 1 -servername N.xxx.yy -CAfile assignment-ca.pem
And this is what I get:
139625941858168:error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error:s3_pkt.c:1493:SSL alert number 80
139625941858168:error:140790E5:SSL routines:ssl23_write:ssl handshake failure:s23_lib.c:177:
In Wireshark, I see that client sent ClientHello, server responded with ServerHello (choosing TLSv1.2 and ECDHE-RSA-AES256-GCM-SHA384) followed by Certificate and then it sent me Alert message containing Internal Error (80).
After trying different thing I have found out that if I run s_client with -tls1 or -tls1_1 I can successfully get past the handshake. -tls1_2 does not work. What is even stranger is that connection through Chrome/Firefox/any other browser succeeds even if TLSv1.2 is negotiated. From what I see, Chrome is sending a different cipher list than me or s_client but even after modifying the cipher list to match the one in Chrome (and making sure that server chooses ECDHE-RSA-AES128-GCM-SHA256), it does not work either. Chrome is sending these TLS extensions, which I don't but most of them seem empty:
Unknown 47802
renegotiation_info
Extended Master Secret
signed_certificate_timestamp
status_request
Application Layer Protocol Negotiation
channel_id
Unknown 6682
Can anybody explain me what is happening here? Unfortunately, I have no way to debug it on the server side so this is all I know.
UPDATE:
After playing around with forged ClientHello messages I managed to track it down to signature_algorithms extension. My app and s_client provide SHA384 + {RSA,DSA,ECDSA} but if I remove these and keep just SHA256 + {RSA,DSA,ECDSA}, as Chrome does, it works and I receive Server Key Exchange message successfully. Could it be that server somehow does not support it, but instead of providing meaningful error message, it just ends unexpectedly and gives me this internal error?
UPDATE 2:
I found answer to why it works with TLS versions prior to 1.2 in RFC5246. Question from the previous UPDATE still holds.
Note: this extension is not meaningful for TLS versions prior to 1.2.
Clients MUST NOT offer it if they are offering prior versions.
However, even if clients do offer it, the rules specified in [TLSEXT]
require servers to ignore extensions they do not understand.
Since you wrote that -tls1_2 does not work I assume either you and/or the server uses an older openssl library. The current version while writing this is 1.1.0e
There were quite some fixes since 0.9.8, which could often be seen on older systems.
For Version 1.0.1 there was this fix, which sounds like your problem:
`Some servers which support TLS 1.0 can choke if we initially indicate
support for TLS 1.2 and later renegotiate using TLS 1.0 in the RSA
encrypted premaster secret. As a workaround use the maximum permitted
client version in client hello, this should keep such servers happy
and still work with previous versions of OpenSSL.`
Maybe also notable:
Don't allow TLS 1.2 SHA-256 ciphersuites in TLS 1.0, 1.1 connections.
So I would suggest to update your openssl-Version and in case of the servers out of your control I would stick to the settings you already found.

Curl keeps saying "SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure" but it should be TLS

The PHP version on my webserver was recently updated. Now I notice that when downloading external https URLs with Curl, for one specific server it fails, giving me this error:
SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
Downloading https stuff from this server though Curl worked fine before.
Now the strange this is: it seems an SSL3 error, but as I understood from other cases regarding this error (also here on SO) it's due to SSL3 no longer being supported by updated versions of PHP or Curl. And rightly so, since SSL3 is insecure.
However, this particular webserver uses TLS1.2, and by no means SSL3.
So if my Curl is not using SSL3, and neither is the webserver, why am I still getting SSL3 related errors?
I already tried setting CURLOPT_SSLVERSION to 4, 5 or 6, and setting CURLOPT_SSL_CIPHER_LIST to TLSv1, all to no avail, error keeps coming up.
Although this error message looks like it is using SSL 3.0 it is probably not. Since TLS1.0 is practically SSL3.1 etc you will find lots of functions and error messages having the SSLv3 string within the TLS code path in OpenSSL. The problem with this specific server is probably something else and one would need to know the server hostname and your installed version of OpenSSL to find out more about the problem.
EDIT: Based on the comment the version of OpenSSL used with curl is 0.9.8b. Since the server can only do TLS 1.2 the handshake will fail, since TLS 1.2 is only supported since OpenSSL 1.0.1. Apart from that 0.9.8b is years out of support and has several security problems which got fixed in later versions.

Nginx error: "No shared cipher". But there are

My Nginx server has an SSL certificate that looks really good and works in most browsers perfectly. The server is https://live.evmote.com . You can "hit" the server by going to https://live.evmote.com/primus .
The SSL Cert check is here: https://www.ssllabs.com/ssltest/analyze.html?d=live.evmote.com
So far, so good. The problem is specifically on the Tesla Model S browser (the in-car browser). It gives a "Bad certificate" error. The Tesla browser is notoriously bad and has incomplete support. There's no way to view the cert chain or debug the problem from the Tesla. It's more like an appliance than a computer.
Here's the SSL support from within the Tesla:
http://i.imgur.com/EbIrClM.jpg
On the Nginx server, I'm getting this error in the log:
SSL3_GET_CLIENT_HELLO:no shared cipher
Now, clearly from the Tesla SSL report and the server report, there are shared ciphers. I would expect that they would handshake on this one:
TLS_RSA_WITH_AES_256_CBC_SHA (0x35)
I'm not sure how to troubleshoot from here.
Thanks,
Ryan
The error message might be misleading. What's definitely a problem is that the browser does not support SNI, but your web site requires it. At least it only serves the valid certificate (for live.evmote.com) for SNI capable browsers, all the others get a self-signed wildcard certificate which will not be accepted by a browser doing proper certificate validation.
We've hit similar problem from the Java client. The root cause was explicitly set protocols in SSL context (io.netty.handler.ssl.SslContext):
val ctx = io.netty.handler.ssl.SslContextBuilder.forClient()
...
.protocols("SSLv2Hello,TLSv1.2,TLSv1.3".split(","))
.build()
And precisely SSLv2Hello, that should be neither declared nor used here.
Unfortunately, we can't control all our clients. So further investigation showed this problem has appeared after OpenSSL upgrade to 1.1.*.
Once we downgraded OpenSSL to 1.0.* it do the trick. Nginx 1.18.0 + OpenSSL 1.0.2u could handle handshakes with SSLv2Hello without errors and with the highest protocol possible.

httperf: connection failed with unexpected error 0

Has anybody seen "httperf: connection failed with unexpected error 0" when running httperf with --ssl?
This is blocking my test on that domain. When I tested --ssl on https://google.com it worked fine.
On the other end of my "problematic" domain there is ELB, forwarding calls to heroku.
On my workstation: OSX 10.9.5 and httperf-0.9.0 (via brew)
I had the same issue, by looking at NGINX logs it turns out the SSL handshake fails because SSLv3 is disabled server side.
The project seemed a bit dead so I modified this file at line 924 :
I replaced SSLv3_client_method() with TLSv1_client_method()
Then the usual compilation stuff configure-make-install. Be sure to have openssl on your build machine.
Source : https://www.openssl.org/docs/ssl/SSL_CTX_new.html
The answer by #oto turned out be related to my fix as well. Basically, we stopped using SSLv3 on our server (and, apparently, all other ssl protocols used by httperf) due to the POODLE vulnerability, and httperf uses SSLv3, so it fails to connect.
Until they update httperf there seems to be no easy way around this. One way to fix it is to change from SSLv3 to TLSv1 by hand, as mentioned in the other answer.
I found this patch pull-request on GitHub. It changes the code so you can specify the ssl protocol with a flag, so I could force using TLSv1 instead of SSLv3.
For both fixes you will need to download the httperf source code, make the changes (like applying the patch), and then compile. I cloned the source from GitHub, so I had to run the autoreconf -i command before running make, but the instructions are pretty good. I had to use commit ed5c631 since the latest commits appear to be broken.