Using TLS 1.3 with Phoenix

I am using the config in a project of mine and it works with OTP 24.
What kind of error do you get?

For instance, when i try to create a simple tls server implementation (It’s not the real code, I just tried to simulate the problem as an example), as follow:

  defp tls_start() do
    :ssl.start()
    {:ok, listen_socket} = :ssl.listen(8080, [{:certfile, "server.crt"}, {:keyfile, "server.key"}, {:cacertfile, "ca.crt"}, {:reuseaddr, true}, {:versions, [:'tlsv1.3'], ciphers: [%{cipher: :aes_gcm, prf: :sha384}]}]) #%{cipher: :chacha20_poly1305, prf: :sha384}
    {:ok, tls_socket} = :ssl.transport_accept(listen_socket)
    {:ok, socket} = :ssl.handshake(tls_socket)
    {:ok, socket}
  end

I get this error:
(throw) {:option_not_a_key_value_tuple, {:versions, [:"tlsv1.3"], [ciphers: [%{cipher: :aes_gcm, prf: :sha384}]]}}

but according to this Erlang/Otp documentation, otp/tls_record.erl at 3cd45f14afb81f0d569a3c3350fcab172c75d1f0 · erlang/otp · GitHub I am passing the correct erlang cipher suite, right?

could you please share your config?

That should be:

{:ok, listen_socket} = :ssl.listen(8080, [{:certfile, "server.crt"}, {:keyfile, "server.key"}, {:cacertfile, "ca.crt"}, {:reuseaddr, true}, {:versions, [:'tlsv1.3']}, ciphers: [%{cipher: :aes_gcm, prf: :sha384}]])

You didn’t close the {:versions, versions} tuple correctly…

1 Like

Thanks, right,
After fixing to :
{:ok, listen_socket} = :ssl.listen(8080, [{:certfile, "server.crt"}, {:keyfile, "server.key"}, {:cacertfile, "ca.crt"}, {:reuseaddr, true}, {:versions, [:'tlsv1.3']}, ciphers: [%{cipher: :chacha20_poly1305, prf: :sha384}]])

the error is:

(MatchError) no match of right hand side value: {:error, {:options, {:insufficient_crypto_support, {:"tlsv1.3", {:versions, [:"tlsv1.3"]}}}}}
     code: tls_start()

the one that exactly i receive in my real application.

This means the OpenSSL version you are using (or that Erlang/OTPs :crypto module was built against) does not support all the necessary primitives to enable TLS 1.3. You may have to upgrade your OpenSSL version and rebuild Erlang/OTP.

Edit: you can the exact list of what OTP requires from OpenSSL to enable TLS 1.3 here

2 Likes

It looks like chacha20_poly1305 in combination with sha384 is not supported (at least not for my installation):

:ssl.cipher_suites(:all, :'tlsv1.3') |> Enum.filter(fn %{cipher: cipher} -> cipher == :chacha20_poly1305 end)
[
  %{cipher: :chacha20_poly1305, key_exchange: :any, mac: :aead, prf: :sha256},
  %{
    cipher: :chacha20_poly1305,
    key_exchange: :ecdhe_ecdsa,
    mac: :aead,
    prf: :sha256
  },
  %{
    cipher: :chacha20_poly1305,
    key_exchange: :ecdhe_rsa,
    mac: :aead,
    prf: :sha256
  },
  %{
    cipher: :chacha20_poly1305,
    key_exchange: :dhe_rsa,
    mac: :aead,
    prf: :sha256
  }
]

And I think you have to fill all fields of the cipher struct to make it work (or use the string representation), like:

{:ok, listen_socket} = :ssl.listen(
  8080, 
  [
    {:certfile, "server.crt"}, {:keyfile, "server.key"}, {:cacertfile, "ca.crt"}, {:reuseaddr, true}, 
    {:versions, [:'tlsv1.3']},
    ciphers: [
      %{key_exchange: :any, cipher: :chacha20_poly1305, mac: :aead, prf: :sha256}
    ]
  ]
)
2 Likes

Thanks, it was really helpful.

Thanks Voltone, You are right, the issue is with my OpenSSl version.