4

I'm trying to create a simple SSL server that uses a Pre-Shared Key to authenticate a client (no ssl certs). It seems this functionality exists in the Erlang ssl module, but it's unclear to me how to use it effectively. It's worth mentioning I'm attempting to use it in Elixir (eventually as a GenServer).

I've made a simple example that should just accept a connection, and then proceed with a handshake when a client connects.

# Server
defmodule SimpleSSLServer do
  def start() do
    :ssl.start()

    # Limit Cipers to what supports PSKs
    ciphers_suites =
      :ssl.cipher_suites(:all, :"tlsv1.3")
      |> Enum.filter(&match?(%{cipher: cip} when cip in [:aes_128_gcm], &1))

    {:ok, listen_socket} =
      :ssl.listen(8085,
        reuseaddr: true,
        user_lookup_fun:
          {&user_lookup/3, "001122334455ff001122334455ff001122334455ff001122334455ff"},
        ciphers: ciphers_suites
      )

    {:ok, transport_socket} = :ssl.transport_accept(listen_socket)
    {:ok, _socket} = :ssl.handshake(transport_socket)
  end

  def user_lookup(:psk, _id, state) do
    {:ok, state}
  end
end

SimpleSSLServer.start()
# Client 
openssl s_client -connect 127.0.0.1:8085 -psk 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f -tls1_3 -ciphersuites TLS_AES_128_GCM_SHA256

This application compiles, and when you run the server and connect a client the following message occurs:

** (exit) exited in: :gen_statem.call(#PID<0.187.0>, {:start, :infinity}, :infinity)
    ** (EXIT) an exception was raised:
        ** (MatchError) no match of right hand side value: {:state, {:static_env, :server, :gen_tcp, :tls_gen_connection, :tcp, :tcp_closed, :tcp_error, :tcp_passive, 'localhost', 8085, ...super long amount of state
            (ssl 10.6.1) tls_handshake_1_3.erl:652: :tls_handshake_1_3.do_start/2
            (ssl 10.6.1) tls_connection_1_3.erl:269: :tls_connection_1_3.start/3
            (stdlib 3.17) gen_statem.erl:1203: :gen_statem.loop_state_callback/11
            (ssl 10.6.1) tls_connection.erl:154: :tls_connection.init/1
            (stdlib 3.17) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
    (stdlib 3.17) gen.erl:220: :gen.do_call/4
    (stdlib 3.17) gen_statem.erl:693: :gen_statem.call_dirty/4
    (ssl 10.6.1) ssl_gen_statem.erl:1187: :ssl_gen_statem.call/2
    (ssl 10.6.1) ssl_gen_statem.erl:223: :ssl_gen_statem.handshake/2
    test.exs:18: SimpleSSLServer.start/0

Any help is appreciated, this is likely something very obvious I'm missing!

clone1018
  • 1,207
  • 2
  • 10
  • 13
  • Interestingly, if you provide the regular cert arguments to the `:ssl.listen` options, it works just fine and ignores the cert options. For example: `keyfile: "selfsigned_key.pem", certfile: "selfsigned.pem"` – clone1018 Feb 09 '22 at 15:38

0 Answers0