Skip to content

ssl: Unexpected message received during TLS1.3 session key renewal #10273

@bjosv

Description

@bjosv

Describe the bug
We get an unexpected message passed from ssl:send/2 when a TLS1.3 client socket connection, that is configured to use passive mode, is renewing its session keys.
The message we receive is a {Ref, ok}.

Expected behavior
No message should be received by the process sending messages when session keys are renewed.

Affected versions
The OTP versions that are affected by this bug (tested on):
25.3.2.21, 26.2.5.15, 27.3.4.3, 28.1.0.0

Additional context
As stated we use passive mode. We also have a blocking ssl:recv in another process that isn't a controlling process, but I don't think that matters. The minimal reproduction seem to trigger the issue anyway.

To Reproduce

  1. Prepare certs and keyfiles:
mkdir -p tls
openssl genrsa -out tls/ca.key 4096
openssl req -x509 -new -nodes -key tls/ca.key -sha256 -days 1024 -subj "/C=SE/" -out tls/ca.crt
openssl genrsa -out tls/server.key 4096
openssl req -new -key tls/server.key -subj "/C=SE/CN=localhost/" -out tls/server.csr
openssl x509 -req -in tls/server.csr -CA tls/ca.crt -CAkey tls/ca.key -CAcreateserial -out tls/server.crt -days 500 -sha256
openssl genrsa -out tls/client.key 4096
openssl req -new -sha256 -key tls/client.key -subj "/C=SE/CN=localhost/" | openssl x509 -req -sha256 -CA tls/ca.crt -CAkey tls/ca.key -CAserial tls/ca.txt -CAcreateserial -days 1 -out tls/client.crt
chmod 644 tls/*.key
  1. Start an Erlang shell using a container (and mount certs):
docker run --rm -i -v ./tls:/tls:ro erlang:28.1.0.0-alpine
%% Start a simple TLS listener
ssl:start().
server_recv_loop(Socket) ->
    case ssl:recv(Socket, 0) of
        {ok, _Data} ->
            server_recv_loop(Socket);
        {error, Reason} ->
            io:format(user, "Server error: ~p~n", [Reason])
    end.

spawn(fun() ->
              {ok, LSocket} = ssl:listen(4000, [{certfile,   "tls/server.crt"},
                                                {keyfile,    "tls/server.key"},
                                                {reuseaddr, true},
                                                {active, false},
                                                {versions, ['tlsv1.3']},
                                                {verify, verify_none}]),
              {ok, TSocket} = ssl:transport_accept(LSocket),
              {ok, Socket} = ssl:handshake(TSocket),
              server_recv_loop(Socket)
      end).

Start the client that uses a very low key_update_at value to trigger the problem faster.
The key update seems to give us a {Ref, ok} message

{ok, Socket} = ssl:connect("localhost", 4000, [{active, false}, binary,
                                               {cacertfile, "tls/ca.crt"},
                                               {certfile,   "tls/client.crt"},
                                               {keyfile,    "tls/client.key"},
                                               {server_name_indication, disable},
                                               {key_update_at, 5000},
                                               {versions, ['tlsv1.3']}], infinity).
client_send_loop(Socket) ->
    ssl:send(Socket, "1234567890"),
    receive
        Msg ->
            io:format(user, "Unexpected msg received: ~p~n~n", [Msg]),
            ok
    after 1 ->
            ok
    end,
    client_send_loop(Socket).

client_send_loop(Socket).

Logs received:

Unexpected msg received: {#Ref<0.2397323741.1569456129.138591>,ok}
Unexpected msg received: {#Ref<0.2397323741.1569456129.140081>,ok}
Unexpected msg received: {#Ref<0.2397323741.1569456129.141571>,ok}
Unexpected msg received: {#Ref<0.2397323741.1569456129.143064>,ok}
Unexpected msg received: {#Ref<0.2397323741.1569456129.144554>,ok}

Metadata

Metadata

Assignees

Labels

bugIssue is reported as a bugteam:PSAssigned to OTP team PS

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions