ecdsa-with-SHA256 cert trips warning about key size
tycho opened this issue · 17 comments
My host uses a certificate with a 256-bit ECC public/private key. analyze.py doesn't appreciate this:
hostname:443 has bad ssl/tls
Things that are bad:
* don't use a public key smaller than 2048 bits
The warning seems to only make sense for RSA certificates.
Perhaps the warning should only trigger if conn['sigalg'][0]
contains 'RSA', as in sha256WithRSAEncryption
?
diff --git a/analyze.py b/analyze.py
index e519a6f..021f52d 100755
--- a/analyze.py
+++ b/analyze.py
@@ -59,7 +59,7 @@ def is_fubar(results):
has_ssl2 = True
logging.debug('SSLv2 is in the list of fubar protocols')
fubar = True
- if int(conn['pubkey'][0]) < 2048:
+ if int(conn['pubkey'][0]) < 2048 and 'RSA' in conn['sigalg'][0]:
has_wrong_pubkey = True
logging.debug(conn['pubkey'][0] + ' is a fubar pubkey size')
fubar = True
sorry for the delay, could you check the master
branch now? I believe it got fixed by f5ad580
Seems confused about some sizes still, but different ones:
$ python2 ./analyze.py -t www.uplinklabs.net
www.uplinklabs.net:443 has obscure or unknown ssl/tls
Changes needed to match the old level:
* enable TLSv1
* enable SSLv3
* add cipher DES-CBC3-SHA
* use a certificate with sha1WithRSAEncryption signature
* use DHE of 1024bits and ECC of 160bits
Changes needed to match the intermediate level:
* consider enabling TLSv1
* add cipher AES128-SHA
* use a certificate signed with sha256WithRSAEncryption
* consider using DHE of at least 2048bits and ECC of at least 256bits
Changes needed to match the modern level:
* remove cipher ECDHE-ECDSA-AES256-SHA
* remove cipher ECDHE-ECDSA-AES128-SHA
* disable TLSv1.1
* use DHE of at least 2048bits and ECC of at least 256bits
Looking at the last line of the "modern" suggestions, I don't know why that message is there:
$ ./cipherscan www.uplinklabs.net
.....................
Target: www.uplinklabs.net:443
prio ciphersuite protocols pfs curves
1 ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
2 ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
3 ECDHE-ECDSA-AES256-SHA384 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
4 ECDHE-ECDSA-AES128-SHA256 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
5 ECDHE-ECDSA-AES256-SHA TLSv1.1,TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
6 ECDHE-ECDSA-AES128-SHA TLSv1.1,TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
Certificate: trusted, 384 bits, ecdsa-with-SHA256 signature
TLS ticket lifetime hint: 300
NPN protocols: None
OCSP stapling: supported
Cipher ordering: server
Curves ordering: server - fallback: no
Server supports secure renegotiation
Server supported compression methods: NONE
TLS Tolerance: yes
Intolerance to:
SSL 3.254 : absent
TLS 1.0 : PRESENT
TLS 1.1 : absent
TLS 1.2 : absent
TLS 1.3 : absent
TLS 1.4 : absent
This shows up in the debug log:
DEBUG:root:ECDH,P-521,521bits is not a good PFS parameter for the modern configuration
It looks like it's calling has_good_pfs()
with must_match
set to True
, which means the message should read "exactly 256bits" instead of "at least 256bits". Seems like "must_match" should go away...
no, that's exactly the behaviour we want, for "modern" level you need to support P-256, if you don't support it, you're not at the modern level
though the message is a bit confusing...
Uhm, my server does support P-256. It just also supports P-521 and others. Do I need to deliberately reduce the security and only support P-256?
Oh, I see, in ECDHParameters, not Curves. Still seems silly to require a lower-strength curve for that...
I set ECDHParameters to prime256v1 and it still sees P-521, which is the first one listed in my Curves list. Hmm.
the curves
column lists only two: secp521r1,secp384r1
, it should list 3: secp521r1,secp384r1,prime256v1
Yeah, I don't get why it doesn't. My Apache config is this right now:
SSLOpenSSLConfCmd ECDHParameters prime256v1
SSLOpenSSLConfCmd Curves X25519:secp521r1:secp384r1:prime256v1
SSLOpenSSLConfCmd DHParameters "/etc/ssl/dhparams-4096.pem"
Incidentally the OpenSSL version used in cipherscan doesn't recognize X25519, but that's kind of expected.
can you connect to that server using?:
openssl s_client -curves prime256v1 -connect hostname.example.com:443\
-servername hostname.example.com
Also, I think that ECDHParameters
and Curves
conflict with each-other; only Curves
should be used with new openssl (that ECDHParameters
was necessary for 1.0.2, IIRC)
Yep, you're right. Curves takes precedence over ECDHParameters.
I get this, when explicitly setting the curve:
$ ./openssl s_client -curves prime256v1 -connect www.uplinklabs.net:443 -servername www.uplinklabs.net
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
CONNECTED(00000003)
140571701110464:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:769:
[...]
That's presumably because the s_client -curves parameter imposes a restriction on the server key type as well (which in my case is a secp384r1 key)?
If I comment out the Curves line (I already removed ECDHParameters, so that's gone too), then cipherscan appears to be happier:
prio ciphersuite protocols pfs curves
1 ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 ECDH,P-256,256bits prime256v1,secp521r1,secp384r1
2 ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 ECDH,P-256,256bits prime256v1,secp521r1,secp384r1
3 ECDHE-ECDSA-AES256-SHA384 TLSv1.2 ECDH,P-256,256bits prime256v1,secp521r1,secp384r1
4 ECDHE-ECDSA-AES128-SHA256 TLSv1.2 ECDH,P-256,256bits prime256v1,secp521r1,secp384r1
I can also explicitly set the SSLOpenSSLConfCmd Curves
line to prime256v1:secp521r1:secp384r1
and the output looks like the above. So apparently having prime256v1
listed last somehow prevents cipherscan from discovering it? That seems strange.
That's presumably because the s_client -curves parameter imposes a restriction on the server key type as well (which in my case is a secp384r1 key)?
I don't honestly remember, I did have discussion with openssl devels that this would be bad (as in, if that's your only cert, just send it, don't make a decision for the client, but if you have multiple certificates, pick the one that will fit the limits advertised in ClientHello), but don't remember what was the outcome, or when was it implemented
(also, that -curves
sets what curves client advertises support for, it does not limit the ones it will accept for certs; in your example it's the server that refuses to process the connection)
I can also explicitly set the SSLOpenSSLConfCmd Curves line to prime256v1:secp521r1:secp384r1 and the output looks like the above.
then leave it as such :)
that shows that the server supports only the curves you listed in config, and those are the secure curves, so that's good, you may want to just add x25519 there and put the P-256 last
Why does listing prime256v1
last in Curves make it undiscoverable by cipherscan? It was already in the list at the end, but cipherscan only saw secp521r1,secp384r1
for some reason.
undiscoverable or unnegotiable?
are you able to negotiate P-256 when it's put last in server settings by manipulating -curves
in s_client
?
I don't know. The s_client test seems unable to tell us anything useful because I get this whenever I try using the -curves prime256v1
arguments, regardless of where the curve is placed in the curve list:
139995147781824:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:769:
The difference I've been observing is that when I place prime256v1
early in the curvelist, cipherscan discovers it, and when it's late in the curvelist, it doesn't.
Also, I just noticed something.
I have a few different certificates/keys on the same physical host with different hostnames. I noticed that one with an RSA4096
key discovers prime256v1
regardless of early/late position in the curve list:
prio ciphersuite protocols pfs curves
1 ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1,prime256v1
2 ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1,prime256v1
3 ECDHE-RSA-AES128-SHA256 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1,prime256v1
4 ECDHE-RSA-AES256-SHA384 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1,prime256v1
But on the hostname with the secp384r1
key, it doesn't if prime256v1
is late:
prio ciphersuite protocols pfs curves
1 ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
2 ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
3 ECDHE-ECDSA-AES256-SHA384 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
4 ECDHE-ECDSA-AES128-SHA256 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
I don't know. The s_client test seems unable to tell us anything useful because I get this whenever I try using the -curves prime256v1 arguments, regardless of where the curve is placed in the curve list
that actually tells us that openssl still has the problematic behaviour, I'll file a bug for this
cipherscan can detect prime256v1 when it's early, because it sends all, and then starts removing them one by one based on what server picks
ah, so it's not fixed, see openssl/openssl#2237