Open bernd-edlinger opened 1 month ago
If both versions support TLS-1.3 they must never choose older version. If they cannot agree on supported groups connection failure is inevitable.
The problem is the client cannot know how the server is configured, and therefore the server should take the
signature_algorithms
extension into account, because the meaning of the ECDSA signature algorithm IDs are
quite different for TLS1.3 and for TLS1.2:
TLS1.3 implies a 1:1 connection between ECDSA signature algorithms and EC groups,
but TLS1.2 allows the cross product of signature_algorithms
extension and supported_groups
extension.
The server should know that, and choose TLS1.2 if it has the freedom to do so.
If both sides support TLS 1.3, that should be used. Otherwise you can force the use of older TLS versions.
What you say means that, when the server does only support TLS1.2,
then a man in the middle could simply remove any signature that he don't like
from the signature_algorithms
extension of the client hello, say everything
with sha256, sha384 and sha512 in the name, and neither
the server nor the client will notice anything from this attack?
Please say that there is some kind of a posteriori authentication of the unencrypted handshake messages exchanged between client and server, even if the TLS1.2 protocol is used.
Please say that there is some kind of a posteriori authentication of the unencrypted handshake messages exchanged between client and server, even if the TLS1.2 protocol is used.
The entire handshake is authenticated in the Finished message.
The entire handshake is authenticated in the Finished message.
Thanks for the confirmation.
I want to use the received client hello's signature_algorithm
extension in
addition to the server's configured -sigalgs
in is_tls13_capable
to make
the right decision which protocol to use.
If the server is configured in a way that TLSv1.3 is possible, and the client claims TLSv1.3 support then TLSv1.3 should be negotiated. Even if that means that the handshake later fails because the client and server cannot agree on sigalgs/ciphersuites/whatever.
But, because the client does advertise brainpool in the groups extension but not in the signature_algorithm extension, it is clear that it does simply not implement those and, expects the server to use TLS1.2 only in this case, and TLS1.3 should of course be used for RSA certificates.
it is clear that it does simply not implement those and, expects the server to use TLS1.2 only in this case
I'm failing to see the issue here. The client support TLSv1.3. It doesn't support brainpool sigalgs. The server supports TLSv1.3 and only support brainpool sigalgs. The correct outcome is TLSv1.3 is chosen and then handshake failure results because of the failure to agree on a sigalg. This is the expected outcome.
Okay, then let me summarize how I see the situation:
I have a software that consists of client and server which is distributed over the internet.
The servers can use either RSA, nist, ED25519, ED448 or brainpool certificate.
The clients dont know in advance which certificate type will be used.
Both client and server are prepared for this situation in this way:
They call SSL_CTX_set1_curves
with all required curves, but they do not try to interfere
with the used signature_algorithms, so there is no call to SSL_CTX_set1_sigalgs_list
.
Currently everything is working, but they are currently still using openssl-3.0.
And as soon as the servers will be updated to openssl-3.2 some connections will start to fail.
If I see that right, there will not even be a re-compilation necessary, just replacing the shared objects
will be enough to create unexpected incompatibilities between some servers and some clients.
This is ABSOLUTELY NOT the expected outcome.
So as a compromise how about that:
Instead of looking at the signature_algorithm extension of the client hello, I propose to do this in tls_check_sigalg_curve:
In case of a brainpool curves, if TLS1.2 is not disabled, and the supported groups contain only the TLS1.2 brainpool id, but the TLS1.3 brainpool sigalg is only from the default sigalgs list, and was not explicitly specified, it is clear that this configuration is intended to be useful for TLS1.2, so don't try to negotiate TLS1.3 which might fail.
Finally, I think I am starting to understand the problem you are describing. Sorry for being a bit slow.
Let me describe it in my own words:
In 3.0 there was no support for brainpool certs in TLSv1.3 (but they were supported in TLSv1.2). A server configured with only a brainpool cert runs the "is_tls13_capable" check, discovers that it only has TLSv1.2 capable certs and therefore will only negotiate TLSv1.2 as a maximum
A 3.0 client (which has TLSv1.3 enabled but has no TLSv1.3 brainpool sigalgs support) connects to such a server and the connection is successfully established using TLSv1.2
The server operator then upgrades to 3.2 but does not otherwise change their configuration. In 3.2 we added TLSv1.3 brainpool sigalg support. The server is configured with a brainpool cert and runs the "is_tls13_capable" check. Since it now supports TLSv1.3 with that cert TLSv1.3 is now enabled (where it wasn't prior to the upgrade).
The same 3.0 client (still with TLSv1.3 enabled, but still with no TLSv1.3 brainpool sigalgs support) connects to the server. Since both client and server both have TLSv1.3 enabled, TLSv1.3 is selected. Since the client doesn't have the brainpool sigalgs support the handshake fails.
So, this represents an ABI break because the only change here is that the server upgraded from 3.0 to 3.2 and suddenly handshakes start failing.
Is that correct?
Is that correct?
Yes, exactly.
A possible fix for the ABI break is in #25733
When an openssl-3.0 client wants to support brainpool server certificates, but also allow TLS1.3 with RSA certificates, everything works fine, when both client and server enable brainpool groups, in addition to nist groups. So the client has to use this command line:
./openssl s_client -groups P-256:brainpoolP256r1
and the openssl-3.0 server uses this command line for brainpool:./openssl s_server -cert ../test/certs/server-ecdsa-brainpoolP256r1-cert.pem -key ../test/certs/server-ecdsa-brainpoolP256r1-key.pem -groups P-256:brainpoolP256r1
or this command line for RSA:./openssl s_server
everything works fine, RSA use TLS1.3 and ECC use TLS1.2. Also if both server and client use openssl-3.2 everything works as well, except the ECC use TLS1.3, as expected. BUT the openssl-3.0 client cannot connect to the openssl-3.2 server when the server uses brainpool:Reason is the openssl-3.2 server chooses TLS1.3 although there is no signature algorithm
ecdsa_brainpoolP256r1_sha256
advertised by the openssl-3.0 client, so that is bound to fail. As a workaround either the openssl-3.0 client or the openssl-3.2 server could disable tls1_3 but that is not desirable for the RSA server.