summaryrefslogtreecommitdiff
path: root/lib/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/doc/src/notes.xml47
-rw-r--r--lib/ssl/doc/src/ssl.xml6
-rw-r--r--lib/ssl/src/Makefile1
-rw-r--r--lib/ssl/src/dtls_connection.erl263
-rw-r--r--lib/ssl/src/dtls_connection_sup.erl28
-rw-r--r--lib/ssl/src/dtls_gen_connection.erl183
-rw-r--r--lib/ssl/src/dtls_handshake.erl36
-rw-r--r--lib/ssl/src/dtls_listener_sup.erl29
-rw-r--r--lib/ssl/src/dtls_record.erl16
-rw-r--r--lib/ssl/src/dtls_server_session_cache_sup.erl27
-rw-r--r--lib/ssl/src/dtls_server_sup.erl47
-rw-r--r--lib/ssl/src/dtls_sup.erl47
-rw-r--r--lib/ssl/src/inet_tls_dist.erl14
-rw-r--r--lib/ssl/src/ssl.app.src1
-rw-r--r--lib/ssl/src/ssl.erl17
-rw-r--r--lib/ssl/src/ssl_admin_sup.erl57
-rw-r--r--lib/ssl/src/ssl_alert.hrl11
-rw-r--r--lib/ssl/src/ssl_certificate.erl4
-rw-r--r--lib/ssl/src/ssl_cipher.erl182
-rw-r--r--lib/ssl/src/ssl_connection_sup.erl41
-rw-r--r--lib/ssl/src/ssl_crl.erl16
-rw-r--r--lib/ssl/src/ssl_dist_admin_sup.erl42
-rw-r--r--lib/ssl/src/ssl_dist_connection_sup.erl23
-rw-r--r--lib/ssl/src/ssl_dist_sup.erl40
-rw-r--r--lib/ssl/src/ssl_gen_statem.erl31
-rw-r--r--lib/ssl/src/ssl_handshake.erl38
-rw-r--r--lib/ssl/src/ssl_listen_tracker_sup.erl27
-rw-r--r--lib/ssl/src/ssl_record.erl28
-rw-r--r--lib/ssl/src/ssl_server_session_cache_sup.erl29
-rw-r--r--lib/ssl/src/ssl_sup.erl43
-rw-r--r--lib/ssl/src/ssl_upgrade_server_session_cache_sup.erl27
-rw-r--r--lib/ssl/src/tls_connection.erl221
-rw-r--r--lib/ssl/src/tls_connection_1_3.erl36
-rw-r--r--lib/ssl/src/tls_connection_sup.erl28
-rw-r--r--lib/ssl/src/tls_dist_server_sup.erl63
-rw-r--r--lib/ssl/src/tls_dist_sup.erl46
-rw-r--r--lib/ssl/src/tls_dtls_connection.erl166
-rw-r--r--lib/ssl/src/tls_dyn_connection_sup.erl78
-rw-r--r--lib/ssl/src/tls_gen_connection.erl33
-rw-r--r--lib/ssl/src/tls_handshake.erl83
-rw-r--r--lib/ssl/src/tls_record.erl28
-rw-r--r--lib/ssl/src/tls_record_1_3.erl5
-rw-r--r--lib/ssl/src/tls_sender.erl43
-rw-r--r--lib/ssl/src/tls_server_session_ticket_sup.erl28
-rw-r--r--lib/ssl/src/tls_server_sup.erl81
-rw-r--r--lib/ssl/src/tls_socket.erl23
-rw-r--r--lib/ssl/src/tls_sup.erl43
-rw-r--r--lib/ssl/test/dtls_api_SUITE.erl68
-rw-r--r--lib/ssl/test/openssl_client_cert_SUITE.erl54
-rw-r--r--lib/ssl/test/property_test/ssl_eqc_cipher_format.erl59
-rw-r--r--lib/ssl/test/ssl_api_SUITE.erl145
-rw-r--r--lib/ssl/test/ssl_cert_SUITE.erl48
-rw-r--r--lib/ssl/test/ssl_dist_SUITE.erl68
-rw-r--r--lib/ssl/test/ssl_dist_test_lib.erl75
-rw-r--r--lib/ssl/test/ssl_dist_test_lib.hrl4
-rw-r--r--lib/ssl/test/ssl_eqc_SUITE.erl7
-rw-r--r--lib/ssl/test/ssl_session_SUITE.erl59
-rw-r--r--lib/ssl/test/ssl_test_lib.erl61
-rw-r--r--lib/ssl/test/tls_1_3_record_SUITE.erl2
-rw-r--r--lib/ssl/test/tls_api_SUITE.erl35
-rw-r--r--lib/ssl/vsn.mk2
61 files changed, 1890 insertions, 1203 deletions
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 7ca6cc2e5b..b8cab8cce7 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -27,6 +27,53 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
+<section><title>SSL 10.5.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct typo of ECC curve name in signature algorithm
+ handling. Will make the signature algorithm
+ ecdsa_secp521r1_sha512 succeed.</p>
+ <p>
+ Own Id: OTP-17756 Aux Id: GH-5383, PR-5397 </p>
+ </item>
+ <item>
+ <p>
+ Suppress authenticity warning when option verify_none is
+ explicitly supplied.</p>
+ <p>
+ Own Id: OTP-17757 Aux Id: GH-5352, PR-5395 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.5.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix TLS-1.2 RSA-PSS negotiation and also fix broken
+ certificate request message for pre-TLS-1.3 servers.</p>
+ <p>
+ Own Id: OTP-17688 Aux Id: GH-5255 </p>
+ </item>
+ <item>
+ <p>
+ Fix CRL issuer verification that under some circumstances
+ could fail with a function_clause error.</p>
+ <p>
+ Own Id: OTP-17723 Aux Id: GH-5300 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 10.5.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index 700d8be5fb..0b4bf3b3c7 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -485,7 +485,7 @@ version.
</p>
<note> <p> TLS-1.2 algorithms will not be negotiated for TLS-1.3, but TLS-1.3 RSASSA-PSS <seetype marker="#rsassa_pss_scheme">rsassa_pss_scheme()</seetype>
- signature schemes may be negotiated also for TLS-1.2 from @OTP-16590@
+ signature schemes may be negotiated also for TLS-1.2 from 24.1 (fully working from 24.1.3).
However if TLS-1.3 is negotiated when both TLS-1.3 and TLS-1.2 is supported using defaults, the corresponding TLS-1.2 algorithms
to the TLS-1.3 legacy signature schemes will be considered as the legacy schemes and applied only to certificate signatures.
</p>
@@ -519,7 +519,7 @@ version.
<p>
The client will send a <c>signature_algorithms_cert</c> extension
(in the client hello message), if TLS version 1.2
- (back-ported to TLS 1.2 in @OTP-16590@) or later is used, and
+ (back-ported to TLS 1.2 in 24.1) or later is used, and
the signature_algs_cert option is explicitly specified. By
default, only the <seetype
marker="#signature_algs">signature_algs</seetype> extension
@@ -884,7 +884,7 @@ fun(srp, Username :: binary(), UserState :: term()) ->
<datatype>
<name name="ssl_imp"/>
- <desc><p>Deprecated since OTP-17, has no affect.</p></desc>
+ <desc><p>Deprecated since OTP-17, has no effect.</p></desc>
</datatype>
<datatype>
diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile
index 9cbee91946..1ba0f49f91 100644
--- a/lib/ssl/src/Makefile
+++ b/lib/ssl/src/Makefile
@@ -103,6 +103,7 @@ MODULES= \
tls_client_ticket_store \
tls_dist_sup \
tls_dist_server_sup \
+ tls_dyn_connection_sup\
tls_sender \
tls_server_session_ticket\
tls_server_session_ticket_sup\
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index 1a4f001273..47e0e9f90a 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -132,6 +132,8 @@
-export([renegotiate/2]).
+-export([alert_or_reset_connection/3]). %% Code re-use from dtls_gen_connection.
+
%% gen_statem state functions
-export([initial_hello/3,
config_error/3,
@@ -200,14 +202,19 @@ initial_hello({call, From}, {start, Timeout},
#state{static_env = #static_env{host = Host,
port = Port,
role = client,
+ socket = {_, Socket},
+ transport_cb = Transport,
session_cache = Cache,
session_cache_cb = CacheCb},
+ protocol_specific = PS,
handshake_env = #handshake_env{renegotiation = {Renegotiation, _}},
connection_env = CEnv,
ssl_options = #{versions := Versions} = SslOpts,
session = #session{own_certificates = OwnCerts} = NewSession,
connection_states = ConnectionStates0
} = State0) ->
+ Packages = maps:get(active_n, PS),
+ dtls_socket:setopts(Transport, Socket, [{active,Packages}]),
Session = ssl_session:client_select_session({Host, Port, SslOpts}, Cache, CacheCb, NewSession),
Hello = dtls_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
Session#session.session_id, Renegotiation, OwnCerts),
@@ -223,17 +230,15 @@ initial_hello({call, From}, {start, Timeout},
State1#state{connection_env =
CEnv#connection_env{negotiated_version = HelloVersion}}),
State = State2#state{connection_env = CEnv#connection_env{negotiated_version = Version}, %% RequestedVersion
- session = Session,
- start_or_recv_from = From},
+ session = Session,
+ start_or_recv_from = From,
+ protocol_specific = PS#{active_n_toggle := false}
+ },
dtls_gen_connection:next_event(hello, no_record, State, [{{timeout, handshake}, Timeout, close} | Actions]);
initial_hello({call, _} = Type, Event, #state{static_env = #static_env{role = server},
- protocol_specific = PS} = State) ->
- Result = ssl_gen_statem:?FUNCTION_NAME(Type, Event,
- State#state{protocol_specific =
- PS#{current_cookie_secret => dtls_v1:cookie_secret(),
- previous_cookie_secret => <<>>,
- ignored_alerts => 0,
- max_ignored_alerts => 10}}),
+ protocol_specific = PS0} = State) ->
+ PS = PS0#{current_cookie_secret => dtls_v1:cookie_secret(), previous_cookie_secret => <<>>},
+ Result = ssl_gen_statem:?FUNCTION_NAME(Type, Event, State#state{protocol_specific = PS}),
erlang:send_after(dtls_v1:cookie_timeout(), self(), new_cookie_secret),
Result;
initial_hello(Type, Event, State) ->
@@ -268,7 +273,7 @@ hello(internal, #client_hello{cookie = <<>>,
handshake_env = HsEnv,
connection_env = CEnv,
protocol_specific = #{current_cookie_secret := Secret}} = State0) ->
- case tls_dtls_connection:handle_sni_extension(State0, Hello) of
+ try tls_dtls_connection:handle_sni_extension(State0, Hello) of
#state{} = State1 ->
{ok, {IP, Port}} = dtls_socket:peername(Transport, Socket),
Cookie = dtls_handshake:cookie(Secret, IP, Port, Hello),
@@ -285,9 +290,9 @@ hello(internal, #client_hello{cookie = <<>>,
State#state{handshake_env = HsEnv#handshake_env{
tls_handshake_history =
ssl_handshake:init_handshake_history()}},
- Actions);
- #alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version,?FUNCTION_NAME, State0)
+ Actions)
+ catch throw:#alert{} = Alert ->
+ alert_or_reset_connection(Alert, ?FUNCTION_NAME, State0)
end;
hello(internal, #hello_verify_request{cookie = Cookie},
#state{static_env = #static_env{role = client,
@@ -317,27 +322,18 @@ hello(internal, #hello_verify_request{cookie = Cookie},
State = State2#state{connection_env = CEnv#connection_env{negotiated_version = Version} % RequestedVersion
},
dtls_gen_connection:next_event(?FUNCTION_NAME, no_record, State, Actions);
-hello(internal, #client_hello{extensions = Extensions, client_version = ClientVersion} = Hello,
+hello(internal, #client_hello{extensions = Extensions} = Hello,
#state{ssl_options = #{handshake := hello},
handshake_env = HsEnv,
start_or_recv_from = From} = State0) ->
- case tls_dtls_connection:handle_sni_extension(State0, Hello) of
+ try tls_dtls_connection:handle_sni_extension(State0, Hello) of
#state{} = State ->
{next_state, user_hello, State#state{start_or_recv_from = undefined,
handshake_env = HsEnv#handshake_env{hello = Hello}},
- [{reply, From, {ok, Extensions}}]};
- #alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, ClientVersion, ?FUNCTION_NAME, State0)
+ [{reply, From, {ok, Extensions}}]}
+ catch throw:#alert{} = Alert ->
+ alert_or_reset_connection(Alert, ?FUNCTION_NAME, State0)
end;
-hello(internal, #server_hello{extensions = Extensions} = Hello,
- #state{ssl_options = #{
- handshake := hello},
- handshake_env = HsEnv,
- start_or_recv_from = From} = State) ->
- {next_state, user_hello, State#state{start_or_recv_from = undefined,
- handshake_env = HsEnv#handshake_env{
- hello = Hello}},
- [{reply, From, {ok, Extensions}}]};
hello(internal, #client_hello{cookie = Cookie} = Hello, #state{static_env = #static_env{role = server,
transport_cb = Transport,
socket = Socket},
@@ -350,32 +346,42 @@ hello(internal, #client_hello{cookie = Cookie} = Hello, #state{static_env = #sta
handle_client_hello(Hello, State);
_ ->
case dtls_handshake:cookie(PSecret, IP, Port, Hello) of
- Cookie ->
+ Cookie ->
handle_client_hello(Hello, State);
_ ->
%% Handle bad cookie as new cookie request RFC 6347 4.1.2
hello(internal, Hello#client_hello{cookie = <<>>}, State)
end
end;
+hello(internal, #server_hello{extensions = Extensions} = Hello,
+ #state{ssl_options = #{
+ handshake := hello},
+ handshake_env = HsEnv,
+ start_or_recv_from = From} = State) ->
+ {next_state, user_hello, State#state{start_or_recv_from = undefined,
+ handshake_env = HsEnv#handshake_env{
+ hello = Hello}},
+ [{reply, From, {ok, Extensions}}]};
+
hello(internal, #server_hello{} = Hello,
#state{
static_env = #static_env{role = client},
handshake_env = #handshake_env{
- renegotiation = {Renegotiation, _},
- ocsp_stapling_state = OcspState0} = HsEnv,
- connection_env = #connection_env{negotiated_version = ReqVersion},
+ renegotiation = {Renegotiation, _},
+ ocsp_stapling_state = OcspState0} = HsEnv,
connection_states = ConnectionStates0,
session = #session{session_id = OldId},
ssl_options = SslOptions} = State) ->
- case dtls_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation, OldId) of
- #alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, ReqVersion, ?FUNCTION_NAME, State);
- {Version, NewId, ConnectionStates, ProtoExt, Protocol, OcspState} ->
- tls_dtls_connection:handle_session(Hello,
- Version, NewId, ConnectionStates, ProtoExt, Protocol,
- State#state{handshake_env =
- HsEnv#handshake_env{
- ocsp_stapling_state = maps:merge(OcspState0,OcspState)}})
+ try
+ {Version, NewId, ConnectionStates, ProtoExt, Protocol, OcspState} =
+ dtls_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation, OldId),
+ tls_dtls_connection:handle_session(Hello,
+ Version, NewId, ConnectionStates, ProtoExt, Protocol,
+ State#state{handshake_env =
+ HsEnv#handshake_env{
+ ocsp_stapling_state = maps:merge(OcspState0,OcspState)}})
+ catch throw:#alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
end;
hello(internal, {handshake, {#client_hello{cookie = <<>>} = Handshake, _}}, State) ->
%% Initial hello should not be in handshake history
@@ -487,12 +493,19 @@ cipher(Type, Event, State) ->
gen_handshake(?FUNCTION_NAME, Type, Event, State).
%%--------------------------------------------------------------------
--spec connection(gen_statem:event_type(),
+-spec connection(gen_statem:event_type(),
#hello_request{} | #client_hello{}| term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-connection(enter, _, State) ->
- {keep_state, State};
+connection(enter, _, #state{connection_states = Cs0} = State0) ->
+ State = case maps:is_key(previous_cs, Cs0) of
+ false ->
+ State0;
+ true ->
+ Cs = maps:remove(previous_cs, Cs0),
+ State0#state{connection_states = Cs}
+ end,
+ {keep_state, State};
connection(info, Event, State) ->
gen_info(Event, ?FUNCTION_NAME, State);
connection(internal, #hello_request{}, #state{static_env = #static_env{host = Host,
@@ -541,14 +554,42 @@ connection(internal, #client_hello{}, #state{static_env = #static_env{role = ser
State1 = dtls_gen_connection:send_alert(Alert, State0),
{Record, State} = ssl_gen_statem:prepare_connection(State1, Connection),
dtls_gen_connection:next_event(?FUNCTION_NAME, Record, State);
+connection(internal, new_connection, #state{ssl_options=SSLOptions,
+ handshake_env=HsEnv,
+ connection_states = OldCs} = State) ->
+ case maps:get(previous_cs, OldCs, undefined) of
+ undefined ->
+ #{beast_mitigation := BeastMitigation} = SSLOptions,
+ ConnectionStates0 = dtls_record:init_connection_states(server, BeastMitigation),
+ ConnectionStates = ConnectionStates0#{previous_cs => OldCs},
+ {next_state, hello, State#state{handshake_env = HsEnv#handshake_env{renegotiation = {false, first}},
+ connection_states = ConnectionStates}};
+ _ ->
+ %% Someone spamming new_connection, just drop them
+ {keep_state, State}
+ end;
+
connection({call, From}, {application_data, Data}, State) ->
try
send_application_data(Data, From, ?FUNCTION_NAME, State)
catch throw:Error ->
ssl_gen_statem:hibernate_after(?FUNCTION_NAME, State, [{reply, From, Error}])
end;
+connection({call, From}, {downgrade, Pid},
+ #state{connection_env = CEnv,
+ static_env = #static_env{transport_cb = Transport,
+ socket = {_Server, Socket} = DTLSSocket}} = State) ->
+ %% For testing purposes, downgrades without noticing the server
+ dtls_socket:setopts(Transport, Socket, [{active, false}, {packet, 0}, {mode, binary}]),
+ Transport:controlling_process(Socket, Pid),
+ {stop_and_reply, {shutdown, normal}, {reply, From, {ok, DTLSSocket}},
+ State#state{connection_env = CEnv#connection_env{socket_terminated = true}}};
connection(Type, Event, State) ->
- tls_dtls_connection:?FUNCTION_NAME(Type, Event, State).
+ try
+ tls_dtls_connection:?FUNCTION_NAME(Type, Event, State)
+ catch throw:#alert{}=Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
+ end.
%%TODO does this make sense for DTLS ?
%%--------------------------------------------------------------------
@@ -558,7 +599,12 @@ connection(Type, Event, State) ->
downgrade(enter, _, State) ->
{keep_state, State};
downgrade(Type, Event, State) ->
- tls_dtls_connection:?FUNCTION_NAME(Type, Event, State).
+ try
+ tls_dtls_connection:?FUNCTION_NAME(Type, Event, State)
+ catch throw:#alert{}=Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
+ end.
+
%%--------------------------------------------------------------------
%% gen_statem callbacks
@@ -620,12 +666,15 @@ initial_state(Role, Host, Port, Socket,
flight_buffer = dtls_gen_connection:new_flight(),
protocol_specific = #{active_n => InternalActiveN,
active_n_toggle => true,
- flight_state => dtls_gen_connection:initial_flight_state(DataTag)}
+ flight_state => dtls_gen_connection:initial_flight_state(DataTag),
+ ignored_alerts => 0,
+ max_ignored_alerts => 10
+ }
}.
handle_client_hello(#client_hello{client_version = ClientVersion} = Hello, State0) ->
- case tls_dtls_connection:handle_sni_extension(State0, Hello) of
+ try
#state{connection_states = ConnectionStates0,
static_env = #static_env{trackers = Trackers},
handshake_env = #handshake_env{kex_algorithm = KeyExAlg,
@@ -633,31 +682,28 @@ handle_client_hello(#client_hello{client_version = ClientVersion} = Hello, State
negotiated_protocol = CurrentProtocol} = HsEnv,
connection_env = CEnv,
session = #session{own_certificates = OwnCerts} = Session0,
- ssl_options = SslOpts} = State1 ->
- SessionTracker = proplists:get_value(session_id_tracker, Trackers),
- case dtls_handshake:hello(Hello, SslOpts, {SessionTracker, Session0,
- ConnectionStates0, OwnCerts, KeyExAlg}, Renegotiation) of
- #alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, ClientVersion, hello, State1);
- {Version, {Type, Session},
- ConnectionStates, Protocol0, ServerHelloExt, HashSign} ->
- Protocol = case Protocol0 of
- undefined -> CurrentProtocol;
- _ -> Protocol0
- end,
-
- State = prepare_flight(State0#state{connection_states = ConnectionStates,
- connection_env = CEnv#connection_env{negotiated_version = Version},
- handshake_env = HsEnv#handshake_env{
- hashsign_algorithm = HashSign,
- client_hello_version = ClientVersion,
- negotiated_protocol = Protocol},
- session = Session}),
- {next_state, hello, State, [{next_event, internal, {common_client_hello, Type, ServerHelloExt}}]}
- end;
- #alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, ClientVersion, hello, State0)
- end.
+ ssl_options = SslOpts} =
+ tls_dtls_connection:handle_sni_extension(State0, Hello),
+ SessionTracker = proplists:get_value(session_id_tracker, Trackers),
+ {Version, {Type, Session}, ConnectionStates, Protocol0, ServerHelloExt, HashSign} =
+ dtls_handshake:hello(Hello, SslOpts, {SessionTracker, Session0,
+ ConnectionStates0, OwnCerts, KeyExAlg}, Renegotiation),
+ Protocol = case Protocol0 of
+ undefined -> CurrentProtocol;
+ _ -> Protocol0
+ end,
+
+ State = prepare_flight(State0#state{connection_states = ConnectionStates,
+ connection_env = CEnv#connection_env{negotiated_version = Version},
+ handshake_env = HsEnv#handshake_env{
+ hashsign_algorithm = HashSign,
+ client_hello_version = ClientVersion,
+ negotiated_protocol = Protocol},
+ session = Session}),
+ {next_state, hello, State, [{next_event, internal, {common_client_hello, Type, ServerHelloExt}}]}
+ catch #alert{} = Alert ->
+ alert_or_reset_connection(Alert, hello, State0)
+ end.
handle_state_timeout(flight_retransmission_timeout, StateName,
@@ -670,40 +716,43 @@ handle_state_timeout(flight_retransmission_timeout, StateName,
%% This will reset the retransmission timer by repeating the enter state event
{repeat_state, State, Actions}.
+alert_or_reset_connection(Alert, StateName, #state{connection_states = Cs} = State) ->
+ case maps:get(previous_cs, Cs, undefined) of
+ undefined ->
+ ssl_gen_statem:handle_own_alert(Alert, StateName, State);
+ PreviousConn ->
+ %% There exists an old connection and the new one failed,
+ %% reset to the old working one.
+ %% The next alert will be sent
+ HsEnv0 = State#state.handshake_env,
+ HsEnv = HsEnv0#handshake_env{renegotiation = undefined},
+ NewState = State#state{connection_states = PreviousConn,
+ handshake_env = HsEnv
+ },
+ {next_state, connection, NewState}
+ end.
-
-gen_handshake(StateName, Type, Event,
- #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
- try tls_dtls_connection:StateName(Type, Event, State) of
- Result ->
- Result
- catch
- _:_ ->
- ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,
- malformed_handshake_data),
- Version, StateName, State)
+gen_handshake(StateName, Type, Event, State) ->
+ try tls_dtls_connection:StateName(Type, Event, State)
+ catch
+ throw:#alert{}=Alert ->
+ alert_or_reset_connection(Alert, StateName, State);
+ error:_ ->
+ Alert = ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data),
+ alert_or_reset_connection(Alert, StateName, State)
end.
-gen_info(Event, connection = StateName, #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
- try dtls_gen_connection:handle_info(Event, StateName, State) of
- Result ->
- Result
- catch
- _:_ ->
- ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?INTERNAL_ERROR,
- malformed_data),
- Version, StateName, State)
+gen_info(Event, connection = StateName, State) ->
+ try dtls_gen_connection:handle_info(Event, StateName, State)
+ catch error:_ ->
+ Alert = ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, malformed_data),
+ alert_or_reset_connection(Alert, StateName, State)
end;
-
-gen_info(Event, StateName, #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
- try dtls_gen_connection:handle_info(Event, StateName, State) of
- Result ->
- Result
- catch
- _:_ ->
- ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,
- malformed_handshake_data),
- Version, StateName, State)
+gen_info(Event, StateName, State) ->
+ try dtls_gen_connection:handle_info(Event, StateName, State)
+ catch error:_ ->
+ Alert = ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,malformed_handshake_data),
+ alert_or_reset_connection(Alert, StateName, State)
end.
prepare_flight(#state{flight_buffer = Flight,
@@ -763,7 +812,7 @@ send_application_data(Data, From, _StateName,
{Msgs, ConnectionStates} =
dtls_record:encode_data(Data, Version, ConnectionStates0),
State = State0#state{connection_states = ConnectionStates},
- case dtls_gen_connection:send(Transport, Socket, Msgs) of
+ case send_msgs(Transport, Socket, Msgs) of
ok ->
ssl_logger:debug(LogLevel, outbound, 'record', Msgs),
ssl_gen_statem:hibernate_after(connection, State, [{reply, From, ok}]);
@@ -772,6 +821,14 @@ send_application_data(Data, From, _StateName,
end
end.
+send_msgs(Transport, Socket, [Msg|Msgs]) ->
+ case dtls_gen_connection:send(Transport, Socket, Msg) of
+ ok -> send_msgs(Transport, Socket, Msgs);
+ Error -> Error
+ end;
+send_msgs(_, _, []) ->
+ ok.
+
time_to_renegotiate(_Data,
#{current_write := #{sequence_number := Num}},
RenegotiateAt) ->
diff --git a/lib/ssl/src/dtls_connection_sup.erl b/lib/ssl/src/dtls_connection_sup.erl
index 4c5c0a490f..b2b9708209 100644
--- a/lib/ssl/src/dtls_connection_sup.erl
+++ b/lib/ssl/src/dtls_connection_sup.erl
@@ -51,17 +51,17 @@ start_child_dist(Args) ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
-init(_O) ->
- RestartStrategy = simple_one_for_one,
- MaxR = 0,
- MaxT = 3600,
-
- Name = undefined, % As simple_one_for_one is used.
- StartFunc = {ssl_gen_statem, start_link, []},
- Restart = temporary, % E.g. should not be restarted
- Shutdown = 4000,
- Modules = [ssl_gen_statem, dtls_connection],
- Type = worker,
-
- ChildSpec = {Name, StartFunc, Restart, Shutdown, Type, Modules},
- {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}.
+init(_) ->
+ SupFlags = #{strategy => simple_one_for_one,
+ intensity => 0,
+ period => 3600
+ },
+ ChildSpecs = [#{id => undefined,
+ start => {ssl_gen_statem, start_link, []},
+ restart => temporary,
+ shutdown => 4000,
+ modules => [ssl_gen_statem, dtls_connection],
+ type => worker
+ }
+ ],
+ {ok, {SupFlags, ChildSpecs}}.
diff --git a/lib/ssl/src/dtls_gen_connection.erl b/lib/ssl/src/dtls_gen_connection.erl
index 2032d77074..dab05335c0 100644
--- a/lib/ssl/src/dtls_gen_connection.erl
+++ b/lib/ssl/src/dtls_gen_connection.erl
@@ -68,6 +68,14 @@
send_alert_in_connection/2,
close/5,
protocol_name/0]).
+
+
+%% See thread @ http://lists.cluenet.de/pipermail/ipv6-ops/2011-June/005755.html
+%% 1280 - headers
+-define(PMTUEstimate, 1200).
+
+
+
%%====================================================================
%% Internal application API
%%====================================================================
@@ -105,30 +113,29 @@ next_record(#state{protocol_buffers =
CurrentRead = dtls_record:get_connection_state_by_epoch(Epoch, ConnectionStates, read),
case dtls_record:replay_detect(CT, CurrentRead) of
false ->
- decode_cipher_text(State#state{connection_states = ConnectionStates}) ;
+ decode_cipher_text(State) ;
true ->
%% Ignore replayed record
- next_record(State#state{protocol_buffers =
- Buffers#protocol_buffers{dtls_cipher_texts = Rest},
- connection_states = ConnectionStates})
+ next_record(State#state{protocol_buffers = Buffers#protocol_buffers{dtls_cipher_texts = Rest}})
end;
next_record(#state{protocol_buffers =
#protocol_buffers{dtls_cipher_texts = [#ssl_tls{epoch = Epoch} | Rest]}
= Buffers,
- connection_states = #{current_read := #{epoch := CurrentEpoch}} = ConnectionStates} = State)
+ connection_states = #{current_read := #{epoch := CurrentEpoch}}} = State)
when Epoch > CurrentEpoch ->
%% TODO Buffer later Epoch message, drop it for now
- next_record(State#state{protocol_buffers =
- Buffers#protocol_buffers{dtls_cipher_texts = Rest},
- connection_states = ConnectionStates});
-next_record(#state{protocol_buffers =
- #protocol_buffers{dtls_cipher_texts = [ _ | Rest]}
- = Buffers,
- connection_states = ConnectionStates} = State) ->
- %% Drop old epoch message
- next_record(State#state{protocol_buffers =
- Buffers#protocol_buffers{dtls_cipher_texts = Rest},
- connection_states = ConnectionStates});
+ next_record(State#state{protocol_buffers = Buffers#protocol_buffers{dtls_cipher_texts = Rest}});
+next_record(#state{protocol_buffers = #protocol_buffers{dtls_cipher_texts =
+ [#ssl_tls{epoch = Epoch} | Rest]
+ } = Buffers
+ } = State) ->
+ case Epoch of
+ 0 -> %% A reconnect (client might have rebooted and re-connected)
+ decode_cipher_text(State);
+ _ ->
+ %% Drop old epoch message
+ next_record(State#state{protocol_buffers = Buffers#protocol_buffers{dtls_cipher_texts = Rest}})
+ end;
next_record(#state{static_env = #static_env{role = server,
socket = {Listener, {Client, _}}}} = State) ->
dtls_packet_demux:active_once(Listener, Client, self()),
@@ -182,16 +189,16 @@ next_event(StateName, no_record,
%% TODO maybe buffer later epoch
next_event(StateName, no_record, State, Actions);
{#alert{} = Alert, State} ->
- Version = State#state.connection_env#connection_env.negotiated_version,
- handle_own_alert(Alert, Version, StateName, State)
+ handle_own_alert(Alert, StateName, State)
end;
next_event(connection = StateName, Record,
#state{connection_states = #{current_read := #{epoch := CurrentEpoch}}} = State0, Actions) ->
case Record of
- #ssl_tls{epoch = CurrentEpoch,
+ #ssl_tls{epoch = Epoch,
type = ?HANDSHAKE,
- version = Version} = Record ->
- State = dtls_version(StateName, Version, State0),
+ version = Version} = Record
+ when Epoch =:= CurrentEpoch; Epoch =:= 0 ->
+ State = dtls_version(StateName, Version, State0),
{next_state, StateName, State,
[{next_event, internal, {protocol_record, Record}} | Actions]};
#ssl_tls{epoch = CurrentEpoch} ->
@@ -223,8 +230,7 @@ next_event(StateName, Record,
%% TODO maybe buffer later epoch
next_event(StateName, no_record, State0, Actions);
#alert{} = Alert ->
- Version = State0#state.connection_env#connection_env.negotiated_version,
- handle_own_alert(Alert, Version, StateName, State0)
+ handle_own_alert(Alert, StateName, State0)
end.
initial_flight_state(udp)->
@@ -246,12 +252,11 @@ send_handshake_flight(#state{static_env = #static_env{socket = Socket,
connection_states = ConnectionStates0,
ssl_options = #{log_level := LogLevel}} = State0,
Epoch) ->
- PMTUEstimate = 1400, %% TODO make configurable
#{current_write := #{max_fragment_length := MaxFragmentLength}} = ConnectionStates0,
- MaxSize = min(MaxFragmentLength, PMTUEstimate),
+ MaxSize = min(MaxFragmentLength, ?PMTUEstimate),
{Encoded, ConnectionStates} =
encode_handshake_flight(lists:reverse(Flight), Version, MaxSize, Epoch, ConnectionStates0),
- send(Transport, Socket, Encoded),
+ send_packets(Transport, Socket, Encoded),
ssl_logger:debug(LogLevel, outbound, 'record', Encoded),
{State0#state{connection_states = ConnectionStates}, []};
@@ -264,14 +269,12 @@ send_handshake_flight(#state{static_env = #static_env{socket = Socket,
connection_states = ConnectionStates0,
ssl_options = #{log_level := LogLevel}} = State0,
Epoch) ->
- PMTUEstimate = 1400, %% TODO make configurable
#{current_write := #{max_fragment_length := MaxFragmentLength}} = ConnectionStates0,
- MaxSize = min(MaxFragmentLength, PMTUEstimate),
+ MaxSize = min(MaxFragmentLength, ?PMTUEstimate),
{HsBefore, ConnectionStates1} =
encode_handshake_flight(lists:reverse(Flight0), Version, MaxSize, Epoch, ConnectionStates0),
{EncChangeCipher, ConnectionStates} = encode_change_cipher(ChangeCipher, Version, Epoch, ConnectionStates1),
-
- send(Transport, Socket, [HsBefore, EncChangeCipher]),
+ send_packets(Transport, Socket, HsBefore ++ EncChangeCipher),
ssl_logger:debug(LogLevel, outbound, 'record', [HsBefore]),
ssl_logger:debug(LogLevel, outbound, 'record', [EncChangeCipher]),
{State0#state{connection_states = ConnectionStates}, []};
@@ -285,16 +288,15 @@ send_handshake_flight(#state{static_env = #static_env{socket = Socket,
connection_states = ConnectionStates0,
ssl_options = #{log_level := LogLevel}} = State0,
Epoch) ->
- PMTUEstimate = 1400, %% TODO make configurable
#{current_write := #{max_fragment_length := MaxFragmentLength}} = ConnectionStates0,
- MaxSize = min(MaxFragmentLength, PMTUEstimate),
+ MaxSize = min(MaxFragmentLength, ?PMTUEstimate),
{HsBefore, ConnectionStates1} =
encode_handshake_flight(lists:reverse(Flight0), Version, MaxSize, Epoch-1, ConnectionStates0),
{EncChangeCipher, ConnectionStates2} =
encode_change_cipher(ChangeCipher, Version, Epoch-1, ConnectionStates1),
{HsAfter, ConnectionStates} =
encode_handshake_flight(lists:reverse(Flight1), Version, MaxSize, Epoch, ConnectionStates2),
- send(Transport, Socket, [HsBefore, EncChangeCipher, HsAfter]),
+ send_packets(Transport, Socket, HsBefore ++ EncChangeCipher ++ HsAfter),
ssl_logger:debug(LogLevel, outbound, 'record', [HsBefore]),
ssl_logger:debug(LogLevel, outbound, 'record', [EncChangeCipher]),
ssl_logger:debug(LogLevel, outbound, 'record', [HsAfter]),
@@ -309,14 +311,13 @@ send_handshake_flight(#state{static_env = #static_env{socket = Socket,
connection_states = ConnectionStates0,
ssl_options = #{log_level := LogLevel}} = State0,
Epoch) ->
- PMTUEstimate = 1400, %% TODO make configurable
#{current_write := #{max_fragment_length := MaxFragmentLength}} = ConnectionStates0,
- MaxSize = min(MaxFragmentLength, PMTUEstimate),
+ MaxSize = min(MaxFragmentLength, ?PMTUEstimate),
{EncChangeCipher, ConnectionStates1} =
encode_change_cipher(ChangeCipher, Version, Epoch-1, ConnectionStates0),
{HsAfter, ConnectionStates} =
encode_handshake_flight(lists:reverse(Flight1), Version, MaxSize, Epoch, ConnectionStates1),
- send(Transport, Socket, [EncChangeCipher, HsAfter]),
+ send_packets(Transport, Socket, EncChangeCipher ++ HsAfter),
ssl_logger:debug(LogLevel, outbound, 'record', [EncChangeCipher]),
ssl_logger:debug(LogLevel, outbound, 'record', [HsAfter]),
{State0#state{connection_states = ConnectionStates}, []}.
@@ -332,9 +333,8 @@ handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, Stat
ssl_gen_statem:hibernate_after(StateName, State, Actions)
end;
%%% DTLS record protocol level handshake messages
-handle_protocol_record(#ssl_tls{type = ?HANDSHAKE,
- fragment = Data},
- StateName,
+handle_protocol_record(#ssl_tls{type = ?HANDSHAKE, epoch = Epoch, fragment = Data},
+ StateName,
#state{protocol_buffers = Buffers0,
connection_env = #connection_env{negotiated_version = Version},
ssl_options = Options} = State) ->
@@ -344,27 +344,31 @@ handle_protocol_record(#ssl_tls{type = ?HANDSHAKE,
next_event(StateName, no_record, State#state{protocol_buffers = Buffers});
{Packets, Buffers} ->
HsEnv = State#state.handshake_env,
- Events = dtls_handshake_events(Packets),
- {next_state, StateName,
+ HSEvents = dtls_handshake_events(Packets),
+ Events = case is_new_connection(Epoch, Packets, State) of
+ true -> [{next_event, internal, new_connection} | HSEvents];
+ false -> HSEvents
+ end,
+ {next_state, StateName,
State#state{protocol_buffers = Buffers,
- handshake_env =
- HsEnv#handshake_env{unprocessed_handshake_events
- = unprocessed_events(Events)}}, Events}
+ handshake_env =
+ HsEnv#handshake_env{
+ unprocessed_handshake_events = unprocessed_events(HSEvents)}
+ }, Events}
end
catch throw:#alert{} = Alert ->
- handle_own_alert(Alert, Version, StateName, State)
+ handle_own_alert(Alert, StateName, State)
end;
%%% DTLS record protocol level change cipher messages
handle_protocol_record(#ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = Data}, StateName, State) ->
{next_state, StateName, State, [{next_event, internal, #change_cipher_spec{type = Data}}]};
%%% DTLS record protocol level Alert messages
-handle_protocol_record(#ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName,
- #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
+handle_protocol_record(#ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName, State) ->
case decode_alerts(EncAlerts) of
Alerts = [_|_] ->
handle_alerts(Alerts, {next_state, StateName, State});
#alert{} = Alert ->
- handle_own_alert(Alert, Version, StateName, State)
+ handle_own_alert(Alert, StateName, State)
end;
%% Ignore unknown TLS record level protocol messages
handle_protocol_record(#ssl_tls{type = _Unknown}, StateName, State) ->
@@ -478,6 +482,28 @@ send(Transport, {Listener, Socket}, Data) when is_pid(Listener) ->
send(Transport, Socket, Data) -> % Client socket
dtls_socket:send(Transport, Socket, Data).
+send_packets(_Transport, _Socket, []) ->
+ ok;
+send_packets(Transport, Socket, Packets) ->
+ {Packet, Rest} = pack_packets(Packets, 0, ?PMTUEstimate+80, []),
+ case send(Transport, Socket, Packet) of
+ ok -> send_packets(Transport, Socket, Rest);
+ Err -> Err
+ end.
+
+pack_packets([P|Rest]=Packets, SoFar, Max, Acc) ->
+ Size = erlang:iolist_size(P),
+ Next = SoFar + Size,
+ if Size > Max, Acc =:= [] ->
+ {P, Rest};
+ Next < Max ->
+ pack_packets(Rest, Next, Max, [P|Acc]);
+ true ->
+ {lists:reverse(Acc), Packets}
+ end;
+pack_packets([], _, _, Acc) ->
+ {lists:reverse(Acc), []}.
+
socket(Pid, Transport, Socket, _Tracker) ->
dtls_socket:socket(Pid, Transport, Socket, ?MODULE).
@@ -489,14 +515,12 @@ getopts(Transport, Socket, Tag) ->
%% raw data from socket, unpack records
handle_info({Protocol, _, _, _, Data}, StateName,
- #state{static_env = #static_env{role = Role,
- data_tag = Protocol}} = State0) ->
+ #state{static_env = #static_env{data_tag = Protocol}} = State0) ->
case next_dtls_record(Data, StateName, State0) of
{Record, State} ->
next_event(StateName, Record, State);
#alert{} = Alert ->
- ssl_gen_statem:handle_normal_shutdown(Alert#alert{role = Role}, StateName, State0),
- {stop, {shutdown, own_alert}, State0}
+ handle_own_alert(Alert, StateName, State0)
end;
handle_info({PassiveTag, Socket}, StateName,
@@ -555,6 +579,15 @@ handle_info(Msg, StateName, State) ->
%% Internal functions
%%====================================================================
+is_new_connection(0, [{#client_hello{},_Raw}|_],
+ #state{
+ connection_states =
+ #{current_read := #{epoch := CurrentEpoch}}})
+ when CurrentEpoch > 0 ->
+ true;
+is_new_connection(_, _, _) ->
+ false.
+
dtls_handshake_events(Packets) ->
lists:map(fun(Packet) ->
{next_event, internal, {handshake, Packet}}
@@ -569,10 +602,15 @@ unprocessed_events(Events) ->
erlang:length(Events)-1.
encode_handshake_flight(Flight, Version, MaxFragmentSize, Epoch, ConnectionStates) ->
- Fragments = lists:map(fun(Handshake) ->
- dtls_handshake:fragment_handshake(Handshake, MaxFragmentSize)
- end, Flight),
- dtls_record:encode_handshake(Fragments, Version, Epoch, ConnectionStates).
+ Encode = fun(Fragment, {Acc, Cs0}) ->
+ {Enc, Cs} = dtls_record:encode_handshake(Fragment, Version, Epoch, Cs0),
+ {[Enc|Acc], Cs}
+ end,
+ {Rev, Cs} = lists:foldl(fun(Handshake, {Acc,Cs0}) ->
+ Frags = dtls_handshake:fragment_handshake(Handshake, MaxFragmentSize),
+ lists:foldl(Encode, {Acc,Cs0}, Frags)
+ end, {[], ConnectionStates}, Flight),
+ {lists:reverse(Rev), Cs}.
encode_change_cipher(#change_cipher_spec{}, Version, Epoch, ConnectionStates) ->
dtls_record:encode_change_cipher_spec(Version, Epoch, ConnectionStates).
@@ -621,12 +659,28 @@ handle_alerts([], Result) ->
Result;
handle_alerts(_, {stop, _, _} = Stop) ->
Stop;
-handle_alerts([Alert | Alerts], {next_state, StateName, State}) ->
- handle_alerts(Alerts, ssl_gen_statem:handle_alert(Alert, StateName, State));
-handle_alerts([Alert | Alerts], {next_state, StateName, State, _Actions}) ->
- handle_alerts(Alerts, ssl_gen_statem:handle_alert(Alert, StateName, State)).
+handle_alerts(Alerts, {next_state, StateName, State}) ->
+ handle_alerts_or_reset(Alerts, StateName, State);
+handle_alerts(Alerts, {next_state, StateName, State, _Actions}) ->
+ handle_alerts_or_reset(Alerts, StateName, State).
+
+handle_alerts_or_reset([Alert|Alerts], StateName, #state{connection_states = Cs} = State) ->
+ case maps:get(previous_cs, Cs, undefined) of
+ undefined ->
+ handle_alerts(Alerts, ssl_gen_statem:handle_alert(Alert, StateName, State));
+ PreviousConn ->
+ %% There exists an old connection and the new one sent alerts,
+ %% reset to the old working one.
+ HsEnv0 = State#state.handshake_env,
+ HsEnv = HsEnv0#handshake_env{renegotiation = undefined},
+ NewState = State#state{connection_states = PreviousConn,
+ handshake_env = HsEnv
+ },
+ {next_state, connection, NewState}
+ end.
+
-handle_own_alert(Alert, Version, StateName,
+handle_own_alert(Alert, StateName,
#state{static_env = #static_env{data_tag = udp,
role = Role},
ssl_options = #{log_level := LogLevel}} = State0) ->
@@ -635,10 +689,11 @@ handle_own_alert(Alert, Version, StateName,
log_ignore_alert(LogLevel, StateName, Alert, Role),
{next_state, StateName, State};
{false, State} ->
- ssl_gen_statem:handle_own_alert(Alert, Version, StateName, State)
+ dtls_connection:alert_or_reset_connection(Alert, StateName, State)
end;
-handle_own_alert(Alert, Version, StateName, State) ->
- ssl_gen_statem:handle_own_alert(Alert, Version, StateName, State).
+handle_own_alert(Alert, StateName, State) ->
+ dtls_connection:alert_or_reset_connection(Alert, StateName, State).
+
ignore_alert(#alert{level = ?FATAL}, #state{protocol_specific = #{ignored_alerts := N,
max_ignored_alerts := N}} = State) ->
{false, State};
diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl
index 9999933d90..e46a52fb8c 100644
--- a/lib/ssl/src/dtls_handshake.erl
+++ b/lib/ssl/src/dtls_handshake.erl
@@ -108,7 +108,7 @@ hello(#server_hello{server_version = Version, random = Random,
Compression, HelloExt, SslOpt,
ConnectionStates0, Renegotiation, IsNew);
false ->
- ?ALERT_REC(?FATAL, ?PROTOCOL_VERSION)
+ throw(?ALERT_REC(?FATAL, ?PROTOCOL_VERSION))
end.
hello(#client_hello{client_version = ClientVersion} = Hello,
#{versions := Versions} = SslOpts,
@@ -155,7 +155,7 @@ encode_handshake(Handshake, Version, Seq) ->
%%--------------------------------------------------------------------
-spec get_dtls_handshake(ssl_record:ssl_version(), binary(), #protocol_buffers{}, ssl_options()) ->
- {[dtls_handshake()], #protocol_buffers{}}.
+ {[{dtls_handshake(), binary()}], #protocol_buffers{}}.
%%
%% Description: Given buffered and new data from dtls_record, collects
%% and returns it as a list of handshake messages, also returns
@@ -195,13 +195,13 @@ handle_client_hello(Version,
SslOpts, OwnCert),
case CipherSuite of
no_suite ->
- ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY);
+ throw(?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY));
_ ->
#{key_exchange := KeyExAlg} = ssl_cipher_format:suite_bin_to_map(CipherSuite),
case ssl_handshake:select_hashsign({ClientHashSigns, undefined}, OwnCert, KeyExAlg,
SupportedHashSigns, TLSVersion) of
#alert{} = Alert ->
- Alert;
+ throw(Alert);
HashSign ->
handle_client_hello_extensions(Version, Type, Random, CipherSuites, HelloExt,
SslOpts, Session1, ConnectionStates0,
@@ -209,33 +209,27 @@ handle_client_hello(Version,
end
end;
false ->
- ?ALERT_REC(?FATAL, ?PROTOCOL_VERSION)
+ throw(?ALERT_REC(?FATAL, ?PROTOCOL_VERSION))
end.
handle_client_hello_extensions(Version, Type, Random, CipherSuites,
HelloExt, SslOpts, Session0, ConnectionStates0, Renegotiation, HashSign) ->
- try ssl_handshake:handle_client_hello_extensions(dtls_record, Random, CipherSuites,
- HelloExt, dtls_v1:corresponding_tls_version(Version),
- SslOpts, Session0,
+ {Session, ConnectionStates, Protocol, ServerHelloExt} =
+ ssl_handshake:handle_client_hello_extensions(dtls_record, Random, CipherSuites,
+ HelloExt, dtls_v1:corresponding_tls_version(Version),
+ SslOpts, Session0,
ConnectionStates0, Renegotiation,
- Session0#session.is_resumable) of
- {Session, ConnectionStates, Protocol, ServerHelloExt} ->
- {Version, {Type, Session}, ConnectionStates, Protocol, ServerHelloExt, HashSign}
- catch throw:Alert ->
- Alert
- end.
+ Session0#session.is_resumable),
+ {Version, {Type, Session}, ConnectionStates, Protocol, ServerHelloExt, HashSign}.
handle_server_hello_extensions(Version, SessionId, Random, CipherSuite,
Compression, HelloExt, SslOpt, ConnectionStates0, Renegotiation, IsNew) ->
- try ssl_handshake:handle_server_hello_extensions(dtls_record, Random, CipherSuite,
+ {ConnectionStates, ProtoExt, Protocol, OcspState} =
+ ssl_handshake:handle_server_hello_extensions(dtls_record, Random, CipherSuite,
Compression, HelloExt,
dtls_v1:corresponding_tls_version(Version),
- SslOpt, ConnectionStates0, Renegotiation, IsNew) of
- {ConnectionStates, ProtoExt, Protocol, OcspState} ->
- {Version, SessionId, ConnectionStates, ProtoExt, Protocol, OcspState}
- catch throw:Alert ->
- Alert
- end.
+ SslOpt, ConnectionStates0, Renegotiation, IsNew),
+ {Version, SessionId, ConnectionStates, ProtoExt, Protocol, OcspState}.
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/dtls_listener_sup.erl b/lib/ssl/src/dtls_listener_sup.erl
index 4f46407290..699f27b95f 100644
--- a/lib/ssl/src/dtls_listener_sup.erl
+++ b/lib/ssl/src/dtls_listener_sup.erl
@@ -76,18 +76,17 @@ register_listener(OwnerAndListner, IP, Port) ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
-init(_O) ->
- ets:new(dtls_listener_sup, [named_table, public, set]),
- RestartStrategy = simple_one_for_one,
- MaxR = 0,
- MaxT = 3600,
-
- Name = undefined, % As simple_one_for_one is used.
- StartFunc = {dtls_packet_demux, start_link, []},
- Restart = temporary, % E.g. should not be restarted
- Shutdown = 4000,
- Modules = [dtls_packet_demux],
- Type = worker,
-
- ChildSpec = {Name, StartFunc, Restart, Shutdown, Type, Modules},
- {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}.
+init(_) ->
+ ets:new(dtls_listener_sup, [named_table, public, set]),
+ SupFlags = #{strategy => simple_one_for_one,
+ intensity => 0,
+ period => 3600
+ },
+ ChildSpecs = [#{id => undefined,
+ start => {dtls_packet_demux, start_link, []},
+ restart => temporary,
+ shutdown => 4000,
+ modules => [dtls_packet_demux],
+ type => worker
+ }],
+ {ok, {SupFlags, ChildSpecs}}.
diff --git a/lib/ssl/src/dtls_record.erl b/lib/ssl/src/dtls_record.erl
index ef275fad4c..e3c9b829c4 100644
--- a/lib/ssl/src/dtls_record.erl
+++ b/lib/ssl/src/dtls_record.erl
@@ -75,6 +75,9 @@ init_connection_states(Role, BeastMitigation) ->
ConnectionEnd = ssl_record:record_protocol_role(Role),
Initial = initial_connection_state(ConnectionEnd, BeastMitigation),
Current = Initial#{epoch := 0},
+ %% No need to pass Version to ssl_record:empty_connection_state since
+ %% random nonce is generated with same algorithm for DTLS version
+ %% Might require a change for DTLS-1.3
InitialPending = ssl_record:empty_connection_state(ConnectionEnd, BeastMitigation),
Pending = empty_connection_state(InitialPending),
#{saved_read => Current,
@@ -204,16 +207,17 @@ encode_alert_record(#alert{level = Level, description = Description},
%%--------------------------------------------------------------------
-spec encode_change_cipher_spec(ssl_record:ssl_version(), integer(), ssl_record:connection_states()) ->
- {iolist(), ssl_record:connection_states()}.
+ {[iolist()], ssl_record:connection_states()}.
%%
%% Description: Encodes a change_cipher_spec-message to send on the ssl socket.
%%--------------------------------------------------------------------
encode_change_cipher_spec(Version, Epoch, ConnectionStates) ->
- encode_plain_text(?CHANGE_CIPHER_SPEC, Version, Epoch, ?byte(?CHANGE_CIPHER_SPEC_PROTO), ConnectionStates).
+ {Enc, Cs} = encode_plain_text(?CHANGE_CIPHER_SPEC, Version, Epoch, ?byte(?CHANGE_CIPHER_SPEC_PROTO), ConnectionStates),
+ {[Enc], Cs}.
%%--------------------------------------------------------------------
-spec encode_data(binary(), ssl_record:ssl_version(), ssl_record:connection_states()) ->
- {iolist(),ssl_record:connection_states()}.
+ {[iolist()],ssl_record:connection_states()}.
%%
%% Description: Encodes data to send on the ssl-socket.
%%--------------------------------------------------------------------
@@ -236,7 +240,8 @@ encode_data(Data, Version, ConnectionStates) ->
end, {[], ConnectionStates}, Frags),
{lists:reverse(RevCipherText), ConnectionStates1};
_ ->
- encode_plain_text(?APPLICATION_DATA, Version, Epoch, Data, ConnectionStates)
+ {Enc, Cs} = encode_plain_text(?APPLICATION_DATA, Version, Epoch, Data, ConnectionStates),
+ {[Enc], Cs}
end.
encode_plain_text(Type, Version, Epoch, Data, ConnectionStates) ->
@@ -455,7 +460,8 @@ get_dtls_records_aux({_, _, Version, _} = Vinfo, <<?BYTE(Type),?BYTE(MajVer),?BY
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
end;
get_dtls_records_aux(_, <<?BYTE(_), ?BYTE(_MajVer), ?BYTE(_MinVer),
- ?UINT16(Length), _/binary>>,
+ ?UINT16(_Epoch), ?UINT48(_Seq),
+ ?UINT16(Length), _/binary>>,
_Acc, _) when Length > ?MAX_CIPHER_TEXT_LENGTH ->
?ALERT_REC(?FATAL, ?RECORD_OVERFLOW);
diff --git a/lib/ssl/src/dtls_server_session_cache_sup.erl b/lib/ssl/src/dtls_server_session_cache_sup.erl
index 65fbb34918..c0242ab2c0 100644
--- a/lib/ssl/src/dtls_server_session_cache_sup.erl
+++ b/lib/ssl/src/dtls_server_session_cache_sup.erl
@@ -47,17 +47,16 @@ start_child(Listener) ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
-init(_O) ->
- RestartStrategy = simple_one_for_one,
- MaxR = 0,
- MaxT = 3600,
-
- Name = undefined, % As simple_one_for_one is used.
- StartFunc = {ssl_server_session_cache, start_link, []},
- Restart = temporary, % E.g. should not be restarted
- Shutdown = 4000,
- Modules = [ssl_server_session_cache],
- Type = worker,
-
- ChildSpec = {Name, StartFunc, Restart, Shutdown, Type, Modules},
- {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}.
+init(_) ->
+ SupFlags = #{strategy => simple_one_for_one,
+ intensity => 0,
+ period => 3600
+ },
+ ChildSpecs = [#{id => undefined,
+ start => {ssl_server_session_cache, start_link, []},
+ restart => temporary,
+ shutdown => 4000,
+ modules => [ssl_server_session_cache],
+ type => worker
+ }],
+ {ok, {SupFlags, ChildSpecs}}.
diff --git a/lib/ssl/src/dtls_server_sup.erl b/lib/ssl/src/dtls_server_sup.erl
index 7ec6db3984..1430627cf2 100644
--- a/lib/ssl/src/dtls_server_sup.erl
+++ b/lib/ssl/src/dtls_server_sup.erl
@@ -43,33 +43,34 @@ start_link() ->
%%% Supervisor callback
%%%=========================================================================
-init([]) ->
- DTLSListeners = dtls_listeners_spec(),
- %% Add SessionTracker if we add DTLS-1.3
- Pre_1_3SessionTracker = ssl_server_session_child_spec(),
-
- {ok, {{one_for_all, 10, 3600}, [DTLSListeners,
- Pre_1_3SessionTracker
- ]}}.
-
+init([]) ->
+ SupFlags = #{strategy => one_for_all,
+ intensity => 10,
+ period => 3600
+ },
+ ChildSpecs = [dtls_listeners_spec(),
+ ssl_server_session_child_spec()
+ %% TODO Add DTLS-1.3 session ticket handling
+ ],
+ {ok, {SupFlags, ChildSpecs}}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
dtls_listeners_spec() ->
- Name = dtls_listener,
- StartFunc = {dtls_listener_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => dtls_listener_sup,
+ start => {dtls_listener_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [dtls_listener_sup],
+ type => supervisor
+ }.
ssl_server_session_child_spec() ->
- Name = dtls_server_session_cache_sup,
- StartFunc = {dtls_server_session_cache_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [dtls_server_session_cache_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => dtls_server_session_cache_sup,
+ start => {dtls_server_session_cache_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [dtls_server_session_cache_sup],
+ type => supervisor
+ }.
diff --git a/lib/ssl/src/dtls_sup.erl b/lib/ssl/src/dtls_sup.erl
index acc4415a9f..2b73f13e19 100644
--- a/lib/ssl/src/dtls_sup.erl
+++ b/lib/ssl/src/dtls_sup.erl
@@ -44,33 +44,30 @@ start_link() ->
%%%=========================================================================
init([]) ->
- DTLSConnectionManager = dtls_connection_manager_child_spec(),
- DTLSServers = dtls_server_spec(),
-
- {ok, {{one_for_one, 10, 3600}, [DTLSConnectionManager,
- DTLSServers
- ]}}.
+ SupFlags = #{strategy => one_for_one,
+ intensity => 10,
+ period => 3600
+ },
+ Children = [dtls_connection_child_spec(), server_instance_child_spec()],
+ {ok, {SupFlags, Children}}.
-
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-dtls_server_spec() ->
- Name = dtls_servers,
- StartFunc = {dtls_server_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [dtls_server_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
-dtls_connection_manager_child_spec() ->
- Name = dtls_connection,
- StartFunc = {dtls_connection_sup, start_link, []},
- Restart = permanent,
-
- Shutdown = 4000,
- Modules = [dtls_connection_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+dtls_connection_child_spec() ->
+ #{id => dtls_connection_sup,
+ start => {dtls_connection_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [dtls_connection_sup],
+ type => supervisor
+ }.
+server_instance_child_spec() ->
+ #{id => dtls_server_sup,
+ start => {dtls_server_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [dtls_server_sup],
+ type => supervisor
+ }.
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
index 5cfbeff387..cddc4f90bf 100644
--- a/lib/ssl/src/inet_tls_dist.erl
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -53,15 +53,7 @@ select(Node) ->
gen_select(inet_tcp, Node).
gen_select(Driver, Node) ->
- case dist_util:split_node(Node) of
- {node,_,Host} ->
- case Driver:getaddr(Host) of
- {ok, _} -> true;
- _ -> false
- end;
- _ ->
- false
- end.
+ inet_tcp_dist:gen_select(Driver, Node).
%% ------------------------------------------------------------
%% Get the address family that this distribution uses
@@ -582,8 +574,8 @@ do_setup_connect(Driver, Kernel, Node, Address, Ip, TcpPort, Version, Type, MyNo
Opts = trace(connect_options(get_ssl_options(client))),
dist_util:reset_timer(Timer),
case ssl:connect(
- Address, TcpPort,
- [binary, {active, false}, {packet, 4},
+ Ip, TcpPort,
+ [binary, {active, false}, {packet, 4}, {server_name_indication, Address},
Driver:family(), {nodelay, true}] ++ Opts,
net_kernel:connecttime()) of
{ok, #sslsocket{pid = [_, DistCtrl| _]} = SslSocket} ->
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index d761520856..a43a84f26d 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -18,6 +18,7 @@
tls_server_session_ticket_sup,
tls_server_session_ticket,
tls_sup,
+ tls_dyn_connection_sup,
ssl_dh_groups,
%% DTLS
dtls_connection,
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 672cd6ef14..b1ea481fc7 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -1526,14 +1526,15 @@ handle_options(Transport, Socket, Opts0, Role, Host) ->
%% Ensure all options are evaluated at startup
SslOpts1 = add_missing_options(SslOpts0, ?RULES),
- SslOpts = #{protocol := Protocol}
+ SslOpts2 = #{protocol := Protocol}
= process_options(SslOpts1,
#{},
#{role => Role,
host => Host,
rules => ?RULES}),
- maybe_client_warn_no_verify(SslOpts, Role),
+ maybe_client_warn_no_verify(SslOpts2, Role),
+ SslOpts = maps:without([warn_verify_none], SslOpts2),
%% Handle special options
{Sock, Emulated} = emulated_options(Transport, Socket, Protocol, SockOpts0),
ConnetionCb = connection_cb(Protocol),
@@ -1862,7 +1863,7 @@ handle_option(user_lookup_fun = Option, Value0,
Value = validate_option(Option, Value0),
OptionsMap#{Option => Value};
handle_option(verify = Option, unbound, OptionsMap, #{rules := Rules}) ->
- handle_verify_option(default_value(Option, Rules), OptionsMap);
+ handle_verify_option(default_value(Option, Rules), OptionsMap#{warn_verify_none => true});
handle_option(verify = _Option, Value, OptionsMap, _Env) ->
handle_verify_option(Value, OptionsMap);
handle_option(verify_fun = Option, unbound, #{verify := Verify} = OptionsMap, #{rules := Rules})
@@ -2830,9 +2831,11 @@ add_filter(undefined, Filters) ->
add_filter(Filter, Filters) ->
[Filter | Filters].
-maybe_client_warn_no_verify(#{verify := verify_none, log_level := LogLevel}, client) ->
- ssl_logger:log(warning, LogLevel, #{description => "Authenticity is not established by certificate path validation",
- reason => "Option {verify, verify_peer} and cacertfile/cacerts is missing"}, #{});
+maybe_client_warn_no_verify(#{verify := verify_none,
+ warn_verify_none := true,
+ log_level := LogLevel}, client) ->
+ ssl_logger:log(warning, LogLevel, #{description => "Authenticity is not established by certificate path validation",
+ reason => "Option {verify, verify_peer} and cacertfile/cacerts is missing"}, #{});
maybe_client_warn_no_verify(_,_) ->
- %% Client certificate validation is optional in TLS
+ %% Warning not needed. Note client certificate validation is optional in TLS
ok.
diff --git a/lib/ssl/src/ssl_admin_sup.erl b/lib/ssl/src/ssl_admin_sup.erl
index 0cf2ab6332..9c10bf7b41 100644
--- a/lib/ssl/src/ssl_admin_sup.erl
+++ b/lib/ssl/src/ssl_admin_sup.erl
@@ -43,11 +43,15 @@ start_link() ->
%%% Supervisor callback
%%%=========================================================================
-init([]) ->
- PEMCache = pem_cache_child_spec(),
- SessionCertManager = session_and_cert_manager_child_spec(),
- TicketStore = ticket_store_spec(),
- {ok, {{rest_for_one, 10, 3600}, [PEMCache, SessionCertManager, TicketStore]}}.
+init([]) ->
+ SupFlags = #{strategy => rest_for_one,
+ intensity => 10,
+ period => 3600
+ },
+ ChildSpecs = [pem_cache_child_spec(),
+ session_and_cert_manager_child_spec(),
+ ticket_store_spec()],
+ {ok, {SupFlags, ChildSpecs}}.
manager_opts() ->
CbOpts = case application:get_env(ssl, session_cb) of
@@ -69,34 +73,33 @@ manager_opts() ->
%%--------------------------------------------------------------------
pem_cache_child_spec() ->
- Name = ssl_pem_cache,
- StartFunc = {ssl_pem_cache, start_link, [[]]},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [ssl_pem_cache],
- Type = worker,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
+ #{id => ssl_pem_cache,
+ start => {ssl_pem_cache, start_link, [[]]},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [ssl_pem_cache],
+ type => worker
+ }.
session_and_cert_manager_child_spec() ->
Opts = manager_opts(),
- Name = ssl_manager,
- StartFunc = {ssl_manager, start_link, [Opts]},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [ssl_manager],
- Type = worker,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => ssl_manager,
+ start => {ssl_manager, start_link, [Opts]},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [ssl_manager],
+ type => worker
+ }.
ticket_store_spec() ->
- Name = tls_client_ticket_store,
Size = client_session_ticket_store_size(),
Lifetime = client_session_ticket_lifetime(),
- StartFunc = {tls_client_ticket_store, start_link, [Size,Lifetime]},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [tls_client_ticket_store],
- Type = worker,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => tls_client_ticket_store,
+ start => {tls_client_ticket_store, start_link, [Size, Lifetime]},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [tls_client_ticket_store],
+ type => worker
+ }.
session_cb_init_args() ->
case application:get_env(ssl, session_cb_init_args) of
diff --git a/lib/ssl/src/ssl_alert.hrl b/lib/ssl/src/ssl_alert.hrl
index eb3e3ec837..420b014aae 100644
--- a/lib/ssl/src/ssl_alert.hrl
+++ b/lib/ssl/src/ssl_alert.hrl
@@ -26,6 +26,7 @@
-ifndef(ssl_alert).
-define(ssl_alert, true).
+%%-define(ssl_debug, true).
-include_lib("kernel/include/logger.hrl").
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -114,8 +115,14 @@
-define(CERTIFICATE_REQUIRED, 116).
-define(NO_APPLICATION_PROTOCOL, 120).
--define(ALERT_REC(Level,Desc), #alert{level=Level,description=Desc,where= ?LOCATION}).
--define(ALERT_REC(Level,Desc,Reason), #alert{level=Level,description=Desc,where=?LOCATION,reason=Reason}).
+-ifdef(ssl_debug).
+-define(ST_LOCATION, fun(Map) -> Map#{st => process_info(self(), current_stacktrace)} end (?LOCATION)).
+-else.
+-define(ST_LOCATION, ?LOCATION).
+-endif.
+
+-define(ALERT_REC(Level,Desc), #alert{level=Level,description=Desc,where= ?ST_LOCATION}).
+-define(ALERT_REC(Level,Desc,Reason), #alert{level=Level,description=Desc,where=?ST_LOCATION,reason=Reason}).
-define(MAX_ALERTS, 10).
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index ebaa9a6bec..375a416b95 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -548,10 +548,10 @@ is_supported_signature_algorithm_1_2(#'OTPCertificate'{signatureAlgorithm =
is_supported_signature_algorithm_1_2(#'OTPCertificate'{signatureAlgorithm = SignAlg}, SignAlgs) ->
Scheme = ssl_cipher:signature_algorithm_to_scheme(SignAlg),
{Hash, Sign, _ } = ssl_cipher:scheme_to_components(Scheme),
- lists:member({pre_1_3_hash(Hash), pre_1_3_sign(Sign)}, SignAlgs).
+ ssl_cipher:is_supported_sign({pre_1_3_hash(Hash), pre_1_3_sign(Sign)}, ssl_cipher:signature_schemes_1_2(SignAlgs)).
is_supported_signature_algorithm_1_3(#'OTPCertificate'{signatureAlgorithm = SignAlg}, SignAlgs) ->
Scheme = ssl_cipher:signature_algorithm_to_scheme(SignAlg),
- lists:member(Scheme, SignAlgs).
+ ssl_cipher:is_supported_sign(Scheme, SignAlgs).
pre_1_3_sign(rsa_pkcs1) ->
rsa;
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 35b2da773b..52d37d9093 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -58,7 +58,9 @@
calc_mac_hash/4,
calc_mac_hash/6,
is_stream_ciphersuite/1,
+ is_supported_sign/2,
signature_scheme/1,
+ signature_schemes_1_2/1,
scheme_to_components/1,
hash_size/1,
effective_key_bits/1,
@@ -564,6 +566,119 @@ hash_size(sha384) ->
hash_size(sha512) ->
64.
+is_supported_sign({Hash, rsa} = SignAlgo, HashSigns) -> %% PRE TLS-1.3
+ lists:member(SignAlgo, HashSigns) orelse
+ lists:member({Hash, rsa_pss_rsae}, HashSigns);
+is_supported_sign(rsa_pkcs1_sha256 = SignAlgo, HashSigns) -> %% TLS-1.3 leagcy
+ lists:member(SignAlgo, HashSigns) orelse
+ lists:member(rsa_pss_rsae_sha256, HashSigns);
+is_supported_sign(rsa_pkcs1_sha384 = SignAlgo, HashSigns) -> %% TLS-1.3 leagcy
+ lists:member(SignAlgo, HashSigns) orelse
+ lists:member(rsa_pss_rsae_sha384, HashSigns);
+is_supported_sign(rsa_pkcs1_sha512 = SignAlgo, HashSigns) -> %% TLS-1.3 leagcy
+ lists:member(SignAlgo, HashSigns) orelse
+ lists:member(rsa_pss_rsae_sha512, HashSigns);
+is_supported_sign(SignAlgo, HashSigns) -> %% PRE TLS-1.3 SignAlgo::tuple() TLS-1.3 SignAlgo::atom()
+ lists:member(SignAlgo, HashSigns).
+
+signature_scheme(rsa_pkcs1_sha256) -> ?RSA_PKCS1_SHA256;
+signature_scheme(rsa_pkcs1_sha384) -> ?RSA_PKCS1_SHA384;
+signature_scheme(rsa_pkcs1_sha512) -> ?RSA_PKCS1_SHA512;
+signature_scheme(ecdsa_secp256r1_sha256) -> ?ECDSA_SECP256R1_SHA256;
+signature_scheme(ecdsa_secp384r1_sha384) -> ?ECDSA_SECP384R1_SHA384;
+signature_scheme(ecdsa_secp521r1_sha512) -> ?ECDSA_SECP521R1_SHA512;
+signature_scheme(rsa_pss_rsae_sha256) -> ?RSA_PSS_RSAE_SHA256;
+signature_scheme(rsa_pss_rsae_sha384) -> ?RSA_PSS_RSAE_SHA384;
+signature_scheme(rsa_pss_rsae_sha512) -> ?RSA_PSS_RSAE_SHA512;
+signature_scheme(eddsa_ed25519) -> ?ED25519;
+signature_scheme(eddsa_ed448) -> ?ED448;
+signature_scheme(rsa_pss_pss_sha256) -> ?RSA_PSS_PSS_SHA256;
+signature_scheme(rsa_pss_pss_sha384) -> ?RSA_PSS_PSS_SHA384;
+signature_scheme(rsa_pss_pss_sha512) -> ?RSA_PSS_PSS_SHA512;
+signature_scheme(rsa_pkcs1_sha1) -> ?RSA_PKCS1_SHA1;
+signature_scheme(ecdsa_sha1) -> ?ECDSA_SHA1;
+%% New algorithms on legacy format
+signature_scheme({sha512, rsa_pss_pss}) ->
+ ?RSA_PSS_PSS_SHA512;
+signature_scheme({sha384, rsa_pss_pss}) ->
+ ?RSA_PSS_PSS_SHA384;
+signature_scheme({sha256, rsa_pss_pss}) ->
+ ?RSA_PSS_PSS_SHA256;
+signature_scheme({sha512, rsa_pss_rsae}) ->
+ ?RSA_PSS_RSAE_SHA512;
+signature_scheme({sha384, rsa_pss_rsae}) ->
+ ?RSA_PSS_RSAE_SHA384;
+signature_scheme({sha256, rsa_pss_rsae}) ->
+ ?RSA_PSS_RSAE_SHA256;
+%% Handling legacy signature algorithms
+signature_scheme({Hash0, Sign0}) ->
+ Hash = hash_algorithm(Hash0),
+ Sign = sign_algorithm(Sign0),
+ <<?UINT16(SigAlg)>> = <<?BYTE(Hash),?BYTE(Sign)>>,
+ SigAlg;
+signature_scheme(?RSA_PKCS1_SHA256) -> rsa_pkcs1_sha256;
+signature_scheme(?RSA_PKCS1_SHA384) -> rsa_pkcs1_sha384;
+signature_scheme(?RSA_PKCS1_SHA512) -> rsa_pkcs1_sha512;
+signature_scheme(?ECDSA_SECP256R1_SHA256) -> ecdsa_secp256r1_sha256;
+signature_scheme(?ECDSA_SECP384R1_SHA384) -> ecdsa_secp384r1_sha384;
+signature_scheme(?ECDSA_SECP521R1_SHA512) -> ecdsa_secp521r1_sha512;
+signature_scheme(?RSA_PSS_RSAE_SHA256) -> rsa_pss_rsae_sha256;
+signature_scheme(?RSA_PSS_RSAE_SHA384) -> rsa_pss_rsae_sha384;
+signature_scheme(?RSA_PSS_RSAE_SHA512) -> rsa_pss_rsae_sha512;
+signature_scheme(?ED25519) -> eddsa_ed25519;
+signature_scheme(?ED448) -> eddsa_ed448;
+signature_scheme(?RSA_PSS_PSS_SHA256) -> rsa_pss_pss_sha256;
+signature_scheme(?RSA_PSS_PSS_SHA384) -> rsa_pss_pss_sha384;
+signature_scheme(?RSA_PSS_PSS_SHA512) -> rsa_pss_pss_sha512;
+signature_scheme(?RSA_PKCS1_SHA1) -> rsa_pkcs1_sha1;
+signature_scheme(?ECDSA_SHA1) -> ecdsa_sha1;
+%% Handling legacy signature algorithms for logging purposes. These algorithms
+%% cannot be used in TLS 1.3 handshakes.
+signature_scheme(SignAlgo) when is_integer(SignAlgo) ->
+ <<?BYTE(Hash),?BYTE(Sign)>> = <<?UINT16(SignAlgo)>>,
+ try
+ {ssl_cipher:hash_algorithm(Hash), ssl_cipher:sign_algorithm(Sign)}
+ catch
+ _:_ ->
+ unassigned
+ end;
+signature_scheme(_) -> unassigned.
+
+signature_schemes_1_2(SigAlgs) ->
+ lists:foldl(fun(Alg, Acc) when is_atom(Alg) ->
+ case scheme_to_components(Alg) of
+ {Hash, Sign = rsa_pss_pss,_} ->
+ [{Hash, Sign} | Acc];
+ {Hash, Sign = rsa_pss_rsae,_} ->
+ [{Hash, Sign} | Acc];
+ {_, _, _} ->
+ Acc
+ end;
+ (Alg, Acc) ->
+ [Alg| Acc]
+ end, [], SigAlgs).
+
+%% TODO: reserved code points?
+
+scheme_to_components(rsa_pkcs1_sha256) -> {sha256, rsa_pkcs1, undefined};
+scheme_to_components(rsa_pkcs1_sha384) -> {sha384, rsa_pkcs1, undefined};
+scheme_to_components(rsa_pkcs1_sha512) -> {sha512, rsa_pkcs1, undefined};
+scheme_to_components(ecdsa_secp256r1_sha256) -> {sha256, ecdsa, secp256r1};
+scheme_to_components(ecdsa_secp384r1_sha384) -> {sha384, ecdsa, secp384r1};
+scheme_to_components(ecdsa_secp521r1_sha512) -> {sha512, ecdsa, secp521r1};
+scheme_to_components(rsa_pss_rsae_sha256) -> {sha256, rsa_pss_rsae, undefined};
+scheme_to_components(rsa_pss_rsae_sha384) -> {sha384, rsa_pss_rsae, undefined};
+scheme_to_components(rsa_pss_rsae_sha512) -> {sha512, rsa_pss_rsae, undefined};
+scheme_to_components(eddsa_ed25519) -> {none, eddsa, ed25519};
+scheme_to_components(eddsa_ed448) -> {none, eddsa, ed448};
+scheme_to_components(rsa_pss_pss_sha256) -> {sha256, rsa_pss_pss, undefined};
+scheme_to_components(rsa_pss_pss_sha384) -> {sha384, rsa_pss_pss, undefined};
+scheme_to_components(rsa_pss_pss_sha512) -> {sha512, rsa_pss_pss, undefined};
+scheme_to_components(rsa_pkcs1_sha1) -> {sha1, rsa_pkcs1, undefined};
+scheme_to_components(ecdsa_sha1) -> {sha1, ecdsa, undefined};
+%% Handling legacy signature algorithms
+scheme_to_components({Hash,Sign}) -> {Hash, Sign, undefined}.
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
@@ -752,71 +867,6 @@ sign_algorithm(Other) when is_integer(Other) andalso ((Other >= 4) and (Other =<
sign_algorithm(Other) when is_integer(Other) andalso ((Other >= 224) and (Other =< 255)) -> Other.
-signature_scheme(rsa_pkcs1_sha256) -> ?RSA_PKCS1_SHA256;
-signature_scheme(rsa_pkcs1_sha384) -> ?RSA_PKCS1_SHA384;
-signature_scheme(rsa_pkcs1_sha512) -> ?RSA_PKCS1_SHA512;
-signature_scheme(ecdsa_secp256r1_sha256) -> ?ECDSA_SECP256R1_SHA256;
-signature_scheme(ecdsa_secp384r1_sha384) -> ?ECDSA_SECP384R1_SHA384;
-signature_scheme(ecdsa_secp521r1_sha512) -> ?ECDSA_SECP521R1_SHA512;
-signature_scheme(rsa_pss_rsae_sha256) -> ?RSA_PSS_RSAE_SHA256;
-signature_scheme(rsa_pss_rsae_sha384) -> ?RSA_PSS_RSAE_SHA384;
-signature_scheme(rsa_pss_rsae_sha512) -> ?RSA_PSS_RSAE_SHA512;
-signature_scheme(eddsa_ed25519) -> ?ED25519;
-signature_scheme(eddsa_ed448) -> ?ED448;
-signature_scheme(rsa_pss_pss_sha256) -> ?RSA_PSS_PSS_SHA256;
-signature_scheme(rsa_pss_pss_sha384) -> ?RSA_PSS_PSS_SHA384;
-signature_scheme(rsa_pss_pss_sha512) -> ?RSA_PSS_PSS_SHA512;
-signature_scheme(rsa_pkcs1_sha1) -> ?RSA_PKCS1_SHA1;
-signature_scheme(ecdsa_sha1) -> ?ECDSA_SHA1;
-%% Handling legacy signature algorithms
-signature_scheme({Hash0, Sign0}) ->
- Hash = hash_algorithm(Hash0),
- Sign = sign_algorithm(Sign0),
- <<?UINT16(SigAlg)>> = <<?BYTE(Hash),?BYTE(Sign)>>,
- SigAlg;
-signature_scheme(?RSA_PKCS1_SHA256) -> rsa_pkcs1_sha256;
-signature_scheme(?RSA_PKCS1_SHA384) -> rsa_pkcs1_sha384;
-signature_scheme(?RSA_PKCS1_SHA512) -> rsa_pkcs1_sha512;
-signature_scheme(?ECDSA_SECP256R1_SHA256) -> ecdsa_secp256r1_sha256;
-signature_scheme(?ECDSA_SECP384R1_SHA384) -> ecdsa_secp384r1_sha384;
-signature_scheme(?ECDSA_SECP521R1_SHA512) -> ecdsa_secp521r1_sha512;
-signature_scheme(?RSA_PSS_RSAE_SHA256) -> rsa_pss_rsae_sha256;
-signature_scheme(?RSA_PSS_RSAE_SHA384) -> rsa_pss_rsae_sha384;
-signature_scheme(?RSA_PSS_RSAE_SHA512) -> rsa_pss_rsae_sha512;
-signature_scheme(?ED25519) -> eddsa_ed25519;
-signature_scheme(?ED448) -> eddsa_ed448;
-signature_scheme(?RSA_PSS_PSS_SHA256) -> rsa_pss_pss_sha256;
-signature_scheme(?RSA_PSS_PSS_SHA384) -> rsa_pss_pss_sha384;
-signature_scheme(?RSA_PSS_PSS_SHA512) -> rsa_pss_pss_sha512;
-signature_scheme(?RSA_PKCS1_SHA1) -> rsa_pkcs1_sha1;
-signature_scheme(?ECDSA_SHA1) -> ecdsa_sha1;
-%% Handling legacy signature algorithms for logging purposes. These algorithms
-%% cannot be used in TLS 1.3 handshakes.
-signature_scheme(SignAlgo) when is_integer(SignAlgo) ->
- <<?BYTE(Hash),?BYTE(Sign)>> = <<?UINT16(SignAlgo)>>,
- {ssl_cipher:hash_algorithm(Hash), ssl_cipher:sign_algorithm(Sign)};
-signature_scheme(_) -> unassigned.
-%% TODO: reserved code points?
-
-scheme_to_components(rsa_pkcs1_sha256) -> {sha256, rsa_pkcs1, undefined};
-scheme_to_components(rsa_pkcs1_sha384) -> {sha384, rsa_pkcs1, undefined};
-scheme_to_components(rsa_pkcs1_sha512) -> {sha512, rsa_pkcs1, undefined};
-scheme_to_components(ecdsa_secp256r1_sha256) -> {sha256, ecdsa, secp256r1};
-scheme_to_components(ecdsa_secp384r1_sha384) -> {sha384, ecdsa, secp384r1};
-scheme_to_components(ecdsa_secp521r1_sha512) -> {sha512, ecdsa, secp521r1};
-scheme_to_components(rsa_pss_rsae_sha256) -> {sha256, rsa_pss_rsae, undefined};
-scheme_to_components(rsa_pss_rsae_sha384) -> {sha384, rsa_pss_rsae, undefined};
-scheme_to_components(rsa_pss_rsae_sha512) -> {sha512, rsa_pss_rsae, undefined};
-scheme_to_components(eddsa_ed25519) -> {none, eddsa, ed25519};
-scheme_to_components(eddsa_ed448) -> {none, eddsa, ed448};
-scheme_to_components(rsa_pss_pss_sha256) -> {sha256, rsa_pss_pss, undefined};
-scheme_to_components(rsa_pss_pss_sha384) -> {sha384, rsa_pss_pss, undefined};
-scheme_to_components(rsa_pss_pss_sha512) -> {sha512, rsa_pss_pss, undefined};
-scheme_to_components(rsa_pkcs1_sha1) -> {sha1, rsa_pkcs1, undefined};
-scheme_to_components(ecdsa_sha1) -> {sha1, ecdsa, undefined};
-%% Handling legacy signature algorithms
-scheme_to_components({Hash,Sign}) -> {Hash, Sign, undefined}.
-
signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-RSASSA-PSS',
parameters = #'RSASSA-PSS-params'{
maskGenAlgorithm =
@@ -842,7 +892,7 @@ signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'ecdsa-with-SHA
signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'ecdsa-with-SHA384'}) ->
ecdsa_secp384r1_sha384;
signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'ecdsa-with-SHA512'}) ->
- ecdsa_secp512r1_sha512;
+ ecdsa_secp521r1_sha512;
signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'sha-1WithRSAEncryption'}) ->
rsa_pkcs1_sha1;
signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?sha1WithRSAEncryption}) ->
diff --git a/lib/ssl/src/ssl_connection_sup.erl b/lib/ssl/src/ssl_connection_sup.erl
index d930ecf2fa..f5d170934c 100644
--- a/lib/ssl/src/ssl_connection_sup.erl
+++ b/lib/ssl/src/ssl_connection_sup.erl
@@ -44,32 +44,33 @@ start_link() ->
%%%=========================================================================
init([]) ->
-
- TLSSup = tls_sup_child_spec(),
- DTLSSup = dtls_sup_child_spec(),
-
- {ok, {{one_for_one, 10, 3600}, [TLSSup, DTLSSup]}}.
+ ChildSpecs = [tls_sup_child_spec(), dtls_sup_child_spec()],
+ SupFlags = #{strategy => one_for_one,
+ intensity => 10,
+ period => 3600
+ },
+ {ok, {SupFlags, ChildSpecs}}.
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
tls_sup_child_spec() ->
- Name = tls_sup,
- StartFunc = {tls_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [tls_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => tls_sup,
+ start => {tls_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [tls_sup],
+ type => supervisor
+ }.
dtls_sup_child_spec() ->
- Name = dtls_sup,
- StartFunc = {dtls_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [dtls_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
+ #{id => dtls_sup,
+ start => {dtls_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [dtls_sup],
+ type => supervisor
+ }.
diff --git a/lib/ssl/src/ssl_crl.erl b/lib/ssl/src/ssl_crl.erl
index d3b66df870..be44693b86 100644
--- a/lib/ssl/src/ssl_crl.erl
+++ b/lib/ssl/src/ssl_crl.erl
@@ -44,8 +44,8 @@ trusted_cert_and_path(CRL, issuer_not_found, CertPath, {Db, DbRef}) ->
{error, unknown_ca} ->
Issuer = public_key:pkix_normalize_name(public_key:pkix_crl_issuer(CRL)),
IsIssuerFun =
- fun({_Key, #cert{otp=ErlCertCandidate}}, Acc) ->
- verify_crl_issuer(CRL, ErlCertCandidate, Issuer, Acc);
+ fun({_Key, CertCandidate}, Acc) ->
+ verify_crl_issuer(CRL, CertCandidate, Issuer, Acc);
(_, Acc) ->
Acc
end,
@@ -63,8 +63,8 @@ trusted_cert_and_path(CRL, issuer_not_found, CertPath, {Db, DbRef}) ->
search_certpath(CRL, CertPath, Db, DbRef) ->
Issuer = public_key:pkix_normalize_name(public_key:pkix_crl_issuer(CRL)),
IsIssuerFun =
- fun(ErlCertCandidate, Acc) ->
- verify_crl_issuer(CRL, ErlCertCandidate, Issuer, Acc)
+ fun(CertCandidate, Acc) ->
+ verify_crl_issuer(CRL, CertCandidate, Issuer, Acc)
end,
case find_issuer(IsIssuerFun, certpath, CertPath) of
{ok, OtpCert} ->
@@ -105,13 +105,13 @@ find_issuer(IsIssuerFun, Db, _) ->
Result
end.
-verify_crl_issuer(CRL, #cert{otp = ErlCertCandidate}, Issuer, NotIssuer) ->
- TBSCert = ErlCertCandidate#'OTPCertificate'.tbsCertificate,
+verify_crl_issuer(CRL, #cert{otp = OTPCertCandidate}, Issuer, NotIssuer) ->
+ TBSCert = OTPCertCandidate#'OTPCertificate'.tbsCertificate,
case public_key:pkix_normalize_name(TBSCert#'OTPTBSCertificate'.subject) of
Issuer ->
- case public_key:pkix_crl_verify(CRL, ErlCertCandidate) of
+ case public_key:pkix_crl_verify(CRL, OTPCertCandidate) of
true ->
- throw({ok, ErlCertCandidate});
+ throw({ok, OTPCertCandidate});
false ->
NotIssuer
end;
diff --git a/lib/ssl/src/ssl_dist_admin_sup.erl b/lib/ssl/src/ssl_dist_admin_sup.erl
index f60806c4cb..3e10643dcd 100644
--- a/lib/ssl/src/ssl_dist_admin_sup.erl
+++ b/lib/ssl/src/ssl_dist_admin_sup.erl
@@ -44,31 +44,31 @@ start_link() ->
%%%=========================================================================
init([]) ->
- PEMCache = pem_cache_child_spec(),
- SessionCertManager = session_and_cert_manager_child_spec(),
- {ok, {{rest_for_one, 10, 3600}, [PEMCache, SessionCertManager]}}.
-
-
+ ChildSpecs = [pem_cache_child_spec(),
+ session_and_cert_manager_child_spec()],
+ SupFlags = #{strategy => rest_for_one,
+ intensity => 10,
+ period => 3600
+ },
+ {ok, {SupFlags, ChildSpecs}}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
pem_cache_child_spec() ->
- Name = ssl_pem_cache_dist,
- StartFunc = {ssl_pem_cache, start_link_dist, [[]]},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [ssl_pem_cache],
- Type = worker,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
+ #{id => ssl_pem_cache_dist,
+ start => {ssl_pem_cache, start_link_dist, [[]]},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [ssl_pem_cache],
+ type => worker
+ }.
session_and_cert_manager_child_spec() ->
Opts = ssl_admin_sup:manager_opts(),
- Name = ssl_dist_manager,
- StartFunc = {ssl_manager, start_link_dist, [Opts]},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [ssl_manager],
- Type = worker,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
+ #{id => ssl_dist_manager,
+ start => {ssl_manager, start_link_dist, [Opts]},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [ssl_manager],
+ type => worker
+ }.
diff --git a/lib/ssl/src/ssl_dist_connection_sup.erl b/lib/ssl/src/ssl_dist_connection_sup.erl
index 441a7577be..47c467b358 100644
--- a/lib/ssl/src/ssl_dist_connection_sup.erl
+++ b/lib/ssl/src/ssl_dist_connection_sup.erl
@@ -43,19 +43,22 @@ start_link() ->
%%% Supervisor callback
%%%=========================================================================
init([]) ->
- TLSSup = tls_sup_child_spec(),
- {ok, {{one_for_one, 10, 3600}, [TLSSup]}}.
+ SupFlags = #{strategy => one_for_one,
+ intensity => 10,
+ period => 3600
+ },
+ ChildSpecs = [tls_sup_child_spec()],
+ {ok, {SupFlags, ChildSpecs}}.
-
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
tls_sup_child_spec() ->
- Name = dist_tls_sup,
- StartFunc = {tls_dist_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [tls_dist_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => tls_dist_sup,
+ start => {tls_dist_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [tls_dist_sup],
+ type => supervisor
+ }.
diff --git a/lib/ssl/src/ssl_dist_sup.erl b/lib/ssl/src/ssl_dist_sup.erl
index ae0887c3d9..74e4775413 100644
--- a/lib/ssl/src/ssl_dist_sup.erl
+++ b/lib/ssl/src/ssl_dist_sup.erl
@@ -58,30 +58,34 @@ start_link() ->
%%%=========================================================================
init([]) ->
- AdminSup = ssl_admin_child_spec(),
- ConnectionSup = ssl_connection_sup(),
- {ok, {{one_for_all, 10, 3600}, [AdminSup, ConnectionSup]}}.
+ SupFlags = #{strategy => one_for_all,
+ intensity => 10,
+ period => 3600
+ },
+ ChildSpecs = [ssl_admin_child_spec(),
+ ssl_connection_sup()],
+ {ok, {SupFlags, ChildSpecs}}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
ssl_admin_child_spec() ->
- Name = ssl_dist_admin_sup,
- StartFunc = {ssl_dist_admin_sup, start_link , []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [ssl_dist_admin_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
+ #{id => ssl_dist_admin_sup,
+ start => {ssl_dist_admin_sup, start_link , []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [ssl_dist_admin_sup],
+ type => supervisor
+ }.
+
ssl_connection_sup() ->
- Name = tls_dist_sup,
- StartFunc = {tls_dist_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [tls_dist_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => tls_dist_sup,
+ start => {tls_dist_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [tls_dist_sup],
+ type => supervisor
+ }.
consult(File) ->
case erl_prim_loader:get_file(File) of
diff --git a/lib/ssl/src/ssl_gen_statem.erl b/lib/ssl/src/ssl_gen_statem.erl
index a68f9e0836..3bbb820ef7 100644
--- a/lib/ssl/src/ssl_gen_statem.erl
+++ b/lib/ssl/src/ssl_gen_statem.erl
@@ -87,7 +87,7 @@
%% Alert and close handling
-export([send_alert/3,
- handle_own_alert/4,
+ handle_own_alert/3,
handle_alert/3,
handle_normal_shutdown/3,
handle_trusted_certs_db/1,
@@ -126,9 +126,8 @@ start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
-spec init(list()) -> no_return().
%% Description: Initialization
%%--------------------------------------------------------------------
-init([_Role, Sender, _Host, _Port, _Socket, {#{erl_dist := ErlDist} = TLSOpts, _, _}, _User, _CbInfo] = InitArgs) ->
+init([_Role, _Sender, _Host, _Port, _Socket, {#{erl_dist := ErlDist} = TLSOpts, _, _}, _User, _CbInfo] = InitArgs) ->
process_flag(trap_exit, true),
- link(Sender),
case ErlDist of
true ->
process_flag(priority, max);
@@ -515,8 +514,7 @@ initial_hello({call, From}, {start, Timeout},
[{{timeout, handshake}, Timeout, close}])
catch
{Ref, #alert{} = Alert} ->
- handle_own_alert(Alert, RequestedVersion, init,
- State0#state{start_or_recv_from = From})
+ handle_own_alert(Alert, init, State0#state{start_or_recv_from = From})
end;
initial_hello({call, From}, {start, Timeout}, #state{static_env = #static_env{role = Role,
protocol_cb = Connection},
@@ -687,7 +685,11 @@ downgrade(info, {CloseTag, Socket},
downgrade(info, Info, State) ->
tls_gen_connection:handle_info(Info, ?FUNCTION_NAME, State);
downgrade(Type, Event, State) ->
- tls_dtls_connection:?FUNCTION_NAME(Type, Event, State).
+ try
+ tls_dtls_connection:?FUNCTION_NAME(Type, Event, State)
+ catch throw:#alert{} = Alert ->
+ handle_own_alert(Alert, ?FUNCTION_NAME, State)
+ end.
%%====================================================================
%% Event/Msg handling
@@ -705,9 +707,8 @@ handle_common_event(internal, {protocol_record, TLSorDTLSRecord}, StateName,
Connection:handle_protocol_record(TLSorDTLSRecord, StateName, State);
handle_common_event(timeout, hibernate, _, _) ->
{keep_state_and_data, [hibernate]};
-handle_common_event(internal, #change_cipher_spec{type = <<1>>}, StateName,
- #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
- handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE), Version, StateName, State);
+handle_common_event(internal, #change_cipher_spec{type = <<1>>}, StateName, State) ->
+ handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE), StateName, State);
handle_common_event({timeout, handshake}, close, _StateName, #state{start_or_recv_from = StartFrom} = State) ->
{stop_and_reply,
{shutdown, user_timeout},
@@ -718,10 +719,11 @@ handle_common_event({timeout, recv}, timeout, StateName, #state{start_or_recv_fr
handle_common_event(internal, {recv, RecvFrom}, StateName, #state{start_or_recv_from = RecvFrom}) when
StateName =/= connection ->
{keep_state_and_data, [postpone]};
-handle_common_event(Type, Msg, StateName, #state{connection_env =
- #connection_env{negotiated_version = Version}} = State) ->
+handle_common_event(internal, new_connection, StateName, State) ->
+ {next_state, StateName, State};
+handle_common_event(Type, Msg, StateName, State) ->
Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, {unexpected_msg, {Type, Msg}}),
- handle_own_alert(Alert, Version, StateName, State).
+ handle_own_alert(Alert, StateName, State).
handle_call({application_data, _Data}, _, _, _) ->
%% In renegotiation priorities handshake, send data when handshake is finished
@@ -939,7 +941,7 @@ send_alert(Alert, connection, #state{static_env = #static_env{protocol_cb = Conn
send_alert(Alert, _, #state{static_env = #static_env{protocol_cb = Connection}} = State) ->
Connection:send_alert(Alert, State).
-handle_own_alert(Alert0, _, StateName,
+handle_own_alert(Alert0, StateName,
#state{static_env = #static_env{role = Role,
protocol_cb = Connection},
ssl_options = #{log_level := LogLevel}} = State) ->
@@ -1188,11 +1190,12 @@ call(FsmPid, Event) ->
{error, closed};
exit:{normal, _} ->
{error, closed};
+ exit:{shutdown,_} ->
+ {error, closed};
exit:{{shutdown, _},_} ->
{error, closed}
end.
-
check_hostname(_, "") ->
?ALERT_REC(?FATAL, ?UNRECOGNIZED_NAME, empty_sni);
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 63fbf5ffff..2d5e29fb61 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -652,8 +652,8 @@ encode_extensions([#srp{username = UserName} | Rest], Acc) ->
encode_extensions(Rest, <<?UINT16(?SRP_EXT), ?UINT16(Len), ?BYTE(SRPLen),
UserName/binary, Acc/binary>>);
encode_extensions([#hash_sign_algos{hash_sign_algos = HashSignAlgos} | Rest], Acc) ->
- SignAlgoList = << <<(ssl_cipher:hash_algorithm(Hash)):8, (ssl_cipher:sign_algorithm(Sign)):8>> ||
- {Hash, Sign} <- HashSignAlgos >>,
+ SignAlgoList = << <<(ssl_cipher:signature_scheme(SignatureScheme)):16 >> ||
+ SignatureScheme <- HashSignAlgos >>,
ListLen = byte_size(SignAlgoList),
Len = ListLen + 2,
encode_extensions(Rest, <<?UINT16(?SIGNATURE_ALGORITHMS_EXT),
@@ -988,17 +988,30 @@ available_signature_algs(undefined, _) ->
available_signature_algs(SupportedHashSigns, Version) when Version >= {3, 3} ->
case contains_scheme(SupportedHashSigns) of
true ->
- #signature_algorithms{signature_scheme_list = SupportedHashSigns};
+ case Version of
+ {3,3} ->
+ #hash_sign_algos{hash_sign_algos = ssl_cipher:signature_schemes_1_2(SupportedHashSigns)};
+ _ ->
+ #signature_algorithms{signature_scheme_list = SupportedHashSigns}
+ end;
false ->
#hash_sign_algos{hash_sign_algos = SupportedHashSigns}
end;
available_signature_algs(_, _) ->
undefined.
+
available_signature_algs(undefined, SupportedHashSigns, _, Version) when
Version >= {3,3} ->
SupportedHashSigns;
-available_signature_algs(#hash_sign_algos{hash_sign_algos = ClientHashSigns}, SupportedHashSigns,
+available_signature_algs(#hash_sign_algos{hash_sign_algos = ClientHashSigns}, SupportedHashSigns0,
_, Version) when Version >= {3,3} ->
+ SupportedHashSigns =
+ case (Version == {3,3}) andalso contains_scheme(SupportedHashSigns0) of
+ true ->
+ ssl_cipher:signature_schemes_1_2(SupportedHashSigns0);
+ false ->
+ SupportedHashSigns0
+ end,
sets:to_list(sets:intersection(sets:from_list(ClientHashSigns),
sets:from_list(SupportedHashSigns)));
available_signature_algs(_, _, _, _) ->
@@ -1880,14 +1893,14 @@ supported_cert_type_or_empty(Algo, Type) ->
end.
certificate_authorities(CertDbHandle, CertDbRef) ->
- Authorities = certificate_authorities_from_db(CertDbHandle, CertDbRef),
+ Authorities = [ Cert || #cert{otp = Cert} <- certificate_authorities_from_db(CertDbHandle, CertDbRef)],
Enc = fun(#'OTPCertificate'{tbsCertificate=TBSCert}) ->
OTPSubj = TBSCert#'OTPTBSCertificate'.subject,
DNEncodedBin = public_key:pkix_encode('Name', OTPSubj, otp),
DNEncodedLen = byte_size(DNEncodedBin),
<<?UINT16(DNEncodedLen), DNEncodedBin/binary>>
end,
- list_to_binary([Enc(Cert) || {_, Cert} <- Authorities]).
+ list_to_binary([Enc(Cert) || Cert <- Authorities]).
certificate_authorities_from_db(CertDbHandle, CertDbRef) when is_reference(CertDbRef) ->
ConnectionCerts = fun({{Ref, _, _}, Cert}, Acc) when Ref == CertDbRef ->
@@ -3278,6 +3291,15 @@ filter_hashsigns([Suite | Suites], [#{key_exchange := KeyExchange} | Algos], Has
%% In this case hashsigns is not used as the kexchange is anonaymous
filter_hashsigns(Suites, Algos, HashSigns, Version, [Suite| Acc]).
+do_filter_hashsigns(rsa = SignAlgo, Suite, Suites, Algos, HashSigns, {3,3} = Version, Acc) ->
+ case (lists:keymember(SignAlgo, 2, HashSigns) orelse
+ lists:keymember(rsa_pss_rsae, 2, HashSigns) orelse
+ lists:keymember(rsa_pss_pss, 2, HashSigns)) of
+ true ->
+ filter_hashsigns(Suites, Algos, HashSigns, Version, [Suite| Acc]);
+ false ->
+ filter_hashsigns(Suites, Algos, HashSigns, Version, Acc)
+ end;
do_filter_hashsigns(SignAlgo, Suite, Suites, Algos, HashSigns, Version, Acc) ->
case lists:keymember(SignAlgo, 2, HashSigns) of
true ->
@@ -3390,8 +3412,7 @@ is_acceptable_cert_type(Sign, Types) ->
%% signature_algorithms_cert = undefined
is_supported_sign(SignAlgo, _, HashSigns, []) ->
- lists:member(SignAlgo, HashSigns);
-
+ ssl_cipher:is_supported_sign(SignAlgo, HashSigns);
%% {'SignatureAlgorithm',{1,2,840,113549,1,1,11},'NULL'}
is_supported_sign({Hash, Sign}, 'NULL', _, SignatureSchemes) ->
Fun = fun (Scheme, Acc) ->
@@ -3408,7 +3429,6 @@ is_supported_sign({Hash, Sign}, 'NULL', _, SignatureSchemes) ->
Hash =:= H1)
end,
lists:foldl(Fun, false, SignatureSchemes);
-
%% TODO: Implement validation for the curve used in the signature
%% RFC 3279 - 2.2.3 ECDSA Signature Algorithm
%% When the ecdsa-with-SHA1 algorithm identifier appears as the
diff --git a/lib/ssl/src/ssl_listen_tracker_sup.erl b/lib/ssl/src/ssl_listen_tracker_sup.erl
index 6afd1c0009..998ec5fbc3 100644
--- a/lib/ssl/src/ssl_listen_tracker_sup.erl
+++ b/lib/ssl/src/ssl_listen_tracker_sup.erl
@@ -51,20 +51,19 @@ start_child_dist(Args) ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
-init(_O) ->
- RestartStrategy = simple_one_for_one,
- MaxR = 0,
- MaxT = 3600,
-
- Name = undefined, % As simple_one_for_one is used.
- StartFunc = {tls_socket, start_link, []},
- Restart = temporary, % E.g. should not be restarted
- Shutdown = 4000,
- Modules = [tls_socket],
- Type = worker,
-
- ChildSpec = {Name, StartFunc, Restart, Shutdown, Type, Modules},
- {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}.
+init(_) ->
+ SupFlags = #{strategy => simple_one_for_one,
+ intensity => 0,
+ period => 3600
+ },
+ ChildSpecs = [#{id => undefined,
+ start => {tls_socket, start_link, []},
+ restart => temporary,
+ shutdown => 4000,
+ modules => [tls_socket],
+ type => worker
+ }],
+ {ok, {SupFlags, ChildSpecs}}.
tracker_name(normal) ->
?MODULE;
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index f1cf503097..86df169408 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -42,7 +42,7 @@
set_server_verify_data/3,
set_max_fragment_length/2,
empty_connection_state/2,
- empty_connection_state/3,
+ empty_connection_state/4,
record_protocol_role/1,
step_encryption_state/1,
step_encryption_state_read/1,
@@ -55,6 +55,7 @@
-export([cipher/4, cipher/5, decipher/4,
cipher_aead/4, cipher_aead/5, decipher_aead/5,
is_correct_mac/2, nonce_seed/3]).
+-define(TLS_1_3, {3, 4}).
-export_type([ssl_version/0, ssl_atom_version/0, connection_states/0, connection_state/0]).
@@ -465,10 +466,12 @@ nonce_seed(_,_, CipherState) ->
empty_connection_state(ConnectionEnd, BeastMitigation) ->
MaxEarlyDataSize = ssl_config:get_max_early_data_size(),
- empty_connection_state(ConnectionEnd, BeastMitigation, MaxEarlyDataSize).
+ empty_connection_state(ConnectionEnd, _Version = undefined,
+ BeastMitigation, MaxEarlyDataSize).
%%
-empty_connection_state(ConnectionEnd, BeastMitigation, MaxEarlyDataSize) ->
- SecParams = empty_security_params(ConnectionEnd),
+empty_connection_state(ConnectionEnd, Version,
+ BeastMitigation, MaxEarlyDataSize) ->
+ SecParams = init_security_parameters(ConnectionEnd, Version),
#{security_parameters => SecParams,
beast_mitigation => BeastMitigation,
compression_state => undefined,
@@ -483,13 +486,16 @@ empty_connection_state(ConnectionEnd, BeastMitigation, MaxEarlyDataSize) ->
early_data_limit => false
}.
-empty_security_params(ConnectionEnd = ?CLIENT) ->
- #security_parameters{connection_end = ConnectionEnd,
- client_random = random()};
-empty_security_params(ConnectionEnd = ?SERVER) ->
- #security_parameters{connection_end = ConnectionEnd,
- server_random = random()}.
-random() ->
+init_security_parameters(?CLIENT, Version) ->
+ #security_parameters{connection_end = ?CLIENT,
+ client_random = make_random(Version)};
+init_security_parameters(?SERVER, Version) ->
+ #security_parameters{connection_end = ?SERVER,
+ server_random = make_random(Version)}.
+
+make_random({_Major, _Minor} = Version) when Version >= ?TLS_1_3 ->
+ ssl_cipher:random_bytes(32);
+make_random(_Version) ->
Secs_since_1970 = calendar:datetime_to_gregorian_seconds(
calendar:universal_time()) - 62167219200,
Random_28_bytes = ssl_cipher:random_bytes(28),
diff --git a/lib/ssl/src/ssl_server_session_cache_sup.erl b/lib/ssl/src/ssl_server_session_cache_sup.erl
index 88f068a319..80868215d8 100644
--- a/lib/ssl/src/ssl_server_session_cache_sup.erl
+++ b/lib/ssl/src/ssl_server_session_cache_sup.erl
@@ -44,22 +44,19 @@ start_link() ->
start_child(Listner) ->
supervisor:start_child(?MODULE, [Listner | [ssl_config:pre_1_3_session_opts(server)]]).
-
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
-init(_O) ->
- RestartStrategy = simple_one_for_one,
- MaxR = 3,
- MaxT = 3600,
-
- Name = undefined, % As simple_one_for_one is used.
- StartFunc = {ssl_server_session_cache, start_link, []},
- Restart = transient, % Should be restarted only on abnormal termination
- Shutdown = 4000,
- Modules = [ssl_server_session_cache],
- Type = worker,
-
- ChildSpec = {Name, StartFunc, Restart, Shutdown, Type, Modules},
- {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}.
-
+init(_) ->
+ SupFlags = #{strategy => simple_one_for_one,
+ intensity => 3,
+ period => 3600
+ },
+ ChildSpecs = [#{id => undefined,
+ start => {ssl_server_session_cache, start_link, []},
+ restart => transient,
+ shutdown => 4000,
+ modules => [ssl_server_session_cache],
+ type => worker
+ }],
+ {ok, {SupFlags, ChildSpecs}}.
diff --git a/lib/ssl/src/ssl_sup.erl b/lib/ssl/src/ssl_sup.erl
index 05a7aaaa82..1c38eae433 100644
--- a/lib/ssl/src/ssl_sup.erl
+++ b/lib/ssl/src/ssl_sup.erl
@@ -43,29 +43,32 @@ start_link() ->
%%% Supervisor callback
%%%=========================================================================
-init([]) ->
- {ok, {{rest_for_one, 10, 3600}, [ssl_admin_child_spec(),
- ssl_connection_sup()
- ]}}.
+init([]) ->
+ SupFlags = #{strategy => rest_for_one,
+ intensity => 10,
+ period => 3600
+ },
+ ChildSpecs = [ssl_admin_child_spec(),
+ ssl_connection_sup()],
+ {ok, {SupFlags, ChildSpecs}}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
ssl_admin_child_spec() ->
- Name = ssl_admin_sup,
- StartFunc = {ssl_admin_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [ssl_admin_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
+ #{id => ssl_admin_sup,
+ start => {ssl_admin_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [ssl_admin_sup],
+ type => supervisor
+ }.
+
ssl_connection_sup() ->
- Name = ssl_connection_sup,
- StartFunc = {ssl_connection_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [ssl_connection_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
+ #{id => ssl_connection_sup,
+ start => {ssl_connection_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [ssl_connection_sup],
+ type => supervisor
+ }.
diff --git a/lib/ssl/src/ssl_upgrade_server_session_cache_sup.erl b/lib/ssl/src/ssl_upgrade_server_session_cache_sup.erl
index 69169cca0d..62f1e8e4f1 100644
--- a/lib/ssl/src/ssl_upgrade_server_session_cache_sup.erl
+++ b/lib/ssl/src/ssl_upgrade_server_session_cache_sup.erl
@@ -69,20 +69,19 @@ start_child(Type) ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
-init(_O) ->
- RestartStrategy = simple_one_for_one,
- MaxR = 3,
- MaxT = 3600,
-
- Name = undefined, % As simple_one_for_one is used.
- StartFunc = {ssl_server_session_cache, start_link, []},
- Restart = transient, % Should be restarted only on abnormal termination
- Shutdown = 4000,
- Modules = [ssl_server_session_cache],
- Type = worker,
-
- ChildSpec = {Name, StartFunc, Restart, Shutdown, Type, Modules},
- {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}.
+init(_) ->
+ SupFlags = #{strategy => simple_one_for_one,
+ intensity => 3,
+ period => 3600
+ },
+ ChildSpecs = [#{id => undefined,
+ start => {ssl_server_session_cache, start_link, []},
+ restart => transient,
+ shutdown => 4000,
+ modules => [ssl_server_session_cache],
+ type => worker
+ }],
+ {ok, {SupFlags, ChildSpecs}}.
sup_name(normal) ->
?MODULE;
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index ff06b5dc71..7f0be2dbc5 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -215,7 +215,7 @@ hello(internal, #client_hello{extensions = Extensions} = Hello,
[{reply, From, {ok, Extensions}}]};
hello(internal, #server_hello{extensions = Extensions} = Hello,
#state{ssl_options = #{
- handshake := hello},
+ handshake := hello},
handshake_env = HsEnv,
start_or_recv_from = From} = State) ->
{next_state, user_hello,
@@ -229,52 +229,56 @@ hello(internal, #client_hello{client_version = ClientVersion} = Hello, #state{ss
%% Continue in TLS 1.3 'start' state
{next_state, start, State0, [{change_callback_module, tls_connection_1_3}, {next_event, internal, Hello}]};
tls_1_0_to_1_2_fsm ->
- case handle_client_hello(Hello, State0) of
+ try handle_client_hello(Hello, State0) of
{ServerHelloExt, Type, State} ->
- {next_state, hello, State, [{next_event, internal, {common_client_hello, Type, ServerHelloExt}}]};
- Alert ->
- ssl_gen_statem:handle_own_alert(Alert, ClientVersion, hello,
- State0#state{connection_env = CEnv#connection_env{negotiated_version
- = ClientVersion}})
+ {next_state, hello, State, [{next_event, internal, {common_client_hello, Type, ServerHelloExt}}]}
+ catch throw:#alert{} = Alert ->
+ State = State0#state{connection_env = CEnv#connection_env{negotiated_version = ClientVersion}},
+ ssl_gen_statem:handle_own_alert(Alert, hello, State)
end
end;
hello(internal, #server_hello{} = Hello,
#state{connection_states = ConnectionStates0,
- connection_env = #connection_env{negotiated_version = ReqVersion} = CEnv,
+ connection_env = CEnv,
static_env = #static_env{role = client},
handshake_env = #handshake_env{
ocsp_stapling_state = OcspState0,
renegotiation = {Renegotiation, _}} = HsEnv,
session = #session{session_id = OldId},
- ssl_options = SslOptions} = State) ->
- case tls_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation, OldId) of
- #alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, ReqVersion, hello,
- State#state{connection_env =
- CEnv#connection_env{negotiated_version = ReqVersion}
- });
- %% Legacy TLS 1.2 and older
- {Version, NewId, ConnectionStates, ProtoExt, Protocol, OcspState} ->
- tls_dtls_connection:handle_session(Hello,
- Version, NewId, ConnectionStates, ProtoExt, Protocol,
- State#state{
- handshake_env = HsEnv#handshake_env{
- ocsp_stapling_state = maps:merge(OcspState0,OcspState)}});
- %% TLS 1.3
- {next_state, wait_sh, SelectedVersion, OcspState} ->
- %% Continue in TLS 1.3 'wait_sh' state
- {next_state, wait_sh,
- State#state{handshake_env = HsEnv#handshake_env{ocsp_stapling_state = maps:merge(OcspState0,OcspState)},
- connection_env = CEnv#connection_env{negotiated_version = SelectedVersion}},
- [{change_callback_module, tls_connection_1_3}, {next_event, internal, Hello}]}
+ ssl_options = SslOptions} = State) ->
+ try
+ case tls_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation, OldId) of
+ %% Legacy TLS 1.2 and older
+ {Version, NewId, ConnectionStates, ProtoExt, Protocol, OcspState} ->
+ tls_dtls_connection:handle_session(Hello,
+ Version, NewId, ConnectionStates, ProtoExt, Protocol,
+ State#state{
+ handshake_env = HsEnv#handshake_env{
+ ocsp_stapling_state = maps:merge(OcspState0,OcspState)}});
+ %% TLS 1.3
+ {next_state, wait_sh, SelectedVersion, OcspState} ->
+ %% Continue in TLS 1.3 'wait_sh' state
+ {next_state, wait_sh,
+ State#state{handshake_env = HsEnv#handshake_env{ocsp_stapling_state = maps:merge(OcspState0,OcspState)},
+ connection_env = CEnv#connection_env{negotiated_version = SelectedVersion}},
+ [{change_callback_module, tls_connection_1_3}, {next_event, internal, Hello}]}
+ end
+ catch throw:#alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, hello, State)
end;
hello(info, Event, State) ->
tls_gen_connection:handle_info(Event, ?FUNCTION_NAME, State);
hello(Type, Event, State) ->
- tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State).
+ try tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State)
+ catch throw:#alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
+ end.
user_hello(Type, Event, State) ->
- tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State).
+ try tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State)
+ catch throw:#alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
+ end.
%%--------------------------------------------------------------------
-spec abbreviated(gen_statem:event_type(), term(), #state{}) ->
@@ -283,7 +287,10 @@ user_hello(Type, Event, State) ->
abbreviated(info, Event, State) ->
gen_info(Event, ?FUNCTION_NAME, State);
abbreviated(Type, Event, State) ->
- tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State).
+ try tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State)
+ catch throw:#alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
+ end.
%%--------------------------------------------------------------------
-spec wait_ocsp_stapling(gen_statem:event_type(), term(), #state{}) ->
@@ -292,7 +299,10 @@ abbreviated(Type, Event, State) ->
wait_ocsp_stapling(info, Event, State) ->
gen_info(Event, ?FUNCTION_NAME, State);
wait_ocsp_stapling(Type, Event, State) ->
- tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State).
+ try tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State)
+ catch throw:#alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
+ end.
%%--------------------------------------------------------------------
-spec certify(gen_statem:event_type(), term(), #state{}) ->
@@ -301,7 +311,10 @@ wait_ocsp_stapling(Type, Event, State) ->
certify(info, Event, State) ->
gen_info(Event, ?FUNCTION_NAME, State);
certify(Type, Event, State) ->
- tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State).
+ try tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State)
+ catch throw:#alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
+ end.
%%--------------------------------------------------------------------
-spec cipher(gen_statem:event_type(), term(), #state{}) ->
@@ -310,7 +323,10 @@ certify(Type, Event, State) ->
cipher(info, Event, State) ->
gen_info(Event, ?FUNCTION_NAME, State);
cipher(Type, Event, State) ->
- tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State).
+ try tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State)
+ catch throw:#alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
+ end.
%%--------------------------------------------------------------------
-spec connection(gen_statem:event_type(),
@@ -395,7 +411,10 @@ connection(internal, #client_hello{},
State = tls_gen_connection:reinit_handshake_data(State0),
tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
connection(Type, Event, State) ->
- tls_dtls_connection:?FUNCTION_NAME(Type, Event, State).
+ try tls_dtls_connection:?FUNCTION_NAME(Type, Event, State)
+ catch throw:#alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
+ end.
%%--------------------------------------------------------------------
-spec downgrade(gen_statem:event_type(), term(), #state{}) ->
@@ -417,8 +436,7 @@ terminate({shutdown, {sender_died, Reason}}, _StateName,
ssl_gen_statem:handle_trusted_certs_db(State),
tls_gen_connection:close(Reason, Socket, Transport, undefined, undefined);
terminate(Reason, StateName, State) ->
- catch ssl_gen_statem:terminate(Reason, StateName, State),
- ensure_sender_terminate(Reason, State).
+ ssl_gen_statem:terminate(Reason, StateName, State).
format_status(Type, Data) ->
ssl_gen_statem:format_status(Type, Data).
@@ -433,8 +451,12 @@ initial_state(Role, Sender, Host, Port, Socket, {SSLOptions, SocketOptions, Trac
{CbModule, DataTag, CloseTag, ErrorTag, PassiveTag}) ->
#{beast_mitigation := BeastMitigation,
erl_dist := IsErlDist,
+ %% Use highest supported version for client/server random nonce generation
+ versions := [Version|_],
client_renegotiation := ClientRenegotiation} = SSLOptions,
- ConnectionStates = tls_record:init_connection_states(Role, BeastMitigation),
+ ConnectionStates = tls_record:init_connection_states(Role,
+ Version,
+ BeastMitigation),
#{session_cb := SessionCacheCb} = ssl_config:pre_1_3_session_opts(Role),
UserMonitor = erlang:monitor(process, User),
InitStatEnv = #static_env{
@@ -474,86 +496,65 @@ initial_state(Role, Sender, Host, Port, Socket, {SSLOptions, SocketOptions, Trac
}.
handle_client_hello(#client_hello{client_version = ClientVersion} = Hello, State0) ->
- case tls_dtls_connection:handle_sni_extension(State0, Hello) of
- #state{connection_states = ConnectionStates0,
- static_env = #static_env{trackers = Trackers},
- handshake_env = #handshake_env{
- kex_algorithm = KeyExAlg,
- renegotiation = {Renegotiation, _},
- negotiated_protocol = CurrentProtocol,
- sni_guided_cert_selection = SNICertSelection} = HsEnv,
- connection_env = CEnv,
- session = #session{own_certificates = OwnCerts} = Session0,
- ssl_options = SslOpts} = State ->
- SessionTracker = proplists:get_value(session_id_tracker, Trackers),
- case tls_handshake:hello(Hello,
- SslOpts,
- {SessionTracker, Session0,
- ConnectionStates0, OwnCerts, KeyExAlg},
- Renegotiation) of
- #alert{} = Alert ->
- Alert;
- {Version, {Type, Session},
- ConnectionStates, Protocol0, ServerHelloExt0, HashSign} ->
- Protocol = case Protocol0 of
- undefined -> CurrentProtocol;
- _ -> Protocol0
- end,
- ServerHelloExt =
- case SNICertSelection of
- true ->
- ServerHelloExt0#{sni => #sni{hostname = ""}};
- false ->
- ServerHelloExt0
- end,
- {ServerHelloExt, Type, State#state{connection_states = ConnectionStates,
- connection_env = CEnv#connection_env{negotiated_version = Version},
- handshake_env = HsEnv#handshake_env{
- hashsign_algorithm = HashSign,
- client_hello_version = ClientVersion,
- negotiated_protocol = Protocol},
- session = Session
- }}
- end;
- #alert{} = Alert ->
- Alert
- end.
+ State = tls_dtls_connection:handle_sni_extension(State0, Hello),
+ #state{connection_states = ConnectionStates0,
+ static_env = #static_env{trackers = Trackers},
+ handshake_env = #handshake_env{
+ kex_algorithm = KeyExAlg,
+ renegotiation = {Renegotiation, _},
+ negotiated_protocol = CurrentProtocol,
+ sni_guided_cert_selection = SNICertSelection} = HsEnv,
+ connection_env = CEnv,
+ session = #session{own_certificates = OwnCerts} = Session0,
+ ssl_options = SslOpts} = State,
+ SessionTracker = proplists:get_value(session_id_tracker, Trackers),
+ {Version, {Type, Session},
+ ConnectionStates, Protocol0, ServerHelloExt0, HashSign} =
+ tls_handshake:hello(Hello,
+ SslOpts,
+ {SessionTracker, Session0,
+ ConnectionStates0, OwnCerts, KeyExAlg},
+ Renegotiation),
+ Protocol = case Protocol0 of
+ undefined -> CurrentProtocol;
+ _ -> Protocol0
+ end,
+ ServerHelloExt =
+ case SNICertSelection of
+ true ->
+ ServerHelloExt0#{sni => #sni{hostname = ""}};
+ false ->
+ ServerHelloExt0
+ end,
+ {ServerHelloExt, Type, State#state{connection_states = ConnectionStates,
+ connection_env = CEnv#connection_env{negotiated_version = Version},
+ handshake_env = HsEnv#handshake_env{
+ hashsign_algorithm = HashSign,
+ client_hello_version = ClientVersion,
+ negotiated_protocol = Protocol},
+ session = Session
+ }}.
-gen_info(Event, connection = StateName, #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
- try tls_gen_connection:handle_info(Event, StateName, State) of
- Result ->
- Result
- catch
+gen_info(Event, connection = StateName, State) ->
+ try
+ tls_gen_connection:handle_info(Event, StateName, State)
+ catch
_:_ ->
ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?INTERNAL_ERROR,
- malformed_data),
- Version, StateName, State)
+ malformed_data),
+ StateName, State)
end;
-gen_info(Event, StateName, #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
- try tls_gen_connection:handle_info(Event, StateName, State) of
- Result ->
- Result
- catch
+gen_info(Event, StateName, State) ->
+ try
+ tls_gen_connection:handle_info(Event, StateName, State)
+ catch
_:_ ->
ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,
- malformed_handshake_data),
- Version, StateName, State)
+ malformed_handshake_data),
+ StateName, State)
end.
-
-ensure_sender_terminate(downgrade, _) ->
- ok; %% Do not terminate sender during downgrade phase
-ensure_sender_terminate(_, #state{protocol_specific = #{sender := Sender}}) ->
- %% Make sure TLS sender dies when connection process is terminated normally
- %% This is needed if the tls_sender is blocked in prim_inet:send
- Kill = fun() ->
- receive
- after 5000 ->
- catch (exit(Sender, kill))
- end
- end,
- spawn(Kill).
choose_tls_fsm(#{versions := Versions},
#client_hello{
diff --git a/lib/ssl/src/tls_connection_1_3.erl b/lib/ssl/src/tls_connection_1_3.erl
index 2d123bab43..bacdf791ad 100644
--- a/lib/ssl/src/tls_connection_1_3.erl
+++ b/lib/ssl/src/tls_connection_1_3.erl
@@ -232,11 +232,10 @@ config_error(Type, Event, State) ->
ssl_gen_statem:?FUNCTION_NAME(Type, Event, State).
-user_hello({call, From}, cancel, #state{connection_env = #connection_env{negotiated_version = Version}}
- = State) ->
+user_hello({call, From}, cancel, State) ->
gen_statem:reply(From, ok),
ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?USER_CANCELED, user_canceled),
- Version, ?FUNCTION_NAME, State);
+ ?FUNCTION_NAME, State);
user_hello({call, From}, {handshake_continue, NewOptions, Timeout},
#state{static_env = #static_env{role = Role},
handshake_env = #handshake_env{hello = Hello},
@@ -269,7 +268,7 @@ start(internal, #client_hello{extensions = Extensions} = Hello,
start(internal, #client_hello{} = Hello, State0) ->
case tls_handshake_1_3:do_start(Hello, State0) of
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, {3,4}, start, State0);
+ ssl_gen_statem:handle_own_alert(Alert, start, State0);
{State, start} ->
{next_state, start, State, []};
{State, negotiated} ->
@@ -289,7 +288,7 @@ start(internal, #server_hello{extensions = Extensions} = ServerHello,
start(internal, #server_hello{} = ServerHello, State0) ->
case tls_handshake_1_3:do_start(ServerHello, State0) of
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, {3,4}, start, State0);
+ ssl_gen_statem:handle_own_alert(Alert, start, State0);
{State, NextState} ->
{next_state, NextState, State, []}
end;
@@ -303,7 +302,7 @@ negotiated(internal, #change_cipher_spec{}, State) ->
negotiated(internal, Message, State0) ->
case tls_handshake_1_3:do_negotiated(Message, State0) of
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, {3,4}, negotiated, State0);
+ ssl_gen_statem:handle_own_alert(Alert, negotiated, State0);
{State, NextState} ->
{next_state, NextState, State, []}
end;
@@ -316,7 +315,7 @@ wait_cert(internal,
#certificate_1_3{} = Certificate, State0) ->
case tls_handshake_1_3:do_wait_cert(Certificate, State0) of
{#alert{} = Alert, State} ->
- ssl_gen_statem:handle_own_alert(Alert, {3,4}, wait_cert, State);
+ ssl_gen_statem:handle_own_alert(Alert, wait_cert, State);
{State, NextState} ->
tls_gen_connection:next_event(NextState, no_record, State)
end;
@@ -331,7 +330,7 @@ wait_cv(internal,
#certificate_verify_1_3{} = CertificateVerify, State0) ->
case tls_handshake_1_3:do_wait_cv(CertificateVerify, State0) of
{#alert{} = Alert, State} ->
- ssl_gen_statem:handle_own_alert(Alert, {3,4}, wait_cv, State);
+ ssl_gen_statem:handle_own_alert(Alert, wait_cv, State);
{State, NextState} ->
tls_gen_connection:next_event(NextState, no_record, State)
end;
@@ -346,7 +345,7 @@ wait_finished(internal,
#finished{} = Finished, State0) ->
case tls_handshake_1_3:do_wait_finished(Finished, State0) of
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, {3,4}, finished, State0);
+ ssl_gen_statem:handle_own_alert(Alert, finished, State0);
State1 ->
{Record, State} = ssl_gen_statem:prepare_connection(State1, tls_gen_connection),
tls_gen_connection:next_event(connection, Record, State,
@@ -370,7 +369,7 @@ wait_sh(internal, #server_hello{extensions = Extensions} = Hello, #state{ssl_op
wait_sh(internal, #server_hello{} = Hello, State0) ->
case tls_handshake_1_3:do_wait_sh(Hello, State0) of
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, {3,4}, wait_sh, State0);
+ ssl_gen_statem:handle_own_alert(Alert, wait_sh, State0);
{State1, start, ServerHello} ->
%% hello_retry_request: go to start
{next_state, start, State1, [{next_event, internal, ServerHello}]};
@@ -388,7 +387,7 @@ wait_ee(internal, #change_cipher_spec{}, State) ->
wait_ee(internal, #encrypted_extensions{} = EE, State0) ->
case tls_handshake_1_3:do_wait_ee(EE, State0) of
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, {3,4}, wait_ee, State0);
+ ssl_gen_statem:handle_own_alert(Alert, wait_ee, State0);
{State1, NextState} ->
tls_gen_connection:next_event(NextState, no_record, State1)
end;
@@ -403,14 +402,14 @@ wait_cert_cr(internal, #change_cipher_spec{}, State) ->
wait_cert_cr(internal, #certificate_1_3{} = Certificate, State0) ->
case tls_handshake_1_3:do_wait_cert_cr(Certificate, State0) of
{#alert{} = Alert, State} ->
- ssl_gen_statem:handle_own_alert(Alert, {3,4}, wait_cert_cr, State);
+ ssl_gen_statem:handle_own_alert(Alert, wait_cert_cr, State);
{State1, NextState} ->
tls_gen_connection:next_event(NextState, no_record, State1)
end;
wait_cert_cr(internal, #certificate_request_1_3{} = CertificateRequest, State0) ->
case tls_handshake_1_3:do_wait_cert_cr(CertificateRequest, State0) of
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, {3,4}, wait_cert_cr, State0);
+ ssl_gen_statem:handle_own_alert(Alert, wait_cert_cr, State0);
{State1, NextState} ->
tls_gen_connection:next_event(NextState, no_record, State1)
end;
@@ -424,7 +423,7 @@ wait_eoed(internal, #change_cipher_spec{}, State) ->
wait_eoed(internal, #end_of_early_data{} = EOED, State0) ->
case tls_handshake_1_3:do_wait_eoed(EOED, State0) of
{#alert{} = Alert, State} ->
- ssl_gen_statem:handle_own_alert(Alert, {3,4}, wait_eoed, State);
+ ssl_gen_statem:handle_own_alert(Alert, wait_eoed, State);
{State1, NextState} ->
tls_gen_connection:next_event(NextState, no_record, State1)
end;
@@ -442,7 +441,7 @@ connection(internal, #key_update{} = KeyUpdate, State0) ->
{ok, State} ->
tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
{error, State, Alert} ->
- ssl_gen_statem:handle_own_alert(Alert, {3,4}, connection, State),
+ ssl_gen_statem:handle_own_alert(Alert, connection, State),
tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State)
end;
connection({call, From}, negotiated_protocol,
@@ -468,9 +467,14 @@ downgrade(Type, Event, State) ->
initial_state(Role, Sender, Host, Port, Socket, {SSLOptions, SocketOptions, Trackers}, User,
{CbModule, DataTag, CloseTag, ErrorTag, PassiveTag}) ->
#{erl_dist := IsErlDist,
+ %% Use highest supported version for client/server random nonce generation
+ versions := [Version|_],
client_renegotiation := ClientRenegotiation} = SSLOptions,
MaxEarlyDataSize = init_max_early_data_size(Role),
- ConnectionStates = tls_record:init_connection_states(Role, disabled, MaxEarlyDataSize),
+ ConnectionStates = tls_record:init_connection_states(Role,
+ Version,
+ disabled,
+ MaxEarlyDataSize),
UserMonitor = erlang:monitor(process, User),
InitStatEnv = #static_env{
role = Role,
diff --git a/lib/ssl/src/tls_connection_sup.erl b/lib/ssl/src/tls_connection_sup.erl
index b7f80ad524..435639cf68 100644
--- a/lib/ssl/src/tls_connection_sup.erl
+++ b/lib/ssl/src/tls_connection_sup.erl
@@ -44,24 +44,22 @@ start_link_dist() ->
start_child(Args) ->
supervisor:start_child(?MODULE, Args).
-
+
start_child_dist(Args) ->
supervisor:start_child(tls_dist_connection_sup, Args).
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
-init(_O) ->
- RestartStrategy = simple_one_for_one,
- MaxR = 0,
- MaxT = 3600,
-
- Name = undefined, % As simple_one_for_one is used.
- StartFunc = {ssl_gen_statem, start_link, []},
- Restart = temporary, % E.g. should not be restarted
- Shutdown = 4000,
- Modules = [ssl_gen_statem, tls_connection, tls_connection_1_3],
- Type = worker,
-
- ChildSpec = {Name, StartFunc, Restart, Shutdown, Type, Modules},
- {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}.
+init(_) ->
+ SupFlags = #{strategy => simple_one_for_one,
+ intensity => 0,
+ period => 3600
+ },
+ ChildSpecs = [#{id => undefined,
+ restart => temporary,
+ type => supervisor,
+ start => {tls_dyn_connection_sup, start_link, []}}],
+ {ok, {SupFlags, ChildSpecs}}.
+
+
diff --git a/lib/ssl/src/tls_dist_server_sup.erl b/lib/ssl/src/tls_dist_server_sup.erl
index 96603a7495..9560d05158 100644
--- a/lib/ssl/src/tls_dist_server_sup.erl
+++ b/lib/ssl/src/tls_dist_server_sup.erl
@@ -43,16 +43,16 @@ start_link() ->
%%% Supervisor callback
%%%=========================================================================
-init([]) ->
- ListenTracker = listen_options_tracker_child_spec(),
- SessionTracker = tls_server_session_child_spec(),
- Pre_1_3SessionTracker = ssl_server_session_child_spec(),
-
- {ok, {{one_for_all, 10, 3600}, [ListenTracker,
- SessionTracker,
- Pre_1_3SessionTracker
- ]}}.
-
+init([]) ->
+ SupFlags = #{strategy => one_for_all,
+ intensity => 10,
+ period => 3600
+ },
+ ChildSpecs = [listen_options_tracker_child_spec(),
+ tls_server_session_child_spec(),
+ ssl_server_session_child_spec()],
+ {ok, {SupFlags, ChildSpecs}}.
+
%%--------------------------------------------------------------------
%%% Internal functions
@@ -61,29 +61,28 @@ init([]) ->
%% Handles emulated options so that they inherited by the accept
%% socket, even when setopts is performed on the listen socket
listen_options_tracker_child_spec() ->
- Name = dist_tls_socket,
- StartFunc = {ssl_listen_tracker_sup, start_link_dist, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [ssl_listen_tracker_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => dist_ssl_listen_tracker_sup,
+ start => {ssl_listen_tracker_sup, start_link_dist, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [ssl_listen_tracker_sup],
+ type => supervisor
+ }.
tls_server_session_child_spec() ->
- Name = dist_tls_server_session_ticket,
- StartFunc = {tls_server_session_ticket_sup, start_link_dist, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [tls_server_session_ticket_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => dist_tls_server_session_ticket,
+ start => {tls_server_session_ticket_sup, start_link_dist, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [tls_server_session_ticket_sup],
+ type => supervisor
+ }.
ssl_server_session_child_spec() ->
- Name = dist_ssl_server_session_cache_sup,
- StartFunc = {ssl_upgrade_server_session_cache_sup, start_link_dist, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [ssl_server_session_cache_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
+ #{id => dist_ssl_upgrade_server_session_cache_sup,
+ start => {ssl_upgrade_server_session_cache_sup, start_link_dist, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [ssl_upgrade_server_session_cache_sup],
+ type => supervisor
+ }.
diff --git a/lib/ssl/src/tls_dist_sup.erl b/lib/ssl/src/tls_dist_sup.erl
index 54e0a6a514..ebff741f9b 100644
--- a/lib/ssl/src/tls_dist_sup.erl
+++ b/lib/ssl/src/tls_dist_sup.erl
@@ -44,32 +44,34 @@ start_link() ->
%%%=========================================================================
init([]) ->
-
- TLSConnetionSup = tls_connection_child_spec(),
- ServerInstanceSup = server_instance_child_spec(),
-
- {ok, {{one_for_one, 10, 3600}, [TLSConnetionSup,
- ServerInstanceSup
- ]}}.
+ SupFlags = #{strategy => one_for_one,
+ intensity => 10,
+ period => 3600
+ },
+ ChildSpecs = [tls_connection_child_spec(),
+ server_instance_child_spec()
+ ],
+ {ok, {SupFlags, ChildSpecs}}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
tls_connection_child_spec() ->
- Name = dist_tls_connection,
- StartFunc = {tls_connection_sup, start_link_dist, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [tls_connection_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
+ #{id => dist_tls_connection_sup,
+ start => {tls_connection_sup, start_link_dist, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [tls_connection_sup],
+ type => supervisor
+ }.
+
server_instance_child_spec() ->
- Name = dist_tls_server_sup,
- StartFunc = {tls_dist_server_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [tls_dist_server_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => tls_dist_server_sup,
+ start => {tls_dist_server_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [tls_dist_server_sup],
+ type => supervisor
+ }.
+
diff --git a/lib/ssl/src/tls_dtls_connection.erl b/lib/ssl/src/tls_dtls_connection.erl
index bb138b035b..5ee5c41b44 100644
--- a/lib/ssl/src/tls_dtls_connection.erl
+++ b/lib/ssl/src/tls_dtls_connection.erl
@@ -22,6 +22,8 @@
%%----------------------------------------------------------------------
%% Purpose: Common handling of a TLS/SSL/DTLS connection, see also
%% tls_connection.erl and dtls_connection.erl
+%%
+%% NOTE: All alerts are thrown out of this module
%%----------------------------------------------------------------------
-module(tls_dtls_connection).
@@ -113,13 +115,11 @@ handle_session(#server_hello{cipher_suite = CipherSuite,
PremasterSecret = make_premaster_secret(ReqVersion, KeyAlgorithm),
- {ExpectNPN, Protocol} = case Protocol0 of
- undefined ->
-
- {false, CurrentProtocol};
- _ ->
- {ProtoExt =:= npn, Protocol0}
- end,
+ {ExpectNPN, Protocol} =
+ case Protocol0 of
+ undefined -> {false, CurrentProtocol};
+ _ -> {ProtoExt =:= npn, Protocol0}
+ end,
State = State0#state{connection_states = ConnectionStates,
handshake_env = HsEnv#handshake_env{kex_algorithm = KeyAlgorithm,
@@ -163,10 +163,9 @@ hello(Type, Event, State) ->
#hello_request{} | term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-user_hello({call, From}, cancel, #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
+user_hello({call, From}, cancel, _State) ->
gen_statem:reply(From, ok),
- ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?USER_CANCELED, user_canceled),
- Version, ?FUNCTION_NAME, State);
+ throw(?ALERT_REC(?FATAL, ?USER_CANCELED, user_canceled));
user_hello({call, From}, {handshake_continue, NewOptions, Timeout},
#state{static_env = #static_env{role = Role},
handshake_env = #handshake_env{hello = Hello},
@@ -209,7 +208,7 @@ abbreviated(internal, #finished{verify_data = Data} = Finished,
Connection),
Connection:next_event(connection, Record, State, [{{timeout, handshake}, infinity, close}]);
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
+ throw(Alert)
end;
abbreviated(internal, #finished{verify_data = Data} = Finished,
#state{static_env = #static_env{role = client,
@@ -232,7 +231,7 @@ abbreviated(internal, #finished{verify_data = Data} = Finished,
Connection),
Connection:next_event(connection, Record, State, [{{timeout, handshake}, infinity, close} | Actions]);
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
+ throw(Alert)
end;
%% only allowed to send next_protocol message after change cipher spec
%% & before finished message and it is not allowed during renegotiation
@@ -309,12 +308,8 @@ certify(info, Msg, State) ->
handle_info(Msg, ?FUNCTION_NAME, State);
certify(internal, #certificate{asn1_certificates = []},
#state{static_env = #static_env{role = server},
- connection_env = #connection_env{negotiated_version = Version},
- ssl_options = #{verify := verify_peer,
- fail_if_no_peer_cert := true}} =
- State) ->
- Alert = ?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE, no_client_certificate_provided),
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State);
+ ssl_options = #{verify := verify_peer, fail_if_no_peer_cert := true}}) ->
+ throw(?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE, no_client_certificate_provided));
certify(internal, #certificate{asn1_certificates = []},
#state{static_env = #static_env{role = server,
protocol_cb = Connection},
@@ -324,11 +319,8 @@ certify(internal, #certificate{asn1_certificates = []},
Connection:next_event(?FUNCTION_NAME, no_record, State0#state{client_certificate_requested = false});
certify(internal, #certificate{},
#state{static_env = #static_env{role = server},
- connection_env = #connection_env{negotiated_version = Version},
- ssl_options = #{verify := verify_none}} =
- State) ->
- Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, unrequested_certificate),
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State);
+ ssl_options = #{verify := verify_none}}) ->
+ throw(?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, unrequested_certificate));
certify(internal, #certificate{},
#state{static_env = #static_env{protocol_cb = Connection},
handshake_env = #handshake_env{
@@ -355,7 +347,7 @@ certify(internal, #certificate{asn1_certificates = [Peer|_]} = Cert,
handle_peer_cert(Role, PeerCert, PublicKeyInfo,
State#state{client_certificate_requested = false}, Connection, []);
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
+ throw(Alert)
end;
certify(internal, #server_key_exchange{exchange_keys = Keys},
#state{static_env = #static_env{role = client,
@@ -397,14 +389,12 @@ certify(internal, #server_key_exchange{exchange_keys = Keys},
session = session_handle_params(Params#server_key_params.params, Session)},
Connection);
false ->
- ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?DECRYPT_ERROR),
- Version, ?FUNCTION_NAME, State)
+ throw(?ALERT_REC(?FATAL, ?DECRYPT_ERROR))
end
end;
certify(internal, #certificate_request{},
#state{static_env = #static_env{role = client},
- handshake_env = #handshake_env{kex_algorithm = KexAlg},
- connection_env = #connection_env{negotiated_version = Version}} = State)
+ handshake_env = #handshake_env{kex_algorithm = KexAlg}})
when KexAlg == dh_anon;
KexAlg == ecdh_anon;
KexAlg == psk;
@@ -414,8 +404,7 @@ certify(internal, #certificate_request{},
KexAlg == srp_dss;
KexAlg == srp_rsa;
KexAlg == srp_anon ->
- ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE),
- Version, ?FUNCTION_NAME, State);
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE));
certify(internal, #certificate_request{},
#state{static_env = #static_env{role = client,
protocol_cb = Connection},
@@ -443,7 +432,7 @@ certify(internal, #certificate_request{} = CertRequest,
case ssl_handshake:select_hashsign(CertRequest, Cert,
SupportedHashSigns, TLSVersion) of
#alert {} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State);
+ throw(Alert);
SelectedHashSign ->
Connection:next_event(?FUNCTION_NAME, no_record,
State#state{client_certificate_requested = true,
@@ -455,7 +444,6 @@ certify(internal, #server_hello_done{},
#state{static_env = #static_env{role = client,
protocol_cb = Connection},
session = #session{master_secret = undefined},
- connection_env = #connection_env{negotiated_version = Version},
handshake_env = #handshake_env{kex_algorithm = KexAlg,
premaster_secret = undefined,
server_psk_identity = PSKIdentity} = HsEnv,
@@ -463,7 +451,7 @@ certify(internal, #server_hello_done{},
when KexAlg == psk ->
case ssl_handshake:premaster_secret({KexAlg, PSKIdentity}, PSKLookup) of
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0);
+ throw(Alert);
PremasterSecret ->
State = master_secret(PremasterSecret,
State0#state{handshake_env =
@@ -473,7 +461,7 @@ certify(internal, #server_hello_done{},
certify(internal, #server_hello_done{},
#state{static_env = #static_env{role = client,
protocol_cb = Connection},
- connection_env = #connection_env{negotiated_version = {Major, Minor}} = Version,
+ connection_env = #connection_env{negotiated_version = {Major, Minor}},
handshake_env = #handshake_env{kex_algorithm = KexAlg,
premaster_secret = undefined,
server_psk_identity = PSKIdentity} = HsEnv,
@@ -485,7 +473,7 @@ certify(internal, #server_hello_done{},
case ssl_handshake:premaster_secret({KexAlg, PSKIdentity}, PSKLookup,
RSAPremasterSecret) of
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0);
+ throw(Alert);
PremasterSecret ->
State = master_secret(PremasterSecret,
State0#state{handshake_env =
@@ -506,7 +494,7 @@ certify(internal, #server_hello_done{},
State = State0#state{connection_states = ConnectionStates},
client_certify_and_key_exchange(State, Connection);
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
+ throw(Alert)
end;
%% Master secret is calculated from premaster_secret
certify(internal, #server_hello_done{},
@@ -524,16 +512,14 @@ certify(internal, #server_hello_done{},
session = Session},
client_certify_and_key_exchange(State, Connection);
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
+ throw(Alert)
end;
certify(internal = Type, #client_key_exchange{} = Msg,
#state{static_env = #static_env{role = server},
client_certificate_requested = true,
- connection_env = #connection_env{negotiated_version = Version},
- ssl_options = #{fail_if_no_peer_cert := true}} = State) ->
+ ssl_options = #{fail_if_no_peer_cert := true}}) ->
%% We expect a certificate here
- Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, {unexpected_msg, {Type, Msg}}),
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State);
+ throw(?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, {unexpected_msg, {Type, Msg}}));
certify(internal, #client_key_exchange{exchange_keys = Keys},
State = #state{handshake_env = #handshake_env{kex_algorithm = KeyAlg},
static_env = #static_env{protocol_cb = Connection},
@@ -543,7 +529,7 @@ certify(internal, #client_key_exchange{exchange_keys = Keys},
State, Connection)
catch
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
+ throw(Alert)
end;
certify(internal, #hello_request{}, _) ->
keep_state_and_data;
@@ -580,15 +566,14 @@ cipher(internal, #certificate_verify{signature = Signature,
Connection:next_event(?FUNCTION_NAME, no_record,
State#state{handshake_env = HsEnv#handshake_env{cert_hashsign_algorithm = HashSign}});
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
+ throw(Alert)
end;
%% client must send a next protocol message if we are expecting it
cipher(internal, #finished{},
#state{static_env = #static_env{role = server},
handshake_env = #handshake_env{expecting_next_protocol_negotiation = true,
- negotiated_protocol = undefined},
- connection_env = #connection_env{negotiated_version = Version}} = State0) ->
- ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE), Version, ?FUNCTION_NAME, State0);
+ negotiated_protocol = undefined}}) ->
+ throw(?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE));
cipher(internal, #finished{verify_data = Data} = Finished,
#state{static_env = #static_env{role = Role,
host = Host,
@@ -610,7 +595,7 @@ cipher(internal, #finished{verify_data = Data} = Finished,
cipher_role(Role, Data, Session,
State#state{handshake_env = HsEnv#handshake_env{expecting_finished = false}});
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
+ throw(Alert)
end;
%% only allowed to send next_protocol message after change cipher spec
%% & before finished message and it is not allowed during renegotiation
@@ -688,16 +673,10 @@ connection(Type, Event, State) ->
downgrade(Type, Event, State) ->
ssl_gen_statem:handle_common_event(Type, Event, ?FUNCTION_NAME, State).
-gen_handshake(StateName, Type, Event,
- #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
- try tls_dtls_connection:StateName(Type, Event, State) of
- Result ->
- Result
- catch
- _:_ ->
- ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,
- malformed_handshake_data),
- Version, StateName, State)
+gen_handshake(StateName, Type, Event, State) ->
+ try tls_dtls_connection:StateName(Type, Event, State)
+ catch error:_ ->
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data))
end.
%%--------------------------------------------------------------------
@@ -825,20 +804,13 @@ new_server_hello(#server_hello{cipher_suite = CipherSuite,
compression_method = Compression,
session_id = SessionId},
#state{session = Session0,
- static_env = #static_env{protocol_cb = Connection},
- connection_env = #connection_env{negotiated_version = Version}} = State0, Connection) ->
- try server_certify_and_key_exchange(State0, Connection) of
- #state{} = State1 ->
- {State, Actions} = server_hello_done(State1, Connection),
- Session =
- Session0#session{session_id = SessionId,
- cipher_suite = CipherSuite,
- compression_method = Compression},
- Connection:next_event(certify, no_record, State#state{session = Session}, Actions)
- catch
- #alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, hello, State0)
- end.
+ static_env = #static_env{protocol_cb = Connection}} = State0, Connection) ->
+ #state{} = State1 = server_certify_and_key_exchange(State0, Connection),
+ {State, Actions} = server_hello_done(State1, Connection),
+ Session = Session0#session{session_id = SessionId,
+ cipher_suite = CipherSuite,
+ compression_method = Compression},
+ Connection:next_event(certify, no_record, State#state{session = Session}, Actions).
resumed_server_hello(#state{session = Session,
connection_states = ConnectionStates0,
@@ -854,7 +826,7 @@ resumed_server_hello(#state{session = Session,
finalize_handshake(State1, abbreviated, Connection),
Connection:next_event(abbreviated, no_record, State, Actions);
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, hello, State0)
+ throw(Alert)
end.
server_hello(ServerHello, State0, Connection) ->
@@ -923,19 +895,11 @@ verify_client_cert(#state{static_env = #static_env{role = client},
verify_client_cert(#state{client_certificate_requested = false} = State, _) ->
State.
-client_certify_and_key_exchange(#state{connection_env = #connection_env{negotiated_version = Version}} =
- State0, Connection) ->
- try do_client_certify_and_key_exchange(State0, Connection) of
- State1 = #state{} ->
- {State2, Actions} = finalize_handshake(State1, certify, Connection),
- State = State2#state{
- %% Reinitialize
- client_certificate_requested = false},
- Connection:next_event(cipher, no_record, State, Actions)
- catch
- throw:#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, certify, State0)
- end.
+client_certify_and_key_exchange(State0, Connection) ->
+ State1 = do_client_certify_and_key_exchange(State0, Connection),
+ {State2, Actions} = finalize_handshake(State1, certify, Connection),
+ State = State2#state{client_certificate_requested = false}, %% Reinitialize
+ Connection:next_event(cipher, no_record, State, Actions).
do_client_certify_and_key_exchange(State0, Connection) ->
State1 = certify_client(State0, Connection),
@@ -965,10 +929,10 @@ certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS
end;
_ -> %% erlang:byte_size(Secret) =/= ?NUM_OF_PREMASTERSECRET_BYTES
FakeSecret
- catch
+ catch
#alert{description = ?DECRYPT_ERROR} ->
FakeSecret
- end,
+ end,
calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPublicDhKey},
#state{handshake_env = #handshake_env{diffie_hellman_params = #'DHParameter'{} = Params,
@@ -1189,12 +1153,7 @@ key_exchange(#state{static_env = #static_env{role = server},
KexAlg == srp_rsa;
KexAlg == srp_anon ->
SrpParams = handle_srp_identity(Username, LookupFun),
- Keys = case generate_srp_server_keys(SrpParams, 0) of
- Alert = #alert{} ->
- throw(Alert);
- Keys0 = {_,_} ->
- Keys0
- end,
+ Keys = generate_srp_server_keys(SrpParams, 0),
#{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates0, read),
#security_parameters{client_random = ClientRandom,
@@ -1301,7 +1260,7 @@ rsa_key_exchange(Version, PremasterSecret, PublicKeyInfo = {Algorithm, _, _})
{premaster_secret, PremasterSecret,
PublicKeyInfo});
rsa_key_exchange(_, _, _) ->
- throw (?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE, pub_key_is_not_rsa)).
+ throw(?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE, pub_key_is_not_rsa)).
rsa_psk_key_exchange(Version, PskIdentity, PremasterSecret,
PublicKeyInfo = {Algorithm, _, _})
@@ -1318,7 +1277,7 @@ rsa_psk_key_exchange(Version, PskIdentity, PremasterSecret,
{psk_premaster_secret, PskIdentity, PremasterSecret,
PublicKeyInfo});
rsa_psk_key_exchange(_, _, _, _) ->
- throw (?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE, pub_key_is_not_rsa)).
+ throw(?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE, pub_key_is_not_rsa)).
request_client_cert(#state{handshake_env = #handshake_env{kex_algorithm = Alg}} = State, _)
when Alg == dh_anon;
@@ -1366,7 +1325,7 @@ calculate_master_secret(PremasterSecret,
session = Session},
Connection:next_event(Next, no_record, State);
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, certify, State0)
+ throw(Alert)
end.
finalize_handshake(State0, StateName, Connection) ->
@@ -1480,7 +1439,7 @@ calculate_secret(#server_srp_params{srp_n = Prime, srp_g = Generator} = ServerKe
certify, certify).
master_secret(#alert{} = Alert, _) ->
- Alert;
+ throw(Alert);
master_secret(PremasterSecret, #state{static_env = #static_env{role = Role},
connection_env = #connection_env{negotiated_version = Version},
session = Session,
@@ -1493,11 +1452,11 @@ master_secret(PremasterSecret, #state{static_env = #static_env{role = Role},
Session#session{master_secret = MasterSecret},
connection_states = ConnectionStates};
#alert{} = Alert ->
- Alert
+ throw(Alert)
end.
generate_srp_server_keys(_SrpParams, 10) ->
- ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER));
generate_srp_server_keys(SrpParams =
#srp_user{generator = Generator, prime = Prime,
verifier = Verifier}, N) ->
@@ -1510,9 +1469,8 @@ generate_srp_server_keys(SrpParams =
end.
generate_srp_client_keys(_Generator, _Prime, 10) ->
- ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER));
generate_srp_client_keys(Generator, Prime, N) ->
-
try crypto:generate_key(srp, {user, [Generator, Prime, '6a']}) of
Keys ->
Keys
@@ -1645,7 +1603,7 @@ handle_resumed_session(SessId, #state{static_env = #static_env{host = Host,
connection_states = ConnectionStates,
session = Session});
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, hello, State)
+ throw(Alert)
end.
make_premaster_secret({MajVer, MinVer}, rsa) ->
@@ -1674,8 +1632,8 @@ handle_sni_extension(#state{static_env =
case ssl_gen_statem:handle_sni_extension(PossibleSNI, State0) of
{ok, State} ->
State;
- {error, Alert} ->
- Alert
+ {error, #alert{}=Alert} ->
+ throw(Alert)
end.
ensure_tls({254, _} = Version) ->
diff --git a/lib/ssl/src/tls_dyn_connection_sup.erl b/lib/ssl/src/tls_dyn_connection_sup.erl
new file mode 100644
index 0000000000..cb0576cbd6
--- /dev/null
+++ b/lib/ssl/src/tls_dyn_connection_sup.erl
@@ -0,0 +1,78 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2021. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Supervises the TLS generic state machine, a process that
+%% owns the transport socket and hence is a significant child, and the
+%% corresponding TLS sender process that sends data to avoid blocking
+%% the state machine process.
+%% ----------------------------------------------------------------------
+
+-module(tls_dyn_connection_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+-export([start_child/3]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+start_link() ->
+ supervisor:start_link(?MODULE, []).
+
+start_child(Sup, sender, Args) ->
+ supervisor:start_child(Sup, sender(Args));
+start_child(Sup, receiver, Args) ->
+ supervisor:start_child(Sup, receiver(Args)).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init(_) ->
+ SupFlags = #{strategy => one_for_all,
+ auto_shutdown => any_significant,
+ intensity => 0,
+ period => 3600
+ },
+ ChildSpecs = [],
+ {ok, {SupFlags, ChildSpecs}}.
+
+sender(Args) ->
+ #{id => sender,
+ restart => temporary,
+ type => worker,
+ start => {tls_sender, start_link, Args},
+ modules => [tls_sender]
+ }.
+
+receiver(Args) ->
+ #{id => receiver,
+ restart => temporary,
+ type => worker,
+ significant => true,
+ start => {ssl_gen_statem, start_link, Args},
+ modules => [ssl_gen_statem, tls_connection, tls_connection_1_3]
+ }.
diff --git a/lib/ssl/src/tls_gen_connection.erl b/lib/ssl/src/tls_gen_connection.erl
index 217620f62e..59d30d7cb0 100644
--- a/lib/ssl/src/tls_gen_connection.erl
+++ b/lib/ssl/src/tls_gen_connection.erl
@@ -82,9 +82,10 @@ start_fsm(Role, Host, Port, Socket, {#{erl_dist := false},_, Trackers} = Opts,
User, {CbModule, _,_, _, _} = CbInfo,
Timeout) ->
try
- {ok, Sender} = tls_sender:start(),
- {ok, Pid} = tls_connection_sup:start_child([Role, Sender, Host, Port, Socket,
- Opts, User, CbInfo]),
+ {ok, DynSup} = tls_connection_sup:start_child([]),
+ {ok, Sender} = tls_dyn_connection_sup:start_child(DynSup, sender, []),
+ {ok, Pid} = tls_dyn_connection_sup:start_child(DynSup, receiver, [Role, Sender, Host, Port, Socket,
+ Opts, User, CbInfo]),
{ok, SslSocket} = ssl_gen_statem:socket_control(?MODULE, Socket, [Pid, Sender], CbModule, Trackers),
ssl_gen_statem:handshake(SslSocket, Timeout)
catch
@@ -96,9 +97,10 @@ start_fsm(Role, Host, Port, Socket, {#{erl_dist := true},_, Trackers} = Opts,
User, {CbModule, _,_, _, _} = CbInfo,
Timeout) ->
try
- {ok, Sender} = tls_sender:start([{spawn_opt, ?DIST_CNTRL_SPAWN_OPTS}]),
- {ok, Pid} = tls_connection_sup:start_child_dist([Role, Sender, Host, Port, Socket,
- Opts, User, CbInfo]),
+ {ok, DynSup} = tls_connection_sup:start_child_dist([]),
+ {ok, Sender} = tls_dyn_connection_sup:start_child(DynSup, sender, [[{spawn_opt, ?DIST_CNTRL_SPAWN_OPTS}]]),
+ {ok, Pid} = tls_dyn_connection_sup:start_child(DynSup, receiver, [Role, Sender, Host, Port, Socket,
+ Opts, User, CbInfo]),
{ok, SslSocket} = ssl_gen_statem:socket_control(?MODULE, Socket, [Pid, Sender], CbModule, Trackers),
ssl_gen_statem:handshake(SslSocket, Timeout)
catch
@@ -241,13 +243,12 @@ getopts(Transport, Socket, Tag) ->
%% raw data from socket, upack records
handle_info({Protocol, _, Data}, StateName,
- #state{static_env = #static_env{data_tag = Protocol},
- connection_env = #connection_env{negotiated_version = Version}} = State0) ->
+ #state{static_env = #static_env{data_tag = Protocol}} = State0) ->
case next_tls_record(Data, StateName, State0) of
{Record, State} ->
next_event(StateName, Record, State);
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, StateName, State0)
+ ssl_gen_statem:handle_own_alert(Alert, StateName, State0)
end;
handle_info({PassiveTag, Socket}, StateName,
#state{static_env = #static_env{socket = Socket,
@@ -321,9 +322,6 @@ handle_info({CloseTag, Socket}, StateName,
%% is called after all data has been deliver.
{next_state, StateName, State#state{protocol_specific = PS#{active_n_toggle => true}}, []}
end;
-handle_info({'EXIT', Sender, Reason}, _,
- #state{protocol_specific = #{sender := Sender}} = State) ->
- {stop, {shutdown, {sender_died, Reason}}, State};
handle_info(Msg, StateName, State) ->
ssl_gen_statem:handle_info(Msg, StateName, State).
@@ -404,26 +402,25 @@ handle_protocol_record(#ssl_tls{type = ?HANDSHAKE, fragment = Data},
end
end
catch throw:#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, StateName, State0)
+ ssl_gen_statem:handle_own_alert(Alert, StateName, State0)
end;
%%% TLS record protocol level change cipher messages
handle_protocol_record(#ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = Data}, StateName, State) ->
{next_state, StateName, State, [{next_event, internal, #change_cipher_spec{type = Data}}]};
%%% TLS record protocol level Alert messages
-handle_protocol_record(#ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName,
- #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
+handle_protocol_record(#ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName,State) ->
try decode_alerts(EncAlerts) of
Alerts = [_|_] ->
handle_alerts(Alerts, {next_state, StateName, State});
[] ->
ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, empty_alert),
- Version, StateName, State);
+ StateName, State);
#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, Version, StateName, State)
+ ssl_gen_statem:handle_own_alert(Alert, StateName, State)
catch
_:_ ->
ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, alert_decode_error),
- Version, StateName, State)
+ StateName, State)
end;
%% Ignore unknown TLS record level protocol messages
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index 05cf1a7339..cb00fa57a3 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -108,7 +108,8 @@ client_hello(_Host, _Port, ConnectionStates,
boolean(), #session{}) ->
{tls_record:tls_version(), ssl:session_id(),
ssl_record:connection_states(), alpn | npn, binary() | undefined, map()}|
- {atom(), atom(), tls_record:tls_version(), map()} | #alert{}.
+ {atom(), atom(), tls_record:tls_version(), map()}.
+ % Otherwise Throws #alert{}
%%
%% Description: Handles a received hello message
%%--------------------------------------------------------------------
@@ -128,7 +129,7 @@ hello(#server_hello{server_version = {Major, Minor},
(M > 3 orelse M =:= 3 andalso N >= 4) andalso %% TLS 1.3 client
(Major =:= 3 andalso Minor < 3 andalso %% Negotiating TLS 1.1 or prior
Down =:= ?RANDOM_OVERRIDE_TLS11) ->
- ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER));
%% TLS 1.2 clients SHOULD also check that the last eight bytes are not
%% equal to the second value if the ServerHello indicates TLS 1.1 or below.
@@ -138,7 +139,7 @@ hello(#server_hello{server_version = {Major, Minor},
when (M =:= 3 andalso N =:= 3) andalso %% TLS 1.2 client
(Major =:= 3 andalso Minor < 3 andalso %% Negotiating TLS 1.1 or prior
Down =:= ?RANDOM_OVERRIDE_TLS11) ->
- ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER));
%% TLS 1.3 - 4.2.1. Supported Versions
@@ -157,9 +158,8 @@ hello(#server_hello{server_version = LegacyVersion,
compression_method = Compression,
session_id = SessionId,
extensions = #{server_hello_selected_version :=
- #server_hello_selected_version{selected_version = Version} = HelloExt}
- },
- #{versions := SupportedVersions,
+ #server_hello_selected_version{selected_version = Version}} = HelloExt},
+ #{versions := SupportedVersions,
ocsp_stapling := Stapling} = SslOpt,
ConnectionStates0, Renegotiation, OldId) ->
%% In TLS 1.3, the TLS server indicates its version using the "supported_versions" extension
@@ -169,7 +169,7 @@ hello(#server_hello{server_version = LegacyVersion,
case LegacyVersion > {3,3} orelse
LegacyVersion =:= {3,3} andalso Version < {3,3} of
true ->
- ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER));
false ->
case tls_record:is_acceptable_version(Version, SupportedVersions) of
true ->
@@ -186,7 +186,7 @@ hello(#server_hello{server_version = LegacyVersion,
ocsp_expect => ocsp_expect(Stapling)}}
end;
false ->
- ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER)
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
end
end;
@@ -205,7 +205,7 @@ hello(#server_hello{server_version = Version,
Compression, HelloExt, SslOpt,
ConnectionStates0, Renegotiation, IsNew);
false ->
- ?ALERT_REC(?FATAL, ?PROTOCOL_VERSION)
+ throw(?ALERT_REC(?FATAL, ?PROTOCOL_VERSION))
end.
@@ -219,7 +219,7 @@ hello(#server_hello{server_version = Version,
{tls_record:tls_version(), {resumed | new, #session{}},
ssl_record:connection_states(), binary() | undefined,
HelloExt::map(), {ssl:hash(), ssl:sign_algo()} |
- undefined} | {atom(), atom()} | {atom(), atom(), tuple()} | #alert{}.
+ undefined} | {atom(), atom()} | {atom(), atom(), tuple()}.
%% TLS 1.2 Server
%% - If "supported_versions" is present (ClientHello):
%% - Select version from "supported_versions" (ignore ClientHello.legacy_version)
@@ -245,8 +245,8 @@ hello(#client_hello{client_version = _ClientVersion,
Version = ssl_handshake:select_supported_version(ClientVersions, Versions),
do_hello(Version, Versions, CipherSuites, Hello, SslOpts, Info, Renegotiation)
catch
- _:_ ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data)
+ error:_ ->
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data))
end;
hello(#client_hello{client_version = ClientVersion,
@@ -259,9 +259,9 @@ hello(#client_hello{client_version = ClientVersion,
catch
error:{case_clause,{asn1, Asn1Reason}} ->
%% ASN-1 decode of certificate somehow failed
- ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {failed_to_decode_own_certificate, Asn1Reason});
- _:_ ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data)
+ throw(?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {failed_to_decode_own_certificate, Asn1Reason}));
+ error:_ ->
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data))
end.
%%--------------------------------------------------------------------
@@ -337,13 +337,13 @@ handle_client_hello(Version,
ClientHashSigns, SupportedHashSigns, OwnCert, Version),
ECCCurve = ssl_handshake:select_curve(Curves, SupportedECCs, ECCOrder),
{Type, #session{cipher_suite = CipherSuite} = Session1}
- = ssl_handshake:select_session(SugesstedId, CipherSuites,
+ = ssl_handshake:select_session(SugesstedId, CipherSuites,
AvailableHashSigns, Compressions,
SessIdTracker, Session0#session{ecc = ECCCurve},
Version, SslOpts, OwnCert),
- case CipherSuite of
+ case CipherSuite of
no_suite ->
- ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_ciphers);
+ throw(?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_ciphers));
_ ->
#{key_exchange := KeyExAlg} = ssl_cipher_format:suite_bin_to_map(CipherSuite),
case ssl_handshake:select_hashsign({ClientHashSigns, ClientSignatureSchemes},
@@ -351,7 +351,7 @@ handle_client_hello(Version,
SupportedHashSigns,
Version) of
#alert{} = Alert ->
- Alert;
+ throw(Alert);
HashSign ->
handle_client_hello_extensions(Version, Type, Random,
CipherSuites, HelloExt,
@@ -361,47 +361,38 @@ handle_client_hello(Version,
end
end;
false ->
- ?ALERT_REC(?FATAL, ?PROTOCOL_VERSION)
+ throw(?ALERT_REC(?FATAL, ?PROTOCOL_VERSION))
end.
handle_client_hello_extensions(Version, Type, Random, CipherSuites,
HelloExt, SslOpts, Session0, ConnectionStates0,
Renegotiation, HashSign) ->
- try ssl_handshake:handle_client_hello_extensions(tls_record, Random, CipherSuites,
- HelloExt, Version, SslOpts,
- Session0, ConnectionStates0,
+ {Session, ConnectionStates, Protocol, ServerHelloExt} =
+ ssl_handshake:handle_client_hello_extensions(tls_record, Random, CipherSuites,
+ HelloExt, Version, SslOpts,
+ Session0, ConnectionStates0,
Renegotiation,
- Session0#session.is_resumable) of
- {Session, ConnectionStates, Protocol, ServerHelloExt} ->
- {Version, {Type, Session}, ConnectionStates, Protocol,
- ServerHelloExt, HashSign}
- catch throw:Alert ->
- Alert
- end.
-
+ Session0#session.is_resumable),
+ {Version, {Type, Session}, ConnectionStates, Protocol, ServerHelloExt, HashSign}.
handle_server_hello_extensions(Version, SessionId, Random, CipherSuite,
- Compression, HelloExt, SslOpt, ConnectionStates0, Renegotiation, IsNew) ->
- try ssl_handshake:handle_server_hello_extensions(tls_record, Random, CipherSuite,
- Compression, HelloExt, Version,
- SslOpt, ConnectionStates0,
- Renegotiation, IsNew) of
- {ConnectionStates, ProtoExt, Protocol, OcspState} ->
- {Version, SessionId, ConnectionStates, ProtoExt, Protocol, OcspState}
- catch throw:Alert ->
- Alert
- end.
-
+ Compression, HelloExt, SslOpt, ConnectionStates0, Renegotiation, IsNew) ->
+ {ConnectionStates, ProtoExt, Protocol, OcspState} =
+ ssl_handshake:handle_server_hello_extensions(tls_record, Random, CipherSuite,
+ Compression, HelloExt, Version,
+ SslOpt, ConnectionStates0,
+ Renegotiation, IsNew),
+ {Version, SessionId, ConnectionStates, ProtoExt, Protocol, OcspState}.
do_hello(undefined, _Versions, _CipherSuites, _Hello, _SslOpts, _Info, _Renegotiation) ->
- ?ALERT_REC(?FATAL, ?PROTOCOL_VERSION);
+ throw(?ALERT_REC(?FATAL, ?PROTOCOL_VERSION));
do_hello(Version, Versions, CipherSuites, Hello, SslOpts, Info, Renegotiation) ->
case ssl_cipher:is_fallback(CipherSuites) of
true ->
Highest = tls_record:highest_protocol_version(Versions),
case tls_record:is_higher(Highest, Version) of
true ->
- ?ALERT_REC(?FATAL, ?INAPPROPRIATE_FALLBACK);
+ throw(?ALERT_REC(?FATAL, ?INAPPROPRIATE_FALLBACK));
false ->
handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
end;
@@ -444,9 +435,7 @@ get_tls_handshake_aux(Version, <<?BYTE(Type), ?UINT24(Length),
ssl_logger:debug(LogLevel, inbound, 'handshake', Handshake),
get_tls_handshake_aux(Version, Rest, Opts, [{Handshake,Raw} | Acc])
catch
- throw:#alert{} = Alert ->
- throw(Alert);
- _:_ ->
+ error:_ ->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, handshake_decode_error))
end;
get_tls_handshake_aux(_Version, Data, _, Acc) ->
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index a551718c38..30341f1598 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -34,8 +34,8 @@
%% Handling of incoming data
-export([get_tls_records/5,
- init_connection_states/2,
- init_connection_states/3]).
+ init_connection_states/3,
+ init_connection_states/4]).
%% Encoding TLS records
-export([encode_handshake/3, encode_alert_record/3,
@@ -66,29 +66,35 @@
%% Handling of incoming data
%%====================================================================
%%--------------------------------------------------------------------
--spec init_connection_states(Role, BeastMitigation) ->
+-spec init_connection_states(Role, Version, BeastMitigation) ->
ssl_record:connection_states() when
Role :: client | server,
+ Version :: tls_version(),
BeastMitigation :: one_n_minus_one | zero_n | disabled.
-%%
+%%
%% Description: Creates a connection_states record with appropriate
%% values for the initial SSL connection setup.
%%--------------------------------------------------------------------
-init_connection_states(Role, BeastMitigation) ->
+init_connection_states(Role, Version, BeastMitigation) ->
MaxEarlyDataSize = ssl_config:get_max_early_data_size(),
- init_connection_states(Role, BeastMitigation, MaxEarlyDataSize).
+ init_connection_states(Role, Version, BeastMitigation, MaxEarlyDataSize).
%%
--spec init_connection_states(Role, BeastMitigation, MaxEarlyDataSize) ->
+-spec init_connection_states(Role, Version, BeastMitigation,
+ MaxEarlyDataSize) ->
ssl_record:connection_states() when
Role :: client | server,
+ Version :: tls_version(),
BeastMitigation :: one_n_minus_one | zero_n | disabled,
MaxEarlyDataSize :: non_neg_integer().
-init_connection_states(Role, BeastMitigation, MaxEarlyDataSize) ->
+init_connection_states(Role, Version, BeastMitigation, MaxEarlyDataSize) ->
ConnectionEnd = ssl_record:record_protocol_role(Role),
Current = initial_connection_state(ConnectionEnd, BeastMitigation, MaxEarlyDataSize),
- Pending = ssl_record:empty_connection_state(ConnectionEnd, BeastMitigation, MaxEarlyDataSize),
+ Pending = ssl_record:empty_connection_state(ConnectionEnd,
+ Version,
+ BeastMitigation,
+ MaxEarlyDataSize),
#{current_read => Current,
pending_read => Pending,
current_write => Current,
@@ -706,9 +712,7 @@ encode_fragments(Type, Version, [Text|Data],
{MajVer, MinVer} = Version,
CipherHeader = <<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Length)>>,
encode_fragments(Type, Version, Data, CS, CompS, CipherS, Seq + 1,
- [[CipherHeader, CipherFragment] | CipherFragments]);
-encode_fragments(_Type, _Version, _Data, CS, _CompS, _CipherS, _Seq, _CipherFragments) ->
- exit({cs, CS}).
+ [[CipherHeader, CipherFragment] | CipherFragments]).
%%--------------------------------------------------------------------
%% 1/n-1 splitting countermeasure Rizzo/Duong-Beast, RC4 ciphers are
diff --git a/lib/ssl/src/tls_record_1_3.erl b/lib/ssl/src/tls_record_1_3.erl
index 3e42e3bf97..92d6491e38 100644
--- a/lib/ssl/src/tls_record_1_3.erl
+++ b/lib/ssl/src/tls_record_1_3.erl
@@ -291,10 +291,7 @@ encode_plain_text(#inner_plaintext{
%% structures are written directly onto the wire.
#tls_cipher_text{opaque_type = Type,
legacy_version = {3,3},
- encoded_record = Data};
-
-encode_plain_text(_, CS) ->
- exit({cs, CS}).
+ encoded_record = Data}.
additional_data(Length) ->
<<?BYTE(?OPAQUE_TYPE), ?BYTE(3), ?BYTE(3),?UINT16(Length)>>.
diff --git a/lib/ssl/src/tls_sender.erl b/lib/ssl/src/tls_sender.erl
index 3d2cafa24c..065e5b9987 100644
--- a/lib/ssl/src/tls_sender.erl
+++ b/lib/ssl/src/tls_sender.erl
@@ -30,15 +30,30 @@
-include("tls_handshake_1_3.hrl").
%% API
--export([start/0, start/1, initialize/2, send_data/2,
- send_post_handshake/2, send_alert/2,
- send_and_ack_alert/2, setopts/2, renegotiate/1, peer_renegotiate/1, downgrade/2,
+-export([start_link/0,
+ start_link/1,
+ initialize/2,
+ send_data/2,
+ send_post_handshake/2,
+ send_alert/2,
+ send_and_ack_alert/2,
+ setopts/2,
+ renegotiate/1,
+ peer_renegotiate/1,
+ downgrade/2,
update_connection_state/3,
- dist_tls_socket/1, dist_handshake_complete/3]).
+ dist_tls_socket/1,
+ dist_handshake_complete/3]).
%% gen_statem callbacks
--export([callback_mode/0, init/1, terminate/3, code_change/4]).
--export([init/3, connection/3, handshake/3, death_row/3]).
+-export([callback_mode/0,
+ init/1,
+ terminate/3,
+ code_change/4]).
+-export([init/3,
+ connection/3,
+ handshake/3,
+ death_row/3]).
-record(static,
{connection_pid,
@@ -65,10 +80,10 @@
%%% API
%%%===================================================================
%%--------------------------------------------------------------------
--spec start() -> {ok, Pid :: pid()} |
+-spec start_link() -> {ok, Pid :: pid()} |
ignore |
{error, Error :: term()}.
--spec start(list()) -> {ok, Pid :: pid()} |
+-spec start_link(list()) -> {ok, Pid :: pid()} |
ignore |
{error, Error :: term()}.
@@ -76,10 +91,10 @@
%% may happen when a socket is busy (busy port) and the
%% same process is sending and receiving
%%--------------------------------------------------------------------
-start() ->
- gen_statem:start(?MODULE, [], []).
-start(SpawnOpts) ->
- gen_statem:start(?MODULE, [], SpawnOpts).
+start_link() ->
+ gen_statem:start_link(?MODULE, [], []).
+start_link(SpawnOpts) ->
+ gen_statem:start_link(?MODULE, [], SpawnOpts).
%%--------------------------------------------------------------------
-spec initialize(pid(), map()) -> ok.
@@ -613,7 +628,9 @@ call(FsmPid, Event) ->
{error, closed};
exit:{normal, _} ->
{error, closed};
- exit:{{shutdown, _},_} ->
+ exit:{shutdown,_} ->
+ {error, closed};
+ exit:{{shutdown, _},_} ->
{error, closed}
end.
diff --git a/lib/ssl/src/tls_server_session_ticket_sup.erl b/lib/ssl/src/tls_server_session_ticket_sup.erl
index bdde94ecea..a515e8bbe0 100644
--- a/lib/ssl/src/tls_server_session_ticket_sup.erl
+++ b/lib/ssl/src/tls_server_session_ticket_sup.erl
@@ -59,18 +59,16 @@ sup_name(dist) ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
-init(_O) ->
- RestartStrategy = simple_one_for_one,
- MaxR = 0,
- MaxT = 3600,
-
- Name = undefined, % As simple_one_for_one is used.
- StartFunc = {tls_server_session_ticket, start_link, []},
- Restart = temporary, % E.g. should not be restarted
- Shutdown = 4000,
- Modules = [tls_server_session_ticket],
- Type = worker,
-
- ChildSpec = {Name, StartFunc, Restart, Shutdown, Type, Modules},
- {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}.
-
+init(_) ->
+ SupFlags = #{strategy => simple_one_for_one,
+ intensity => 0,
+ period => 3600
+ },
+ ChildSpecs = [#{id => undefined,
+ start => {tls_server_session_ticket, start_link, []},
+ restart => transient,
+ shutdown => 4000,
+ modules => [tls_server_session_ticket],
+ type => worker
+ }],
+ {ok, {SupFlags, ChildSpecs}}.
diff --git a/lib/ssl/src/tls_server_sup.erl b/lib/ssl/src/tls_server_sup.erl
index b2f011f221..7f739ed015 100644
--- a/lib/ssl/src/tls_server_sup.erl
+++ b/lib/ssl/src/tls_server_sup.erl
@@ -43,18 +43,19 @@ start_link() ->
%%% Supervisor callback
%%%=========================================================================
-init([]) ->
- ListenTracker = listen_options_tracker_child_spec(),
- SessionTracker = tls_server_session_child_spec(),
- Pre_1_3SessionTracker = ssl_server_session_child_spec(),
- Pre_1_3UpgradeSessionTracker = ssl_upgrade_server_session_child_spec(),
-
- {ok, {{one_for_all, 10, 3600}, [ListenTracker,
- SessionTracker,
- Pre_1_3SessionTracker,
- Pre_1_3UpgradeSessionTracker
- ]}}.
-
+init([]) ->
+ ChildSpecs = [listen_options_tracker_child_spec(),
+ tls_server_session_child_spec(), %% TLS-1.3 Session ticket handling
+ ssl_server_session_child_spec(), %% PRE TLS-1.3 session handling
+ ssl_upgrade_server_session_child_spec() %% PRE TLS-1.3 session handling for upgrade servers
+ ],
+ SupFlags = #{strategy => one_for_all,
+ intensity => 10,
+ period => 3600
+ },
+ {ok, {SupFlags, ChildSpecs}}.
+
+
%%--------------------------------------------------------------------
%%% Internal functions
@@ -63,37 +64,37 @@ init([]) ->
%% Handles emulated options so that they inherited by the accept
%% socket, even when setopts is performed on the listen socket
listen_options_tracker_child_spec() ->
- Name = tls_socket,
- StartFunc = {ssl_listen_tracker_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [ssl_listen_tracker_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => ssl_listen_tracker_sup,
+ start => {ssl_listen_tracker_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [ssl_listen_tracker_sup],
+ type => supervisor
+ }.
tls_server_session_child_spec() ->
- Name = tls_server_session_ticket,
- StartFunc = {tls_server_session_ticket_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [tls_server_session_ticket_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => tls_server_session_ticket,
+ start => {tls_server_session_ticket_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [tls_server_session_ticket_sup],
+ type => supervisor
+ }.
ssl_server_session_child_spec() ->
- Name = ssl_server_session_cache_sup,
- StartFunc = {ssl_server_session_cache_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [ssl_server_session_cache_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => ssl_server_session_cache_sup,
+ start => {ssl_server_session_cache_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [ssl_server_session_cache_sup],
+ type => supervisor
+ }.
ssl_upgrade_server_session_child_spec() ->
- Name = ssl_upgrade_server_session_cache_sup,
- StartFunc = {ssl_upgrade_server_session_cache_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [ssl_upgrade_server_session_cache_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => ssl_upgrade_server_session_cache_sup,
+ start => {ssl_upgrade_server_session_cache_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [ssl_upgrade_server_session_cache_sup],
+ type => supervisor
+ }.
diff --git a/lib/ssl/src/tls_socket.erl b/lib/ssl/src/tls_socket.erl
index 0a583dbb1d..12d59c6b4c 100644
--- a/lib/ssl/src/tls_socket.erl
+++ b/lib/ssl/src/tls_socket.erl
@@ -105,15 +105,7 @@ accept(ListenSocket, #config{transport_info = {Transport,_,_,_,_} = CbInfo,
Tracker = proplists:get_value(option_tracker, Trackers),
{ok, EmOpts} = get_emulated_opts(Tracker),
{ok, Port} = tls_socket:port(Transport, Socket),
- {ok, Sender} = tls_sender:start(),
- ConnArgs = [server, Sender, "localhost", Port, Socket,
- {SslOpts, emulated_socket_options(EmOpts, #socket_options{}), Trackers}, self(), CbInfo],
- case tls_connection_sup:start_child(ConnArgs) of
- {ok, Pid} ->
- ssl_gen_statem:socket_control(ConnectionCb, Socket, [Pid, Sender], Transport, Trackers);
- {error, Reason} ->
- {error, Reason}
- end;
+ start_tls_server_connection(SslOpts, ConnectionCb, Transport, Port, Socket, EmOpts, Trackers, CbInfo);
{error, Reason} ->
{error, Reason}
end.
@@ -399,6 +391,19 @@ code_change(_OldVsn, State, _Extra) ->
call(Pid, Msg) ->
gen_server:call(Pid, Msg, infinity).
+start_tls_server_connection(SslOpts, ConnectionCb, Transport, Port, Socket, EmOpts, Trackers, CbInfo) ->
+ try
+ {ok, DynSup} = tls_connection_sup:start_child([]),
+ {ok, Sender} = tls_dyn_connection_sup:start_child(DynSup, sender, []),
+ ConnArgs = [server, Sender, "localhost", Port, Socket,
+ {SslOpts, emulated_socket_options(EmOpts, #socket_options{}), Trackers}, self(), CbInfo],
+ {ok, Pid} = tls_dyn_connection_sup:start_child(DynSup, receiver, ConnArgs),
+ ssl_gen_statem:socket_control(ConnectionCb, Socket, [Pid, Sender], Transport, Trackers)
+ catch
+ error:{badmatch, {error, _} = Error} ->
+ Error
+ end.
+
split_options(Opts) ->
split_options(Opts, emulated_options(), [], []).
split_options([], _, SocketOpts, EmuOpts) ->
diff --git a/lib/ssl/src/tls_sup.erl b/lib/ssl/src/tls_sup.erl
index a425ae31e2..cafc563943 100644
--- a/lib/ssl/src/tls_sup.erl
+++ b/lib/ssl/src/tls_sup.erl
@@ -43,14 +43,13 @@ start_link() ->
%%% Supervisor callback
%%%=========================================================================
-init([]) ->
-
- TLSConnetionSup = tls_connection_child_spec(),
- ServerInstanceSup = server_instance_child_spec(),
-
- {ok, {{one_for_one, 10, 3600}, [TLSConnetionSup,
- ServerInstanceSup
- ]}}.
+init([]) ->
+ ChildSpecs = [tls_connection_child_spec(), server_instance_child_spec()],
+ SupFlags = #{strategy => one_for_one,
+ intensity => 10,
+ period => 3600
+ },
+ {ok, {SupFlags, ChildSpecs}}.
%%--------------------------------------------------------------------
@@ -58,19 +57,19 @@ init([]) ->
%%--------------------------------------------------------------------
tls_connection_child_spec() ->
- Name = tls_connection,
- StartFunc = {tls_connection_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [tls_connection_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => tls_connection_sup,
+ start => {tls_connection_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [tls_connection_sup],
+ type => supervisor
+ }.
server_instance_child_spec() ->
- Name = tls_server_sup,
- StartFunc = {tls_server_sup, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [tls_server_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+ #{id => tls_server_sup,
+ start => {tls_server_sup, start_link, []},
+ restart => permanent,
+ shutdown => 4000,
+ modules => [tls_server_sup],
+ type => supervisor
+ }.
diff --git a/lib/ssl/test/dtls_api_SUITE.erl b/lib/ssl/test/dtls_api_SUITE.erl
index 572702af02..4117bec12e 100644
--- a/lib/ssl/test/dtls_api_SUITE.erl
+++ b/lib/ssl/test/dtls_api_SUITE.erl
@@ -51,9 +51,12 @@
dtls_listen_two_sockets_5/0,
dtls_listen_two_sockets_5/1,
dtls_listen_two_sockets_6/0,
- dtls_listen_two_sockets_6/1
+ dtls_listen_two_sockets_6/1,
+ client_restarts/0, client_restarts/1
]).
+-include_lib("ssl/src/ssl_internal.hrl").
+
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
@@ -80,7 +83,8 @@ api_tests() ->
dtls_listen_two_sockets_3,
dtls_listen_two_sockets_4,
dtls_listen_two_sockets_5,
- dtls_listen_two_sockets_6
+ dtls_listen_two_sockets_6,
+ client_restarts
].
init_per_suite(Config0) ->
@@ -300,7 +304,6 @@ dtls_listen_two_sockets_6(_Config) when is_list(_Config) ->
ssl:close(S1),
ok.
-
replay_window() ->
[{doc, "Whitebox test of replay window"}].
replay_window(_Config) ->
@@ -347,6 +350,65 @@ bits_to_list(Bits, I, Acc) ->
0 -> bits_to_list(Bits bsr 1, I+1, Acc)
end.
+client_restarts() ->
+ [{doc, "Test re-connection "}].
+
+client_restarts(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client0 = ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {from, self()},
+ {options, [{reuse_sessions, save} | ClientOpts]}]),
+ ReConnect = %% Whitebox re-connect test
+ fun({sslsocket, {gen_udp,_,dtls_gen_connection}, [Pid]} = Socket, ssl) ->
+ ct:log("~p Client Socket: ~p ~n", [self(), Socket]),
+ {ok, {{Adress,CPort},UDPSocket}=IntSocket} = gen_statem:call(Pid, {downgrade, self()}),
+ true = is_port(UDPSocket),
+ ct:log("Info: ~p~n", [inet:info(UDPSocket)]),
+
+ {ok, #config{transport_info = CbInfo, connection_cb = ConnectionCb,
+ ssl = SslOpts0}} = ssl:handle_options(ClientOpts, client, Adress),
+ SslOpts = {SslOpts0, #socket_options{}, undefined},
+
+ ct:sleep(250),
+ ct:log("Client second connect: ~p ~p~n", [Socket, CbInfo]),
+ Res = ssl_gen_statem:connect(ConnectionCb, Adress, CPort, IntSocket, SslOpts, self(), CbInfo, infinity),
+ {Res, Pid}
+ end,
+
+ Client0 ! {apply, self(), ReConnect},
+ receive
+ {apply_res, {Res, _Prev}} ->
+ ct:log("Apply res: ~p~n", [Res]),
+ ok;
+ Msg ->
+ ct:log("Unhandled: ~p~n", [Msg]),
+ ct:fail({wrong_msg, Msg})
+ end,
+
+ receive
+ Msg2 ->
+ ct:log("Unhandled: ~p~n", [Msg2]),
+ ct:fail({wrong_msg, Msg2})
+ after 200 ->
+ ct:log("Nothing received~n", [])
+ end,
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client0),
+
+ ok.
+
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/openssl_client_cert_SUITE.erl b/lib/ssl/test/openssl_client_cert_SUITE.erl
index ad00f2da1f..263628c3c4 100644
--- a/lib/ssl/test/openssl_client_cert_SUITE.erl
+++ b/lib/ssl/test/openssl_client_cert_SUITE.erl
@@ -82,7 +82,7 @@ groups() ->
[
{openssl_client, [], protocol_groups()},
{'tlsv1.3', [], tls_1_3_protocol_groups()},
- {'tlsv1.2', [], pre_tls_1_3_protocol_groups()},
+ {'tlsv1.2', [], pre_tls_1_3_protocol_groups() ++ [{group, rsa_pss_rsae}, {group, rsa_pss_pss}]},
{'tlsv1.1', [], pre_tls_1_3_protocol_groups()},
{'tlsv1', [], pre_tls_1_3_protocol_groups()},
{'dtlsv1.2', [], pre_tls_1_3_protocol_groups()},
@@ -92,8 +92,10 @@ groups() ->
{dsa, [], all_version_tests()},
{rsa_1_3, [], all_version_tests() ++ tls_1_3_tests() ++ [unsupported_sign_algo_client_auth,
unsupported_sign_algo_cert_client_auth]},
- {rsa_pss_rsae, [], all_version_tests() ++ tls_1_3_tests()},
- {rsa_pss_pss, [], all_version_tests() ++ tls_1_3_tests()},
+ {rsa_pss_rsae, [], all_version_tests()},
+ {rsa_pss_pss, [], all_version_tests()},
+ {rsa_pss_rsae_1_3, [], all_version_tests() ++ tls_1_3_tests()},
+ {rsa_pss_pss_1_3, [], all_version_tests() ++ tls_1_3_tests()},
{ecdsa_1_3, [], all_version_tests() ++ tls_1_3_tests()},
{eddsa_1_3, [], all_version_tests() ++ tls_1_3_tests()}
].
@@ -122,8 +124,8 @@ pre_tls_1_3_protocol_groups() ->
tls_1_3_protocol_groups() ->
[{group, rsa_1_3},
- {group, rsa_pss_rsae},
- {group, rsa_pss_pss},
+ {group, rsa_pss_rsae_1_3},
+ {group, rsa_pss_pss_1_3},
{group, ecdsa_1_3},
{group, eddsa_1_3}
].
@@ -198,23 +200,26 @@ init_per_group(Group, Config0) when Group == rsa;
[] ->
{skip, {no_sup, Group, Version}}
end;
-init_per_group(Alg, Config) when Alg == rsa_pss_rsae;
- Alg == rsa_pss_pss ->
+init_per_group(Alg, Config) when
+ Alg == rsa_pss_rsae;
+ Alg == rsa_pss_pss;
+ Alg == rsa_pss_rsae_1_3;
+ Alg == rsa_pss_pss_1_3 ->
Supports = crypto:supports(),
RSAOpts = proplists:get_value(rsa_opts, Supports),
case lists:member(rsa_pkcs1_pss_padding, RSAOpts)
andalso lists:member(rsa_pss_saltlen, RSAOpts)
andalso lists:member(rsa_mgf1_md, RSAOpts)
- andalso ssl_test_lib:is_sane_oppenssl_pss(Alg)
+ andalso ssl_test_lib:is_sane_oppenssl_pss(rsa_alg(Alg))
of
true ->
#{client_config := COpts,
- server_config := SOpts} = ssl_test_lib:make_rsa_pss_pem(Alg, [], Config, ""),
- [{cert_key_alg, Alg} |
+ server_config := SOpts} = ssl_test_lib:make_rsa_pss_pem(rsa_alg(Alg), [], Config, ""),
+ [{cert_key_alg, rsa_alg(Alg)} |
lists:delete(cert_key_alg,
- [{client_cert_opts, COpts},
- {server_cert_opts, SOpts} |
+ [{client_cert_opts, openssl_sig_algs(Alg) ++ COpts},
+ {server_cert_opts, sig_algs(rsa_alg(Alg)) ++ SOpts} |
lists:delete(server_cert_opts,
lists:delete(client_cert_opts, Config))])];
false ->
@@ -433,3 +438,28 @@ hello_retry_client_auth_empty_cert_rejected() ->
ssl_cert_tests:hello_retry_client_auth_empty_cert_rejected().
hello_retry_client_auth_empty_cert_rejected(Config) ->
ssl_cert_tests:hello_retry_client_auth_empty_cert_rejected(Config).
+
+rsa_alg(rsa_pss_rsae_1_3) ->
+ rsa_pss_rsae;
+rsa_alg(rsa_pss_pss_1_3) ->
+ rsa_pss_pss;
+rsa_alg(Atom) ->
+ Atom.
+
+sig_algs(rsa_pss_pss) ->
+ [{signature_algs, [rsa_pss_pss_sha512,
+ rsa_pss_pss_sha384,
+ rsa_pss_pss_sha256]}];
+sig_algs(rsa_pss_rsae) ->
+ [{signature_algs,[rsa_pss_rsae_sha512,
+ rsa_pss_rsae_sha384,
+ rsa_pss_rsae_sha256]}].
+
+openssl_sig_algs(rsa_pss_pss) ->
+ [{sigalgs, "rsa_pss_pss_sha256"}];
+openssl_sig_algs(rsa_pss_rsae) ->
+ [{sigalgs,"rsa_pss_rsae_sha256"}];
+openssl_sig_algs(rsa_pss_pss_1_3) ->
+ [{sigalgs, "rsa_pss_rsae_sha512:rsa_pss_rsae_sha384:rsa_pss_pss_sha256"}];
+openssl_sig_algs(rsa_pss_rsae_1_3) ->
+ [{sigalgs,"rsa_pss_rsae_sha512:rsa_pss_rsae_sha384:rsa_pss_rsae_sha256"}].
diff --git a/lib/ssl/test/property_test/ssl_eqc_cipher_format.erl b/lib/ssl/test/property_test/ssl_eqc_cipher_format.erl
index cf6ed755f7..11330b111b 100644
--- a/lib/ssl/test/property_test/ssl_eqc_cipher_format.erl
+++ b/lib/ssl/test/property_test/ssl_eqc_cipher_format.erl
@@ -51,6 +51,8 @@
-endif.
-endif.
+-include_lib("public_key/include/public_key.hrl").
+
-define('TLS_v1.3', 'tlsv1.3').
-define('TLS_v1.2', 'tlsv1.2').
-define('TLS_v1.1', 'tlsv1.1').
@@ -105,6 +107,11 @@ prop_tls_anon_cipher_suite_openssl_name() ->
end
).
+prop_tls_signature_algs() ->
+ ?FORALL(SigAlg, ?LET(SigAlg, sig_alg(), SigAlg),
+ true = lists:member(ssl_cipher:signature_algorithm_to_scheme(SigAlg), sig_schemes())
+ ).
+
%%--------------------------------------------------------------------
%% Generators -----------------------------------------------
%%--------------------------------------------------------------------
@@ -272,3 +279,55 @@ openssl_legacy_names() ->
"SRP-AES-128-CBC-SHA",
"SRP-AES-256-CBC-SHA"
].
+
+
+sig_alg() ->
+ oneof([#'SignatureAlgorithm'{algorithm = ?'id-RSASSA-PSS',
+ parameters = #'RSASSA-PSS-params'{
+ maskGenAlgorithm =
+ #'MaskGenAlgorithm'{algorithm = ?'id-mgf1',
+ parameters = #'HashAlgorithm'{algorithm = ?'id-sha256'}}}},
+ #'SignatureAlgorithm'{algorithm = ?'id-RSASSA-PSS',
+ parameters = #'RSASSA-PSS-params'{
+ maskGenAlgorithm =
+ #'MaskGenAlgorithm'{algorithm = ?'id-mgf1',
+ parameters = #'HashAlgorithm'{algorithm = ?'id-sha384'}}}},
+
+ #'SignatureAlgorithm'{algorithm = ?'id-RSASSA-PSS',
+ parameters = #'RSASSA-PSS-params'{
+ maskGenAlgorithm =
+ #'MaskGenAlgorithm'{algorithm = ?'id-mgf1',
+ parameters = #'HashAlgorithm'{algorithm = ?'id-sha512'}}}},
+ #'SignatureAlgorithm'{algorithm = ?sha256WithRSAEncryption},
+ #'SignatureAlgorithm'{algorithm = ?sha384WithRSAEncryption},
+ #'SignatureAlgorithm'{algorithm = ?sha512WithRSAEncryption},
+ #'SignatureAlgorithm'{algorithm = ?'ecdsa-with-SHA256'},
+ #'SignatureAlgorithm'{algorithm = ?'ecdsa-with-SHA384'},
+ #'SignatureAlgorithm'{algorithm = ?'ecdsa-with-SHA512'},
+ #'SignatureAlgorithm'{algorithm = ?'sha-1WithRSAEncryption'},
+ #'SignatureAlgorithm'{algorithm = ?'ecdsa-with-SHA1'},
+ #'SignatureAlgorithm'{algorithm = ?'id-Ed25519'},
+ #'SignatureAlgorithm'{algorithm = ?'id-Ed448'},
+ #'SignatureAlgorithm'{algorithm = ?'rsaEncryption',
+ parameters = 'NULL'},
+ #'SignatureAlgorithm'{algorithm = ?'rsaEncryption'},
+ #'SignatureAlgorithm'{algorithm = ?'id-RSASSA-PSS'}]).
+
+sig_schemes() ->
+ [rsa_pss_pss_sha256,
+ rsa_pss_pss_sha384,
+ rsa_pss_pss_sha512,
+ rsa_pkcs1_sha256,
+ rsa_pkcs1_sha384,
+ rsa_pkcs1_sha512,
+ ecdsa_secp256r1_sha256,
+ ecdsa_secp384r1_sha384,
+ ecdsa_secp521r1_sha512,
+ rsa_pkcs1_sha1,
+ rsa_pkcs1_sha1,
+ ecdsa_sha1,
+ eddsa_ed25519,
+ eddsa_ed448,
+ rsa_pkcs1_sha1,
+ rsa_pss_rsae,
+ rsa_pss_pss].
diff --git a/lib/ssl/test/ssl_api_SUITE.erl b/lib/ssl/test/ssl_api_SUITE.erl
index ec831cfb90..22b199aa70 100644
--- a/lib/ssl/test/ssl_api_SUITE.erl
+++ b/lib/ssl/test/ssl_api_SUITE.erl
@@ -171,7 +171,13 @@
invalid_options_tls13/0,
invalid_options_tls13/1,
cookie/0,
- cookie/1
+ cookie/1,
+ warn_verify_none/0,
+ warn_verify_none/1,
+ suppress_warn_verify_none/0,
+ suppress_warn_verify_none/1,
+ check_random_nonce/0,
+ check_random_nonce/1
]).
%% Apply export
@@ -192,6 +198,8 @@
tls_close/1,
no_recv_no_active/1,
ssl_getstat/1,
+ log/2,
+ get_connection_information/3,
%%TODO Keep?
run_error_server/1,
run_error_server_close/1,
@@ -292,7 +300,10 @@ gen_api_tests() ->
invalid_options,
cb_info,
log_alert,
- getstat
+ getstat,
+ warn_verify_none,
+ suppress_warn_verify_none,
+ check_random_nonce
].
handshake_paus_tests() ->
@@ -405,6 +416,10 @@ init_per_testcase(conf_signature_algs, Config) ->
sha ->
{skip, "Tests needs certs with sha256"}
end;
+init_per_testcase(check_random_nonce, Config) ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 20}),
+ Config;
init_per_testcase(_TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 10}),
@@ -2485,7 +2500,128 @@ cookie(Config) when is_list(Config) ->
cookie_extension(Config, true),
cookie_extension(Config, false).
+warn_verify_none() ->
+ [{doc, "Test that verify_none default generates warning."}].
+warn_verify_none(Config) when is_list(Config)->
+ ok = logger:add_handler(?MODULE,?MODULE,#{config=>self()}),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, ServerOpts},
+ {mfa, {ssl_test_lib, no_result, []}}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {from, self()},
+ {host, Hostname},
+ {options, ClientOpts},
+ {mfa, {ssl_test_lib, no_result, []}}]),
+ receive
+ warning_generated ->
+ ok = logger:remove_handler(?MODULE)
+ after 500 ->
+ ok = logger:remove_handler(?MODULE),
+ ct:fail(no_warning)
+ end,
+ ssl_test_lib:close(Client),
+ ssl_test_lib:close(Server).
+
+suppress_warn_verify_none() ->
+ [{doc, "Test that explicit verify_none supresses warning."}].
+suppress_warn_verify_none(Config) when is_list(Config)->
+ ok = logger:add_handler(?MODULE,?MODULE,#{config=>self()}),
+
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, ServerOpts},
+ {mfa, {ssl_test_lib, no_result, []}}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {from, self()},
+ {host, Hostname},
+ {options, [{verify, verify_none} | ClientOpts]},
+ {mfa, {ssl_test_lib, no_result, []}}]),
+ receive
+ warning_generated ->
+ ok = logger:remove_handler(?MODULE),
+ ct:fail(warning)
+ after 500 ->
+ ok = logger:remove_handler(?MODULE)
+ end,
+ ssl_test_lib:close(Client),
+ ssl_test_lib:close(Server).
+
+%%--------------------------------------------------------------------
+check_random_nonce() ->
+ [{doc,"Test random nonce - expecting 32B random for TLS1.3 and 4B UTC "
+ "epoch with 28B random for older version"}].
+check_random_nonce(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ N = 10,
+ F = fun (Id) -> establish_connection(Id,ServerNode, ServerOpts,
+ ClientNode, ClientOpts,
+ Hostname)
+ end,
+ ConnectionPairs = [F(Id) || Id <- lists:seq(1, N)],
+ Randoms = lists:flatten([ssl_test_lib:get_result([Server, Client]) ||
+ {Server, Client} <- ConnectionPairs]),
+ Deltas = [abs(FourBytes - SecsSince) ||
+ {_Id, {_, <<FourBytes:32, _/binary>>}, SecsSince} <- Randoms],
+ MeanDelta = lists:sum(Deltas) div N,
+ case ?config(version, Config) of
+ 'tlsv1.3' ->
+ %% 4B "random" expected since TLS1.3
+ RndThreshold = 10000,
+ true = MeanDelta > RndThreshold;
+ _ ->
+ %% 4 epoch based bytes expected pre TLS1.3
+ EpochThreshold = 10,
+ true = MeanDelta < EpochThreshold
+ end,
+ [begin
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client)
+ end || {Server, Client} <- ConnectionPairs].
+
+establish_connection(Id, ServerNode, ServerOpts, ClientNode, ClientOpts, Hostname) ->
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, get_connection_information,
+ [Id, server_random]}},
+ {options, [{verify, verify_peer} | ServerOpts]}]),
+
+ ListenPort = ssl_test_lib:inet_port(Server),
+ Client =
+ ssl_test_lib:start_client([{node, ClientNode}, {port, ListenPort},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, get_connection_information,
+ [Id, client_random]}},
+ {options, [{verify, verify_peer} |ClientOpts]}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+ {Server, Client}.
+
%%% Checker functions
+get_connection_information(Socket, ConnectionId, InfoType) ->
+ {ok, [ConnectionInfo]} = ssl:connection_information(Socket, [InfoType]),
+ {ConnectionId, ConnectionInfo, secs_since_1970()}.
+secs_since_1970() ->
+ calendar:datetime_to_gregorian_seconds(
+ calendar:universal_time()) - 62167219200.
+
connection_information_result(Socket) ->
{ok, Info = [_ | _]} = ssl:connection_information(Socket),
case length(Info) > 3 of
@@ -2909,3 +3045,8 @@ ssl_getstat(Socket) ->
_ ->
ok
end.
+
+log(#{msg:={report,Report}},#{config:=Pid}) ->
+ Pid ! warning_generated;
+log(_,_) ->
+ ok.
diff --git a/lib/ssl/test/ssl_cert_SUITE.erl b/lib/ssl/test/ssl_cert_SUITE.erl
index 42c44e4855..1eef4a48be 100644
--- a/lib/ssl/test/ssl_cert_SUITE.erl
+++ b/lib/ssl/test/ssl_cert_SUITE.erl
@@ -146,11 +146,11 @@ groups() ->
{'tlsv1', [], ssl_protocol_groups()},
{'dtlsv1.2', [], tls_1_2_protocol_groups()},
{'dtlsv1', [], ssl_protocol_groups()},
- {rsa, [], all_version_tests() ++ rsa_tests() ++ pre_tls_1_3_rsa_tests()},
+ {rsa, [], all_version_tests() ++ rsa_tests() ++ pre_tls_1_3_rsa_tests() ++ [client_auth_seelfsigned_peer]},
{ecdsa, [], all_version_tests()},
{dsa, [], all_version_tests()},
{rsa_1_3, [], all_version_tests() ++ rsa_tests() ++
- tls_1_3_tests() ++ tls_1_3_rsa_tests() ++ [basic_rsa_1024]},
+ tls_1_3_tests() ++ tls_1_3_rsa_tests() ++ [client_auth_seelfsigned_peer, basic_rsa_1024]},
{rsa_pss_rsae, [], all_version_tests() ++ tls_1_2_rsa_tests()},
{rsa_pss_rsae_1_3, [], all_version_tests() ++ rsa_tests() ++ tls_1_3_tests() ++ tls_1_3_rsa_tests()},
{rsa_pss_pss, [], all_version_tests()},
@@ -226,7 +226,6 @@ all_version_tests() ->
client_auth_do_not_allow_partial_chain,
client_auth_partial_chain_fun_fail,
client_auth_sni,
- client_auth_seelfsigned_peer,
missing_root_cert_no_auth,
missing_root_cert_auth,
missing_root_cert_auth_user_verify_fun_accept,
@@ -296,37 +295,9 @@ do_init_per_group(Alg, Config) when Alg == rsa_pss_rsae;
true ->
#{client_config := COpts,
server_config := SOpts} = ssl_test_lib:make_rsa_pss_pem(rsa_alg(Alg), [], Config, ""),
- [{cert_key_alg, rsa_alg(Alg)},
- {extra_client, [{signature_algs, [rsa_pss_pss_sha512,
- rsa_pss_pss_sha384,
- rsa_pss_pss_sha256,
- rsa_pss_rsae_sha512,
- rsa_pss_rsae_sha384,
- rsa_pss_rsae_sha256,
- rsa_pkcs1_sha512,
- rsa_pkcs1_sha384,
- rsa_pkcs1_sha256,
- rsa_pkcs1_sha1,
- {sha512, rsa},
- {sha384, rsa},
- {sha256, rsa},
- {sha224, rsa}
- ]}]},
- {extra_server, [{signature_algs, [rsa_pss_pss_sha512,
- rsa_pss_pss_sha384,
- rsa_pss_pss_sha256,
- rsa_pss_rsae_sha512,
- rsa_pss_rsae_sha384,
- rsa_pss_rsae_sha256,
- {sha512, ecdsa},
- {sha512, rsa},
- {sha384, ecdsa},
- {sha384, rsa},
- {sha256, ecdsa},
- {sha256, rsa},
- {sha224, ecdsa},
- {sha224, rsa}
- ]}]} |
+ [{cert_key_alg, Alg},
+ {extra_client, sig_algs(Alg)},
+ {extra_server, sig_algs(Alg)} |
lists:delete(cert_key_alg,
[{client_cert_opts, COpts},
{server_cert_opts, SOpts} |
@@ -1317,3 +1288,12 @@ chain_and_root(Config) ->
{ok, ExtractedCAs} = ssl_pkix_db:extract_trusted_certs({der, proplists:get_value(cacerts, Config)}),
{ok, Root, Chain} = ssl_certificate:certificate_chain(OwnCert, ets:new(foo, []), ExtractedCAs, [], encoded),
{Chain, Root}.
+
+sig_algs(rsa_pss_pss) ->
+ [{signature_algs, [rsa_pss_pss_sha512,
+ rsa_pss_pss_sha384,
+ rsa_pss_pss_sha256]}];
+sig_algs(rsa_pss_rsae) ->
+ [{signature_algs, [rsa_pss_rsae_sha512,
+ rsa_pss_rsae_sha384,
+ rsa_pss_rsae_sha256]}].
diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl
index 67be91196f..5c8a8d9138 100644
--- a/lib/ssl/test/ssl_dist_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_SUITE.erl
@@ -58,7 +58,9 @@
verify_fun_fail/0,
verify_fun_fail/1,
verify_fun_pass/0,
- verify_fun_pass/1
+ verify_fun_pass/1,
+ epmd_module/0,
+ epmd_module/1
]).
%% Apply export
@@ -75,6 +77,12 @@
verify_pass_always/3,
verify_fail_always/3]).
+%% Epmd module export
+-export([start_link/0,
+ register_node/2,
+ register_node/3,
+ port_please/2,
+ address_please/3]).
-define(DEFAULT_TIMETRAP_SECS, 240).
-define(AWAIT_SSL_NODE_UP_TIMEOUT, 30000).
@@ -102,7 +110,8 @@ all() ->
connect_options,
use_interface,
verify_fun_fail,
- verify_fun_pass
+ verify_fun_pass,
+ epmd_module
].
init_per_suite(Config0) ->
@@ -382,6 +391,53 @@ verify_fun_pass(Config) when is_list(Config) ->
gen_dist_test(verify_fun_pass_test, [{tls_verify_opts, AddTLSVerifyOpts} | Config]).
%%--------------------------------------------------------------------
+epmd_module() ->
+ [{doc,"Test that custom epmd_modules work"}].
+epmd_module(Config0) when is_list(Config0) ->
+ Config = [{hostname, "dummy"} | Config0],
+ NH1 = start_ssl_node(Config, "-epmd_module " ++ atom_to_list(?MODULE)),
+ NH2 = start_ssl_node(Config, "-epmd_module " ++ atom_to_list(?MODULE)),
+
+ {ok, Port1} = apply_on_ssl_node(NH1, fun() -> application:get_env(kernel, dist_listen_port) end),
+ {ok, Port2} = apply_on_ssl_node(NH2, fun() -> application:get_env(kernel, dist_listen_port) end),
+ apply_on_ssl_node(NH1, fun() -> application:set_env(kernel, dist_connect_port, Port2) end),
+ apply_on_ssl_node(NH2, fun() -> application:set_env(kernel, dist_connect_port, Port1) end),
+
+ try
+ basic_test(NH1, NH2, Config)
+ catch
+ _:Reason ->
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ ct:fail(Reason)
+ end,
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ success(Config).
+
+start_link() ->
+ ignore.
+
+register_node(Name, Port) ->
+ register_node(Name, Port, inet_tcp).
+register_node(_Name, Port, _Driver) ->
+ %% Save the port number we're listening on.
+ application:set_env(kernel, dist_listen_port, Port),
+ Creation = rand:uniform(3),
+ {ok, Creation}.
+
+port_please(_Name, _Ip) ->
+ {ok, Port} = application:get_env(kernel, dist_connect_port),
+ {port, Port, 5}.
+
+address_please(_Name, "dummy", AddressFamily) ->
+ %% Use localhost.
+ {ok,Host} = inet:gethostname(),
+ inet:getaddr(Host, AddressFamily);
+address_please(_, _, _) ->
+ {error, nxdomain}.
+
+%%--------------------------------------------------------------------
%%% Internal functions -----------------------------------------------
%%--------------------------------------------------------------------
gen_dist_test(Test, Config) ->
@@ -653,11 +709,17 @@ start_ssl_node(Config, XArgs) ->
mk_node_name(Config) ->
N = erlang:unique_integer([positive]),
Case = proplists:get_value(testcase, Config),
+ Hostname =
+ case proplists:get_value(hostname, Config) of
+ undefined -> "";
+ Host -> "@" ++ Host
+ end,
atom_to_list(?MODULE)
++ "_"
++ atom_to_list(Case)
++ "_"
- ++ integer_to_list(N).
+ ++ integer_to_list(N) ++ Hostname.
+
setup_certs(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
diff --git a/lib/ssl/test/ssl_dist_test_lib.erl b/lib/ssl/test/ssl_dist_test_lib.erl
index e85eddaf08..d0fda480b2 100644
--- a/lib/ssl/test/ssl_dist_test_lib.erl
+++ b/lib/ssl/test/ssl_dist_test_lib.erl
@@ -73,7 +73,9 @@ apply_on_ssl_node(Node, Ref, Msg) ->
stop_ssl_node(#node_handle{connection_handler = Handler,
socket = Socket,
- name = Name}) ->
+ name = Name,
+ logfile = LogPath,
+ dumpfile = DumpPath}) ->
test_server:format("Trying to stop ssl node ~s.~n", [Name]),
Mon = erlang:monitor(process, Handler),
unlink(Handler),
@@ -93,13 +95,24 @@ stop_ssl_node(#node_handle{connection_handler = Handler,
Error ->
erlang:demonitor(Mon, [flush]),
ct:pal("stop_ssl_node/1 ~s Warning ~p ~n", [Name,Error])
- end.
+ end,
+ case file:read_file(LogPath) of
+ {ok, Binary} ->
+ ct:pal("LogPath(~pB) = ~p~n~s", [filelib:file_size(LogPath), LogPath,
+ Binary]);
+ _ ->
+ ok
+ end,
+ ct:pal("DumpPath(~pB) = ~p~n", [filelib:file_size(DumpPath), DumpPath]).
start_ssl_node(Name, Args) ->
{ok, LSock} = gen_tcp:listen(0,
[binary, {packet, 4}, {active, false}]),
{ok, ListenPort} = inet:port(LSock),
- CmdLine = mk_node_cmdline(ListenPort, Name, Args),
+ {ok, Pwd} = file:get_cwd(),
+ LogFilePath = filename:join([Pwd, "error_log." ++ Name]),
+ DumpFilePath = filename:join([Pwd, "erl_crash_dump." ++ Name]),
+ CmdLine = mk_node_cmdline(ListenPort, Name, Args, LogFilePath, DumpFilePath),
test_server:format("Attempting to start ssl node ~ts: ~ts~n", [Name, CmdLine]),
case open_port({spawn, CmdLine}, []) of
Port when is_port(Port) ->
@@ -108,8 +121,8 @@ start_ssl_node(Name, Args) ->
case await_ssl_node_up(Name, LSock) of
#node_handle{} = NodeHandle ->
test_server:format("Ssl node ~s started.~n", [Name]),
- NodeName = list_to_atom(Name ++ "@" ++ host_name()),
- NodeHandle#node_handle{nodename = NodeName};
+ NodeHandle#node_handle{logfile = LogFilePath,
+ dumpfile = DumpFilePath};
Error ->
exit({failed_to_start_node, Name, Error})
end;
@@ -123,7 +136,7 @@ host_name() ->
%% atom_to_list(node())),
Host.
-mk_node_cmdline(ListenPort, Name, Args) ->
+mk_node_cmdline(ListenPort, Name, Args, LogPath, DumpPath) ->
Static = "-detached -noinput",
Pa = filename:dirname(code:which(?MODULE)),
Prog = case catch init:get_argument(progname) of
@@ -134,7 +147,6 @@ mk_node_cmdline(ListenPort, Name, Args) ->
false -> "-sname ";
_ -> "-name "
end,
- {ok, Pwd} = file:get_cwd(),
"\"" ++ Prog ++ "\" "
++ Static ++ " "
++ NameSw ++ " " ++ Name ++ " "
@@ -145,10 +157,10 @@ mk_node_cmdline(ListenPort, Name, Args) ->
++ host_name() ++ " "
++ integer_to_list(ListenPort) ++ " "
++ Args ++ " "
- ++ "-env ERL_CRASH_DUMP " ++ Pwd ++ "/erl_crash_dump." ++ Name ++ " "
+ ++ "-env ERL_CRASH_DUMP " ++ DumpPath ++ " "
++ "-kernel inet_dist_connect_options \"[{recbuf,12582912},{sndbuf,12582912},{high_watermark,8388608},{low_watermark,4194304}]\" "
++ "-kernel inet_dist_listen_options \"[{recbuf,12582912},{sndbuf,12582912},{high_watermark,8388608},{low_watermark,4194304}]\" "
- ++ "-kernel error_logger \"{file,\\\"" ++ Pwd ++ "/error_log." ++ Name ++ "\\\"}\" "
+ ++ "-kernel error_logger \"{file,\\\"" ++ LogPath ++ "\\\"}\" "
++ "-setcookie " ++ atom_to_list(erlang:get_cookie()).
%%
@@ -173,31 +185,36 @@ await_ssl_node_up(Name, LSock) ->
end.
check_ssl_node_up(Socket, Name, Bin) ->
+ NodeName =
+ case string:find(Name,"@") of
+ nomatch ->
+ list_to_atom(Name++"@"++host_name());
+ _ ->
+ list_to_atom(Name)
+ end,
case catch binary_to_term(Bin) of
{'EXIT', _} ->
gen_tcp:close(Socket),
exit({bad_data_received_from_ssl_node, Name, Bin});
{ssl_node_up, NodeName} ->
- case list_to_atom(Name++"@"++host_name()) of
- NodeName ->
- Parent = self(),
- Go = make_ref(),
- %% Spawn connection handler on test server side
- Pid = spawn(
- fun () ->
- link(group_leader()),
- receive Go -> ok end,
- process_flag(trap_exit, true),
- tstsrvr_con_loop(Name, Socket, Parent)
- end),
- ok = gen_tcp:controlling_process(Socket, Pid),
- Pid ! Go,
- #node_handle{connection_handler = Pid,
- socket = Socket,
- name = Name};
- _ ->
- exit({unexpected_ssl_node_connected, NodeName})
- end;
+ Parent = self(),
+ Go = make_ref(),
+ %% Spawn connection handler on test server side
+ Pid = spawn(
+ fun () ->
+ link(group_leader()),
+ receive Go -> ok end,
+ process_flag(trap_exit, true),
+ tstsrvr_con_loop(Name, Socket, Parent)
+ end),
+ ok = gen_tcp:controlling_process(Socket, Pid),
+ Pid ! Go,
+ #node_handle{connection_handler = Pid,
+ socket = Socket,
+ nodename = NodeName,
+ name = Name};
+ {ssl_node_up, OtherNodeName} ->
+ exit({unexpected_ssl_node_connected, OtherNodeName});
Msg ->
exit({unexpected_msg_instead_of_ssl_node_up, Name, Msg})
end.
diff --git a/lib/ssl/test/ssl_dist_test_lib.hrl b/lib/ssl/test/ssl_dist_test_lib.hrl
index 86b9b37026..9b1e1045ba 100644
--- a/lib/ssl/test/ssl_dist_test_lib.hrl
+++ b/lib/ssl/test/ssl_dist_test_lib.hrl
@@ -22,5 +22,7 @@
{connection_handler,
socket,
name,
- nodename}
+ nodename,
+ logfile,
+ dumpfile}
).
diff --git a/lib/ssl/test/ssl_eqc_SUITE.erl b/lib/ssl/test/ssl_eqc_SUITE.erl
index 4bfff1585e..cf6185e591 100644
--- a/lib/ssl/test/ssl_eqc_SUITE.erl
+++ b/lib/ssl/test/ssl_eqc_SUITE.erl
@@ -36,6 +36,7 @@
tls_cipher_openssl_suite_names/1,
tls_anon_cipher_suite_names/1,
tls_anon_cipher_openssl_suite_names/1,
+ tls_signature_algs/1,
tls_unorded_chains/1,
tls_extraneous_chain/1,
tls_extraneous_chains/1,
@@ -54,6 +55,7 @@ all() ->
tls_cipher_openssl_suite_names,
tls_anon_cipher_suite_names,
tls_anon_cipher_openssl_suite_names,
+ tls_signature_algs,
tls_unorded_chains,
tls_extraneous_chain,
tls_extraneous_chains,
@@ -101,6 +103,11 @@ tls_anon_cipher_openssl_suite_names(Config) when is_list(Config) ->
true = ct_property_test:quickcheck(ssl_eqc_cipher_format:prop_tls_anon_cipher_suite_openssl_name(),
Config).
+tls_signature_algs(Config) when is_list(Config) ->
+ %% manual test: proper:quickcheck(ssl_eqc_handshake:prop_tls_signature_algs()).
+ true = ct_property_test:quickcheck(ssl_eqc_cipher_format:prop_tls_signature_algs(),
+ Config).
+
tls_unorded_chains(Config) when is_list(Config) ->
%% manual test: proper:quickcheck(ssl_eqc_chain:prop_tls_ordered_path("/tmp")
ssl:start(),
diff --git a/lib/ssl/test/ssl_session_SUITE.erl b/lib/ssl/test/ssl_session_SUITE.erl
index 8f2be84a84..c74052f6b4 100644
--- a/lib/ssl/test/ssl_session_SUITE.erl
+++ b/lib/ssl/test/ssl_session_SUITE.erl
@@ -159,6 +159,7 @@ init_per_testcase(server_max_session_table, Config) ->
ct:timetrap({seconds, 30}),
Config;
init_per_testcase(_, Config) ->
+ ct:timetrap({seconds, 30}),
Config.
end_per_testcase(reuse_session_expired, Config) ->
@@ -461,49 +462,49 @@ explicit_session_reuse_expired(Config) when is_list(Config) ->
no_reuses_session_server_restart_new_cert() ->
[{doc,"Check that a session is not reused if the server is restarted with a new cert."}].
no_reuses_session_server_restart_new_cert(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_der_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_der_verify_opts, Config),
+ RSA1024ServerOpts = ssl_test_lib:ssl_options(server_rsa_1024_der_opts, Config),
+ RSA1024ClientOpts = ssl_test_lib:ssl_options(client_rsa_1024_der_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
- RSA1024ServerOpts = ssl_test_lib:ssl_options(server_rsa_1024_opts, Config),
- RSA1024ClientOpts = ssl_test_lib:ssl_options(client_rsa_1024_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server =
+ Server0 =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {ssl_test_lib, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
+ Port = ssl_test_lib:inet_port(Server0),
Client0 =
ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, no_result, []}},
- {from, self()}, {options, [{reuse_sessions, save} | ClientOpts]}]),
- SessionInfo =
- receive
- {Server, Info} ->
- Info
- end,
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_info_result, []}},
+ {from, self()}, {options, [{reuse_sessions, save} | ClientOpts]}]),
+ Info0 = receive {Server0, Info00} -> Info00 end,
+ Info0 = receive {Client0, Info01} -> Info01 end,
- ssl_test_lib:close(Server),
+ ct:sleep(?SLEEP),
ssl_test_lib:close(Client0),
+ ssl_test_lib:close(Server0),
- Server1 =
- ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, [{reuseaddr, true} | RSA1024ServerOpts]}]),
+ Server1 = ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
+ {from, self()},
+ {mfa, {ssl_test_lib, session_info_result, []}},
+ {options, [{reuseaddr, true} | RSA1024ServerOpts]}]),
+
+ Client1 = ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_info_result, []}},
+ {from, self()}, {options, RSA1024ClientOpts}]),
+ Info1 = receive {Server1, Info10} -> Info10 end,
- Client1 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, session_info_result, []}},
- {from, self()}, {options, RSA1024ClientOpts}]),
receive
- {Client1, SessionInfo} ->
+ {Client1, Info0} ->
ct:fail(session_reused_when_server_has_new_cert);
- {Client1, _Other} ->
- ok
+ {Client1, Info1} ->
+ ct:pal("First: ~p~nSecond ~p~n",[Info0, Info1]);
+ Unexpected ->
+ ct:fail({unexpected, Unexpected, {Client1, Info1}})
end,
ssl_test_lib:close(Server1),
ssl_test_lib:close(Client1).
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index e4c23c22cf..8b30819816 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -108,6 +108,7 @@
check_ok/1,
check_result/4,
check_result/2,
+ get_result/1,
gen_check_result/4,
basic_alert/4,
session_id/1,
@@ -409,7 +410,7 @@ run_where(_, ipv6) ->
{ClientNode, ServerNode, Host}.
node_to_hostip(Node, Role) ->
- [_ , Host] = string:tokens(atom_to_list(Node), "@"),
+ Host = rpc:call(Node, net_adm, localhost, []),
{ok, Address} = inet:getaddr(Host, inet),
%% Convert client addresses in 127.0.0.0/24 subnet to the atom 'localhost'.
%% This is a workaround for testcase problems caused by the fact that
@@ -1041,7 +1042,15 @@ client_loop_core(Socket, Pid, Transport) ->
{ssl_closed, Socket} ->
ok;
{gen_tcp, closed} ->
- ok
+ ok;
+ {apply, From, Fun} ->
+ try
+ Res = Fun(Socket, Transport),
+ From ! {apply_res, Res}
+ catch E:R:ST ->
+ From ! {apply_res, {E,R,ST}}
+ end,
+ client_loop_core(Socket, Pid, Transport)
end.
client_cont_loop(_Node, Host, Port, Pid, Transport, Options, cancel, _Opts) ->
@@ -1113,9 +1122,20 @@ close(Pid, Timeout) ->
exit(Pid, kill)
end.
+get_result(Pids) ->
+ get_result(Pids, []).
+
+get_result([], Acc) ->
+ Acc;
+get_result([Pid | Tail], Acc) ->
+ receive
+ {Pid, Msg} ->
+ get_result(Tail, [Msg | Acc])
+ end.
+
check_result(Server, ServerMsg, Client, ClientMsg) ->
{ClientIP, ClientPort} = get_ip_port(ServerMsg),
- receive
+ receive
{Server, ServerMsg} ->
check_result(Client, ClientMsg);
%% Workaround to accept local addresses (127.0.0.0/24)
@@ -1710,16 +1730,20 @@ make_rsa_cert(Config) ->
ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
CertChainConf = gen_conf(rsa, rsa, ClientChain, ServerChain),
GenCertData = public_key:pkix_test_data(CertChainConf),
+ #{client_config := ClientDerConf, server_config := ServerDerConf} = GenCertData,
+
[{server_config, ServerConf},
{client_config, ClientConf}] =
x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
[{server_rsa_opts, [{reuseaddr, true} | ServerConf]},
-
- {server_rsa_verify_opts, [{reuseaddr, true},
- {verify, verify_peer} | ServerConf]},
+ {server_rsa_verify_opts, [{reuseaddr, true}, {verify, verify_peer} | ServerConf]},
{client_rsa_opts, ClientConf},
- {client_rsa_verify_opts, [{verify, verify_peer} |ClientConf]}
- | Config];
+ {client_rsa_verify_opts, [{verify, verify_peer} |ClientConf]},
+ {server_rsa_der_opts, [{reuseaddr, true} | ServerDerConf]},
+ {server_rsa_der_verify_opts, [{reuseaddr, true}, {verify, verify_peer} | ServerDerConf]},
+ {client_rsa_der_opts, ClientDerConf},
+ {client_rsa_der_verify_opts, [{verify, verify_peer} |ClientDerConf]}
+ | Config];
false ->
Config
end.
@@ -1734,15 +1758,18 @@ make_rsa_1024_cert(Config) ->
ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
CertChainConf = gen_conf('rsa-1024', 'rsa-1024', ClientChain, ServerChain),
GenCertData = public_key:pkix_test_data(CertChainConf),
+ #{client_config := ClientDerConf, server_config := ServerDerConf} = GenCertData,
[{server_config, ServerConf},
{client_config, ClientConf}] =
x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
[{server_rsa_1024_opts, [{ssl_imp, new},{reuseaddr, true} | ServerConf]},
-
- {server_rsa_1024_verify_opts, [{ssl_imp, new}, {reuseaddr, true},
- {verify, verify_peer} | ServerConf]},
+ {server_rsa_1024_verify_opts, [{ssl_imp, new}, {reuseaddr, true}, {verify, verify_peer} | ServerConf]},
{client_rsa_1024_opts, ClientConf},
- {client_rsa_1024_verify_opts, [{verify, verify_peer} |ClientConf]}
+ {client_rsa_1024_verify_opts, [{verify, verify_peer} |ClientConf]},
+ {server_rsa_1024_der_opts, [{ssl_imp, new},{reuseaddr, true} | ServerDerConf]},
+ {server_rsa_1024_der_verify_opts, [{ssl_imp, new}, {reuseaddr, true}, {verify, verify_peer} | ServerDerConf]},
+ {client_rsa_1024_der_opts, ClientDerConf},
+ {client_rsa_1024_der_verify_opts, [{verify, verify_peer} |ClientDerConf]}
| Config];
false ->
Config
@@ -2080,6 +2107,7 @@ start_client(openssl, Port, ClientOpts, Config) ->
Ciphers = proplists:get_value(ciphers, ClientOpts, ssl:cipher_suites(default,Version)),
Groups0 = proplists:get_value(groups, ClientOpts),
CertArgs = openssl_cert_options(ClientOpts, client),
+ SigAlgs = openssl_sigalgs(proplists:get_value(sigalgs, ClientOpts, undefined)),
AlpnArgs = openssl_alpn_options(proplists:get_value(alpn, ClientOpts, undefined)),
NpnArgs = openssl_npn_options(proplists:get_value(np, ClientOpts, undefined)),
Reconnect = openssl_reconect_option(proplists:get_value(reconnect, ClientOpts, false)),
@@ -2096,7 +2124,7 @@ start_client(openssl, Port, ClientOpts, Config) ->
"-connect", hostname_format(HostName) ++ ":" ++ integer_to_list(Port), cipher_flag(Version),
ciphers(Ciphers, Version),
version_flag(Version)]
- ++ CertArgs ++ AlpnArgs ++ NpnArgs ++ Reconnect ++ MaxFragLen ++ SessionArgs
+ ++ CertArgs ++ SigAlgs ++ AlpnArgs ++ NpnArgs ++ Reconnect ++ MaxFragLen ++ SessionArgs
++ Debug;
Group ->
["s_client",
@@ -2104,7 +2132,7 @@ start_client(openssl, Port, ClientOpts, Config) ->
"-connect", hostname_format(HostName) ++ ":" ++ integer_to_list(Port), cipher_flag(Version),
ciphers(Ciphers, Version), "-groups", Group,
version_flag(Version)]
- ++ CertArgs ++ AlpnArgs ++ NpnArgs ++ Reconnect ++ MaxFragLen ++ SessionArgs
+ ++ CertArgs ++ SigAlgs ++ AlpnArgs ++ NpnArgs ++ Reconnect ++ MaxFragLen ++ SessionArgs
++ Debug
end,
Args = maybe_force_ipv4(Args0),
@@ -2347,6 +2375,11 @@ cert_option("-cert_chain", Value) ->
cert_option(Opt, Value) ->
[Opt, Value].
+openssl_sigalgs(undefined) ->
+ [];
+openssl_sigalgs(SigAlgs) ->
+ ["-sigalgs", SigAlgs].
+
supported_eccs(Opts) ->
ToCheck = proplists:get_value(eccs, Opts, []),
Supported = ssl:eccs(),
diff --git a/lib/ssl/test/tls_1_3_record_SUITE.erl b/lib/ssl/test/tls_1_3_record_SUITE.erl
index ab6d7bf33b..7b774ea1b9 100644
--- a/lib/ssl/test/tls_1_3_record_SUITE.erl
+++ b/lib/ssl/test/tls_1_3_record_SUITE.erl
@@ -36,7 +36,7 @@
-export([encode_decode/0,
encode_decode/1,
finished_verify_data/0,
- finished_verify_data/1,
+ finished_verify_data/1,
'1_RTT_handshake'/0,
'1_RTT_handshake'/1,
'0_RTT_handshake'/0,
diff --git a/lib/ssl/test/tls_api_SUITE.erl b/lib/ssl/test/tls_api_SUITE.erl
index 453ccf12ee..a5f4fe3709 100644
--- a/lib/ssl/test/tls_api_SUITE.erl
+++ b/lib/ssl/test/tls_api_SUITE.erl
@@ -512,8 +512,7 @@ tls_monitor_listener(Config) when is_list(Config) ->
{options, tls_monitor_listen_opts(Version, ServerOpts)}]),
_Port2 = ssl_test_lib:inet_port(Server2),
- ProlistCounts1 = supervisor:count_children(ssl_listen_tracker_sup),
- 2 = proplists:get_value(workers, ProlistCounts1),
+ 2 = count_children(workers, ssl_listen_tracker_sup),
Sessions = session_info(Version),
@@ -534,12 +533,11 @@ tls_monitor_listener(Config) when is_list(Config) ->
ct:sleep(1000)
end,
- ProlistCounts2 = supervisor:count_children(ssl_listen_tracker_sup),
Sessions1 = session_info(Version),
true = (Sessions1 == 1),
-
- 1 = proplists:get_value(workers, ProlistCounts2).
+
+ 1 = count_children(workers, ssl_listen_tracker_sup).
%%--------------------------------------------------------------------
tls_tcp_msg() ->
@@ -826,7 +824,7 @@ transport_close_in_inital_hello(Config) when is_list(Config) ->
Sup = (whereis(tls_connection_sup)),
- check_connection_workers(Sup, 2),
+ check_connection_processes(Sup, 2),
Acceptor ! die,
@@ -838,20 +836,20 @@ transport_close_in_inital_hello(Config) when is_list(Config) ->
{'EXIT', Connector, _} ->
ok
end,
- check_connection_workers(Sup, 0).
+ check_connection_processes(Sup, 0).
-check_connection_workers(Sup, N) ->
- check_connection_workers(Sup, N, 5).
+check_connection_processes(Sup, N) ->
+ check_connection_processes(Sup, N, 5).
-check_connection_workers(Sup, N, 0) ->
- N = proplists:get_value(workers, supervisor:count_children(Sup));
-check_connection_workers(Sup, N, M) ->
- case proplists:get_value(workers, supervisor:count_children(Sup)) of
+check_connection_processes(Sup, N, 0) ->
+ N = count_children(supervisors, Sup);
+check_connection_processes(Sup, N, M) ->
+ case count_children(supervisors, Sup) of
N ->
ok;
_ ->
ct:sleep(500),
- check_connection_workers(Sup, N, M-1)
+ check_connection_processes(Sup, N, M-1)
end.
%%--------------------------------------------------------------------
@@ -1100,8 +1098,9 @@ tls_monitor_client_opts(_, Opts) ->
Opts.
session_info('tlsv1.3') ->
- ProlistCounts = supervisor:count_children(tls_server_session_ticket_sup),
- proplists:get_value(workers, ProlistCounts);
+ count_children(workers, tls_server_session_ticket_sup);
session_info(_) ->
- ProlistCounts = supervisor:count_children(ssl_server_session_cache_sup),
- proplists:get_value(workers, ProlistCounts).
+ count_children(workers, ssl_server_session_cache_sup).
+
+count_children(ChildType, SupRef) ->
+ proplists:get_value(ChildType, supervisor:count_children(SupRef)).
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 8f1847a5be..4064eb55f6 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 10.5.1
+SSL_VSN = 10.5.3