-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
Describe the bug
When a TLS 1.3 server is configured with multiple certificate/key pairs via certs_keys, the server may select a certificate whose public key type is incompatible with the client's signature_algorithms extension. This causes the handshake to fail with insufficient_security / no_suitable_signature_algorithm even though a suitable certificate exists in the server's configuration.
In my tests, this happened when I used two certs: one ECDSA and one RSA, both signed by the same RSA CA. When using a client that only accepts RSA, ssl prioritizes using ECDSA and then fails with:
TLS server: In state start at tls_handshake_1_3.erl:1505 generated SERVER ALERT: Fatal - Insufficient Security
- no_suitable_signature_algorithm
To Reproduce
Have a server listening with multiple cert types:
CertsKeys = [
#{cert => ECDSACert, key => ECDSAKey},
#{cert => RSACert, key => RSAKey}
],
ServerOpts = [{certs_keys, CertsKeys}, {versions, ['tlsv1.3']}],
{ok, LSock} = ssl:listen(Port, ServerOpts).Connect to it with restricted signature_algs:
ClientOpts = [
{verify, verify_peer},
{cacerts, [RSACACert]},
{versions, ['tlsv1.3']},
{signature_algs, [rsa_pss_rsae_sha256]},
{signature_algs_cert, [rsa_pkcs1_sha256, rsa_pss_rsae_sha256]}
],
{ok, Sock} = ssl:connect(Host, Port, ClientOpts).A script in this repository does all the setup and compares the erlang server with openssl_s, which succeeds with the same client configuration.
Expected behavior
Sucessfully handshake, like openssl_s.
Affected versions
At least 27.3 and main.