Uploaded image for project: 'Erlang/OTP'
  1. Erlang/OTP
  2. ERL-908

Server-side `function_clause` in TLS 1.3 handshake when client advertises unsupported `signature_algs`

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 22.0
    • Fix Version/s: 22.0
    • Component/s: ssl
    • Labels:
      None

      Description

      While testing RabbitMQ with Erlang/OTP 22 built from the Git master branch, an SSL client (OpenSSL's s_client) is rejected by the Erlang SSL server. The error returned by ssl:handshake/1 is:

      {error,
       {tls_alert,
        {handshake_failure,
         "received SERVER ALERT: Fatal - Handshake Failure - malformed_handshake_data"}}}
      

      The same scenario with Erlang/OTP 21 works just fine.

      The difference is that the TLS 1.3 code path is taken because the client advertises TLS 1.3 as the highest/first version it supports, and only Erlang/OTP 22 supports this new version.

      With Erlang/OTP 22, the code crashes here:

      %% In tls_handshake_1_3.erl
      
      do_check_cert_sign_algo(SignAlgo, SignHash, [Scheme|T]) ->
          %% HERE:
          %% The call below throws a `function_clause` exception because `Scheme`
          %% is set to `unassigned`.
          {Hash, Sign, _Curve} = ssl_cipher:scheme_to_components(Scheme),
          case compare_sign_algos(SignAlgo, SignHash, Sign, Hash) of
              true ->
                  ok;
              _Else ->
                  do_check_cert_sign_algo(SignAlgo, SignHash, T)
          end.
      

      If I understand correctly, unassigned is the fallback value when a signature scheme is unsupported in ssl_cipher:signature_scheme/1. However, ssl_cipher:scheme_to_components/1 doesn't expect to receive that atom.

      The same crash doesn't happen in the TLS 1.2 code path because the unassigned values are filtered before ssl_cipher:scheme_to_components/1 is called, by ssl_handshake:available_signature_algs/4 function.

      I attached the patch I used locally to fix the problem, but I don't know if this is the best approach.

      I also attached the escript and the self-signed certificates I used to start a dummy SSL server. The s_client command line used is available in a comment at the top of the escript.

        Attachments

        1. cacert.pem
          1 kB
        2. cert.pem
          1 kB
        3. erl908.patch
          3 kB
        4. key.pem
          2 kB
        5. ssl.escript
          1 kB
        6. tlsv1.3-handshake.patch
          0.7 kB

          Activity

            People

            Assignee:
            peterdmv Péter Dimitrov
            Reporter:
            dumbbell dumbbell
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: