aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/doc/src/notes.xml17
-rw-r--r--lib/ssl/src/dtls_connection.erl70
-rw-r--r--lib/ssl/src/dtls_handshake.erl155
-rw-r--r--lib/ssl/src/dtls_packet_demux.erl41
-rw-r--r--lib/ssl/src/dtls_socket.erl6
-rw-r--r--lib/ssl/src/dtls_v1.erl6
-rw-r--r--lib/ssl/src/inet_tls_dist.erl10
-rw-r--r--lib/ssl/src/ssl.erl32
-rw-r--r--lib/ssl/src/ssl_cipher.erl102
-rw-r--r--lib/ssl/src/ssl_cipher.hrl80
-rw-r--r--lib/ssl/src/ssl_cipher_format.erl1358
-rw-r--r--lib/ssl/src/ssl_connection.erl12
-rw-r--r--lib/ssl/src/ssl_handshake.erl10
-rw-r--r--lib/ssl/src/ssl_logger.erl14
-rw-r--r--lib/ssl/src/ssl_record.erl37
-rw-r--r--lib/ssl/src/ssl_record.hrl5
-rw-r--r--lib/ssl/src/tls_connection.erl4
-rw-r--r--lib/ssl/src/tls_handshake.erl2
-rw-r--r--lib/ssl/src/tls_handshake_1_3.erl8
-rw-r--r--lib/ssl/src/tls_record.erl20
-rw-r--r--lib/ssl/src/tls_record_1_3.erl2
-rw-r--r--lib/ssl/test/Makefile5
-rw-r--r--lib/ssl/test/inet_crypto_dist.erl1323
-rw-r--r--lib/ssl/test/ssl.spec2
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl4
-rw-r--r--lib/ssl/test/ssl_cipher_suite_SUITE.erl137
-rw-r--r--lib/ssl/test/ssl_dist_bench_SUITE.erl134
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl2
-rw-r--r--lib/ssl/test/ssl_test_lib.erl213
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl79
-rw-r--r--lib/ssl/test/ssl_upgrade_SUITE.erl13
-rw-r--r--lib/ssl/test/x509_test.erl2
-rw-r--r--lib/ssl/vsn.mk2
33 files changed, 2822 insertions, 1085 deletions
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index a511cb4db3..f0231da2ad 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -27,6 +27,23 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
+<section><title>SSL 9.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With the default BEAST Mitigation strategy for TLS 1.0 an
+ empty TLS fragment could be sent after a one-byte
+ fragment. This glitch has been fixed.</p>
+ <p>
+ Own Id: OTP-15054 Aux Id: ERIERL-346 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 9.2.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index 30b2ab7c4f..e070006900 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -67,7 +67,7 @@
%% Setup
%%====================================================================
start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_, Tracker} = Opts,
- User, {CbModule, _,_, _} = CbInfo,
+ User, {CbModule, _, _, _, _} = CbInfo,
Timeout) ->
try
{ok, Pid} = dtls_connection_sup:start_child([Role, Host, Port, Socket,
@@ -147,13 +147,16 @@ next_record(#state{static_env = #static_env{role = server,
socket = {Listener, {Client, _}}}} = State) ->
dtls_packet_demux:active_once(Listener, Client, self()),
{no_record, State};
-next_record(#state{static_env = #static_env{role = client,
+next_record(#state{protocol_specific = #{active_n_toggle := true,
+ active_n := N} = ProtocolSpec,
+ static_env = #static_env{role = client,
socket = {_Server, Socket} = DTLSSocket,
close_tag = CloseTag,
transport_cb = Transport}} = State) ->
- case dtls_socket:setopts(Transport, Socket, [{active,once}]) of
+ case dtls_socket:setopts(Transport, Socket, [{active,N}]) of
ok ->
- {no_record, State};
+ {no_record, State#state{protocol_specific =
+ ProtocolSpec#{active_n_toggle => false}}};
_ ->
self() ! {CloseTag, DTLSSocket},
{no_record, State}
@@ -193,7 +196,8 @@ next_event(StateName, no_record,
%% TODO maybe buffer later epoch
next_event(StateName, no_record, State, Actions);
{#alert{} = Alert, State} ->
- {next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
+ Version = State#state.connection_env#connection_env.negotiated_version,
+ handle_own_alert(Alert, Version, StateName, State)
end;
next_event(connection = StateName, Record,
#state{connection_states = #{current_read := #{epoch := CurrentEpoch}}} = State0, Actions) ->
@@ -233,7 +237,8 @@ next_event(StateName, Record,
%% TODO maybe buffer later epoch
next_event(StateName, no_record, State0, Actions);
#alert{} = Alert ->
- {next_state, StateName, State0, [{next_event, internal, Alert} | Actions]}
+ Version = State0#state.connection_env#connection_env.negotiated_version,
+ handle_own_alert(Alert, Version, StateName, State0)
end.
%%% DTLS record protocol level application data messages
@@ -289,9 +294,10 @@ handle_protocol_record(#ssl_tls{type = _Unknown}, StateName, State) ->
%% Handshake handling
%%====================================================================
-renegotiate(#state{static_env = #static_env{role = client}} = State, Actions) ->
+renegotiate(#state{static_env = #static_env{role = client}} = State0, Actions) ->
%% Handle same way as if server requested
%% the renegotiation
+ State = reinit_handshake_data(State0),
{next_state, connection, State,
[{next_event, internal, #hello_request{}} | Actions]};
@@ -449,8 +455,7 @@ init({call, From}, {start, Timeout},
session =
Session0#session{session_id = Hello#client_hello.session_id},
start_or_recv_from = From},
- {Record, State} = next_record(State3),
- next_event(hello, Record, State, [{{timeout, handshake}, Timeout, close} | Actions]);
+ next_event(hello, no_record, State3, [{{timeout, handshake}, Timeout, close} | Actions]);
init({call, _} = Type, Event, #state{static_env = #static_env{role = server},
protocol_specific = PS} = State) ->
Result = gen_handshake(?FUNCTION_NAME, Type, Event,
@@ -508,9 +513,8 @@ hello(internal, #client_hello{cookie = <<>>,
%% negotiated.
VerifyRequest = dtls_handshake:hello_verify_request(Cookie, ?HELLO_VERIFY_REQUEST_VERSION),
State1 = prepare_flight(State0#state{connection_env = CEnv#connection_env{negotiated_version = Version}}),
- {State2, Actions} = send_handshake(VerifyRequest, State1),
- {Record, State} = next_record(State2),
- next_event(?FUNCTION_NAME, Record,
+ {State, Actions} = send_handshake(VerifyRequest, State1),
+ next_event(?FUNCTION_NAME, no_record,
State#state{handshake_env = HsEnv#handshake_env{
tls_handshake_history =
ssl_handshake:init_handshake_history()}},
@@ -712,12 +716,10 @@ connection(internal, #hello_request{}, #state{static_env = #static_env{host = Ho
HelloVersion = dtls_record:hello_version(Version, SslOpts#ssl_options.versions),
State1 = prepare_flight(State0),
{State2, Actions} = send_handshake(Hello, State1#state{connection_env = CEnv#connection_env{negotiated_version = HelloVersion}}),
- {Record, State} =
- next_record(
- State2#state{protocol_specific = PS#{flight_state => initial_flight_state(DataTag)},
- session = Session0#session{session_id
- = Hello#client_hello.session_id}}),
- next_event(hello, Record, State, Actions);
+ State = State2#state{protocol_specific = PS#{flight_state => initial_flight_state(DataTag)},
+ session = Session0#session{session_id
+ = Hello#client_hello.session_id}},
+ next_event(hello, no_record, State, Actions);
connection(internal, #client_hello{} = Hello, #state{static_env = #static_env{role = server},
handshake_env = #handshake_env{allow_renegotiate = true} = HsEnv} = State) ->
%% Mitigate Computational DoS attack
@@ -773,7 +775,7 @@ format_status(Type, Data) ->
%%% Internal functions
%%--------------------------------------------------------------------
initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, _}, User,
- {CbModule, DataTag, CloseTag, ErrorTag}) ->
+ {CbModule, DataTag, CloseTag, ErrorTag, PassiveTag}) ->
#ssl_options{beast_mitigation = BeastMitigation} = SSLOptions,
ConnectionStates = dtls_record:init_connection_states(Role, BeastMitigation),
@@ -783,7 +785,12 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, _}, User,
_ ->
ssl_session_cache
end,
-
+ InternalActiveN = case application:get_env(ssl, internal_active_n) of
+ {ok, N} when is_integer(N) ->
+ N;
+ _ ->
+ ?INTERNAL_ACTIVE_N
+ end,
Monitor = erlang:monitor(process, User),
InitStatEnv = #static_env{
role = Role,
@@ -792,6 +799,7 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, _}, User,
data_tag = DataTag,
close_tag = CloseTag,
error_tag = ErrorTag,
+ passive_tag = PassiveTag,
host = Host,
port = Port,
socket = Socket,
@@ -815,7 +823,9 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, _}, User,
user_data_buffer = {[],0,[]},
start_or_recv_from = undefined,
flight_buffer = new_flight(),
- protocol_specific = #{flight_state => initial_flight_state(DataTag)}
+ protocol_specific = #{active_n => InternalActiveN,
+ active_n_toggle => true,
+ flight_state => initial_flight_state(DataTag)}
}.
initial_flight_state(udp)->
@@ -912,12 +922,21 @@ handle_info({Protocol, _, _, _, Data}, StateName,
ssl_connection:handle_normal_shutdown(Alert, StateName, State0),
{stop, {shutdown, own_alert}, State0}
end;
+
+handle_info({PassiveTag, Socket}, StateName,
+ #state{static_env = #static_env{socket = {_, Socket},
+ passive_tag = PassiveTag},
+ protocol_specific = PS} = State) ->
+ next_event(StateName, no_record,
+ State#state{protocol_specific = PS#{active_n_toggle => true}});
+
handle_info({CloseTag, Socket}, StateName,
#state{static_env = #static_env{socket = Socket,
close_tag = CloseTag},
connection_env = #connection_env{negotiated_version = Version},
socket_options = #socket_options{active = Active},
- protocol_buffers = #protocol_buffers{dtls_cipher_texts = CTs}} = State) ->
+ protocol_buffers = #protocol_buffers{dtls_cipher_texts = CTs},
+ protocol_specific = PS} = State) ->
%% Note that as of DTLS 1.2 (TLS 1.1),
%% failure to properly close a connection no longer requires that a
%% session not be resumed. This is a change from DTLS 1.0 to conform
@@ -940,7 +959,8 @@ handle_info({CloseTag, Socket}, StateName,
%% Fixes non-delivery of final DTLS record in {active, once}.
%% Basically allows the application the opportunity to set {active, once} again
%% and then receive the final message.
- next_event(StateName, no_record, State)
+ next_event(StateName, no_record, State#state{
+ protocol_specific = PS#{active_n_toggle => true}})
end;
handle_info(new_cookie_secret, StateName,
@@ -1075,10 +1095,10 @@ start_retransmision_timer(Timeout, #state{protocol_specific = PS} = State) ->
{State#state{protocol_specific = PS#{flight_state => {retransmit, new_timeout(Timeout)}}},
[{state_timeout, Timeout, flight_retransmission_timeout}]}.
-new_timeout(N) when N =< 30 ->
+new_timeout(N) when N =< 30000 ->
N * 2;
new_timeout(_) ->
- 60.
+ 60000.
send_handshake_flight(#state{static_env = #static_env{socket = Socket,
transport_cb = Transport},
diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl
index 46e8348ce0..d8c0e30973 100644
--- a/lib/ssl/src/dtls_handshake.erl
+++ b/lib/ssl/src/dtls_handshake.erl
@@ -193,7 +193,7 @@ handle_client_hello(Version,
no_suite ->
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY);
_ ->
- #{key_exchange := KeyExAlg} = ssl_cipher_format:suite_definition(CipherSuite),
+ #{key_exchange := KeyExAlg} = ssl_cipher_format:suite_bin_to_map(CipherSuite),
case ssl_handshake:select_hashsign({ClientHashSigns, undefined}, Cert, KeyExAlg,
SupportedHashSigns, TLSVersion) of
#alert{} = Alert ->
@@ -427,74 +427,135 @@ merge_fragment(Frag0, [Frag1 | Rest]) ->
Frag ->
merge_fragment(Frag, Rest)
end.
-%% Duplicate
+
+
+%% Duplicate (fully contained fragment)
+%% 2,5 _ _ P P P P P
+%% 2,5 _ _ C C C C C
merge_fragments(#handshake_fragment{
- fragment_offset = PreviousOffSet,
+ fragment_offset = PreviousOffSet,
fragment_length = PreviousLen,
fragment = PreviousData
- } = Previous,
+ } = Previous,
#handshake_fragment{
fragment_offset = PreviousOffSet,
fragment_length = PreviousLen,
fragment = PreviousData}) ->
Previous;
-%% Lager fragment save new data
+%% Duplicate (fully contained fragment)
+%% 2,5 _ _ P P P P P
+%% 2,2 _ _ C C
+%% 0,3 X X X
+%% 5,3 _ _ _ _ _ X X X
merge_fragments(#handshake_fragment{
- fragment_offset = PreviousOffSet,
- fragment_length = PreviousLen,
+ fragment_offset = PreviousOffset,
+ fragment_length = PreviousLen
+ } = Previous,
+ #handshake_fragment{
+ fragment_offset = CurrentOffset,
+ fragment_length = CurrentLen})
+ when PreviousOffset =< CurrentOffset andalso
+ CurrentOffset =< PreviousOffset + PreviousLen andalso
+ CurrentOffset + CurrentLen =< PreviousOffset + PreviousLen ->
+ Previous;
+
+%% Fully overlapping fragments
+%% 2,5 _ _ P P P P P
+%% 0,8 C C C C C C C C
+merge_fragments(#handshake_fragment{
+ fragment_offset = PreviousOffset,
+ fragment_length = PreviousLen
+ },
+ #handshake_fragment{
+ fragment_offset = CurrentOffset,
+ fragment_length = CurrentLen} = Current)
+ when CurrentOffset =< PreviousOffset andalso
+ CurrentOffset + CurrentLen >= PreviousOffset + PreviousLen ->
+ Current;
+
+%% Overlapping fragments
+%% 2,5 _ _ P P P P P
+%% 0,3 C C C
+merge_fragments(#handshake_fragment{
+ fragment_offset = PreviousOffset,
+ fragment_length = PreviousLen,
fragment = PreviousData
- } = Previous,
- #handshake_fragment{
- fragment_offset = PreviousOffSet,
- fragment_length = CurrentLen,
- fragment = CurrentData}) when CurrentLen > PreviousLen ->
- NewLength = CurrentLen - PreviousLen,
- <<_:PreviousLen/binary, NewData/binary>> = CurrentData,
+ } = Previous,
+ #handshake_fragment{
+ fragment_offset = CurrentOffset,
+ fragment_length = CurrentLen,
+ fragment = CurrentData})
+ when CurrentOffset < PreviousOffset andalso
+ CurrentOffset + CurrentLen < PreviousOffset + PreviousLen ->
+ NewDataLen = PreviousOffset - CurrentOffset,
+ <<NewData:NewDataLen/binary, _/binary>> = CurrentData,
Previous#handshake_fragment{
- fragment_length = PreviousLen + NewLength,
- fragment = <<PreviousData/binary, NewData/binary>>
+ fragment_length = PreviousLen + NewDataLen,
+ fragment = <<NewData/binary, PreviousData/binary>>
};
-%% Smaller fragment
+%% Overlapping fragments
+%% 2,5 _ _ P P P P P
+%% 5,3 _ _ _ _ _ C C C
merge_fragments(#handshake_fragment{
- fragment_offset = PreviousOffSet,
- fragment_length = PreviousLen
- } = Previous,
- #handshake_fragment{
- fragment_offset = PreviousOffSet,
- fragment_length = CurrentLen}) when CurrentLen < PreviousLen ->
- Previous;
-%% Next fragment, might be overlapping
+ fragment_offset = PreviousOffset,
+ fragment_length = PreviousLen,
+ fragment = PreviousData
+ } = Previous,
+ #handshake_fragment{
+ fragment_offset = CurrentOffset,
+ fragment_length = CurrentLen,
+ fragment = CurrentData})
+ when CurrentOffset > PreviousOffset andalso
+ CurrentOffset < PreviousOffset + PreviousLen ->
+ NewDataLen = CurrentOffset + CurrentLen - (PreviousOffset + PreviousLen),
+ DropLen = CurrentLen - NewDataLen,
+ <<_:DropLen/binary, NewData/binary>> = CurrentData,
+ Previous#handshake_fragment{
+ fragment_length = PreviousLen + NewDataLen,
+ fragment = <<PreviousData/binary, NewData/binary>>
+ };
+
+%% Adjacent fragments
+%% 2,5 _ _ P P P P P
+%% 7,3 _ _ _ _ _ _ _ C C C
merge_fragments(#handshake_fragment{
- fragment_offset = PreviousOffSet,
- fragment_length = PreviousLen,
+ fragment_offset = PreviousOffset,
+ fragment_length = PreviousLen,
fragment = PreviousData
- } = Previous,
- #handshake_fragment{
- fragment_offset = CurrentOffSet,
- fragment_length = CurrentLen,
- fragment = CurrentData})
- when PreviousOffSet + PreviousLen >= CurrentOffSet andalso
- PreviousOffSet + PreviousLen < CurrentOffSet + CurrentLen ->
- CurrentStart = PreviousOffSet + PreviousLen - CurrentOffSet,
- <<_:CurrentStart/bytes, Data/binary>> = CurrentData,
+ } = Previous,
+ #handshake_fragment{
+ fragment_offset = CurrentOffset,
+ fragment_length = CurrentLen,
+ fragment = CurrentData})
+ when CurrentOffset =:= PreviousOffset + PreviousLen ->
Previous#handshake_fragment{
- fragment_length = PreviousLen + CurrentLen - CurrentStart,
- fragment = <<PreviousData/binary, Data/binary>>};
-%% already fully contained fragment
+ fragment_length = PreviousLen + CurrentLen,
+ fragment = <<PreviousData/binary, CurrentData/binary>>
+ };
+
+%% Adjacent fragments
+%% 2,5 _ _ P P P P P
+%% 0,2 C C
merge_fragments(#handshake_fragment{
- fragment_offset = PreviousOffSet,
- fragment_length = PreviousLen
- } = Previous,
+ fragment_offset = PreviousOffset,
+ fragment_length = PreviousLen,
+ fragment = PreviousData
+ } = Previous,
#handshake_fragment{
- fragment_offset = CurrentOffSet,
- fragment_length = CurrentLen})
- when PreviousOffSet + PreviousLen >= CurrentOffSet andalso
- PreviousOffSet + PreviousLen >= CurrentOffSet + CurrentLen ->
- Previous;
+ fragment_offset = CurrentOffset,
+ fragment_length = CurrentLen,
+ fragment = CurrentData})
+ when PreviousOffset =:= CurrentOffset + CurrentLen ->
+ Previous#handshake_fragment{
+ fragment_length = PreviousLen + CurrentLen,
+ fragment = <<CurrentData/binary, PreviousData/binary>>
+ };
%% No merge there is a gap
+%% 3,5 _ _ _ P P P P
+%% 0,2 C C
merge_fragments(Previous, Current) ->
[Previous, Current].
diff --git a/lib/ssl/src/dtls_packet_demux.erl b/lib/ssl/src/dtls_packet_demux.erl
index e0423b07b4..c6431b55a9 100644
--- a/lib/ssl/src/dtls_packet_demux.erl
+++ b/lib/ssl/src/dtls_packet_demux.erl
@@ -35,7 +35,8 @@
terminate/2, code_change/3]).
-record(state,
- {port,
+ {active_n,
+ port,
listener,
transport,
dtls_options,
@@ -76,10 +77,18 @@ set_sock_opts(PacketSocket, Opts) ->
%%% gen_server callbacks
%%%===================================================================
-init([Port, {TransportModule, _,_,_} = TransportInfo, EmOpts, InetOptions, DTLSOptions]) ->
+init([Port, {TransportModule, _,_,_,_} = TransportInfo, EmOpts, InetOptions, DTLSOptions]) ->
try
{ok, Socket} = TransportModule:open(Port, InetOptions),
- {ok, #state{port = Port,
+ InternalActiveN = case application:get_env(ssl, internal_active_n) of
+ {ok, N} when is_integer(N) ->
+ N;
+ _ ->
+ ?INTERNAL_ACTIVE_N
+ end,
+
+ {ok, #state{active_n = InternalActiveN,
+ port = Port,
first = true,
transport = TransportInfo,
dtls_options = DTLSOptions,
@@ -92,10 +101,11 @@ init([Port, {TransportModule, _,_,_} = TransportInfo, EmOpts, InetOptions, DTLSO
handle_call({accept, _}, _, #state{close = true} = State) ->
{reply, {error, closed}, State};
-handle_call({accept, Accepter}, From, #state{first = true,
+handle_call({accept, Accepter}, From, #state{active_n = N,
+ first = true,
accepters = Accepters,
listener = Socket} = State0) ->
- next_datagram(Socket),
+ next_datagram(Socket, N),
State = State0#state{first = false,
accepters = queue:in({Accepter, From}, Accepters)},
{noreply, State};
@@ -137,19 +147,24 @@ handle_cast({active_once, Client, Pid}, State0) ->
State = handle_active_once(Client, Pid, State0),
{noreply, State}.
-handle_info({Transport, Socket, IP, InPortNo, _} = Msg, #state{listener = Socket, transport = {_,Transport,_,_}} = State0) ->
+handle_info({Transport, Socket, IP, InPortNo, _} = Msg, #state{listener = Socket, transport = {_,Transport,_,_,_}} = State0) ->
State = handle_datagram({IP, InPortNo}, Msg, State0),
- next_datagram(Socket),
{noreply, State};
+handle_info({PassiveTag, Socket},
+ #state{active_n = N,
+ listener = Socket,
+ transport = {_,_,_, udp_error, PassiveTag}}) ->
+ next_datagram(Socket, N);
+
%% UDP socket does not have a connection and should not receive an econnreset
%% This does however happens on some windows versions. Just ignoring it
%% appears to make things work as expected!
-handle_info({udp_error, Socket, econnreset = Error}, #state{listener = Socket, transport = {_,_,_, udp_error}} = State) ->
+handle_info({udp_error, Socket, econnreset = Error}, #state{listener = Socket, transport = {_,_,_, udp_error,_}} = State) ->
Report = io_lib:format("Ignore SSL UDP Listener: Socket error: ~p ~n", [Error]),
?LOG_NOTICE(Report),
{noreply, State};
-handle_info({ErrorTag, Socket, Error}, #state{listener = Socket, transport = {_,_,_, ErrorTag}} = State) ->
+handle_info({ErrorTag, Socket, Error}, #state{listener = Socket, transport = {_,_,_, ErrorTag,_}} = State) ->
Report = io_lib:format("SSL Packet muliplxer shutdown: Socket error: ~p ~n", [Error]),
?LOG_NOTICE(Report),
{noreply, State#state{close=true}};
@@ -203,16 +218,16 @@ dispatch(Client, Msg, #state{dtls_msq_queues = MsgQueues} = State) ->
Pid ! Msg,
State#state{dtls_msq_queues =
kv_update(Client, Queue, MsgQueues)};
- {{value, _}, Queue} ->
+ {{value, _UDP}, _Queue} ->
State#state{dtls_msq_queues =
- kv_update(Client, queue:in(Msg, Queue), MsgQueues)};
+ kv_update(Client, queue:in(Msg, Queue0), MsgQueues)};
{empty, Queue} ->
State#state{dtls_msq_queues =
kv_update(Client, queue:in(Msg, Queue), MsgQueues)}
end
end.
-next_datagram(Socket) ->
- inet:setopts(Socket, [{active, once}]).
+next_datagram(Socket, N) ->
+ inet:setopts(Socket, [{active, N}]).
handle_active_once(Client, Pid, #state{dtls_msq_queues = MsgQueues} = State0) ->
Queue0 = kv_get(Client, MsgQueues),
diff --git a/lib/ssl/src/dtls_socket.erl b/lib/ssl/src/dtls_socket.erl
index 4d07372e31..b305d08f70 100644
--- a/lib/ssl/src/dtls_socket.erl
+++ b/lib/ssl/src/dtls_socket.erl
@@ -45,7 +45,7 @@ listen(Port, #config{transport_info = TransportInfo,
Err
end.
-accept(dtls, #config{transport_info = {Transport,_,_,_},
+accept(dtls, #config{transport_info = {Transport,_,_,_,_},
connection_cb = ConnectionCb,
dtls_handler = {Listner, _}}, _Timeout) ->
case dtls_packet_demux:accept(Listner, self()) of
@@ -55,7 +55,7 @@ accept(dtls, #config{transport_info = {Transport,_,_,_},
{error, Reason}
end.
-connect(Address, Port, #config{transport_info = {Transport, _, _, _} = CbInfo,
+connect(Address, Port, #config{transport_info = {Transport, _, _, _, _} = CbInfo,
connection_cb = ConnectionCb,
ssl = SslOpts,
emulated = EmOpts,
@@ -174,7 +174,7 @@ default_inet_values() ->
[{active, true}, {mode, list}, {packet, 0}, {packet_size, 0}].
default_cb_info() ->
- {gen_udp, udp, udp_closed, udp_error}.
+ {gen_udp, udp, udp_closed, udp_error, udp_passive}.
get_emulated_opts(EmOpts, EmOptNames) ->
lists:map(fun(Name) -> {value, Value} = lists:keysearch(Name, 1, EmOpts),
diff --git a/lib/ssl/src/dtls_v1.erl b/lib/ssl/src/dtls_v1.erl
index b365961a6a..fc9dce02ce 100644
--- a/lib/ssl/src/dtls_v1.erl
+++ b/lib/ssl/src/dtls_v1.erl
@@ -31,18 +31,18 @@
suites(Minor) ->
lists:filter(fun(Cipher) ->
- is_acceptable_cipher(ssl_cipher_format:suite_definition(Cipher))
+ is_acceptable_cipher(ssl_cipher_format:suite_bin_to_map(Cipher))
end,
tls_v1:suites(corresponding_minor_tls_version(Minor))).
all_suites(Version) ->
lists:filter(fun(Cipher) ->
- is_acceptable_cipher(ssl_cipher_format:suite_definition(Cipher))
+ is_acceptable_cipher(ssl_cipher_format:suite_bin_to_map(Cipher))
end,
ssl_cipher:all_suites(corresponding_tls_version(Version))).
anonymous_suites(Version) ->
lists:filter(fun(Cipher) ->
- is_acceptable_cipher(ssl_cipher_format:suite_definition(Cipher))
+ is_acceptable_cipher(ssl_cipher_format:suite_bin_to_map(Cipher))
end,
ssl_cipher:anonymous_suites(corresponding_tls_version(Version))).
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
index e7fab7ebc5..8d9b92361b 100644
--- a/lib/ssl/src/inet_tls_dist.erl
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2019. 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.
@@ -132,8 +132,8 @@ f_recv(SslSocket, Length, Timeout) ->
f_setopts_pre_nodeup(_SslSocket) ->
ok.
-f_setopts_post_nodeup(_SslSocket) ->
- ok.
+f_setopts_post_nodeup(SslSocket) ->
+ ssl:setopts(SslSocket, [nodelay()]).
f_getll(DistCtrl) ->
{ok, DistCtrl}.
@@ -199,7 +199,7 @@ listen(Name) ->
gen_listen(Driver, Name) ->
case inet_tcp_dist:gen_listen(Driver, Name) of
{ok, {Socket, Address, Creation}} ->
- inet:setopts(Socket, [{packet, 4}]),
+ inet:setopts(Socket, [{packet, 4}, {nodelay, true}]),
{ok, {Socket, Address#net_address{protocol=tls}, Creation}};
Other ->
Other
@@ -532,7 +532,7 @@ do_setup_connect(Driver, Kernel, Node, Address, Ip, TcpPort, Version, Type, MyNo
case ssl:connect(
Address, TcpPort,
[binary, {active, false}, {packet, 4},
- Driver:family(), nodelay()] ++ Opts,
+ Driver:family(), {nodelay, true}] ++ Opts,
net_kernel:connecttime()) of
{ok, #sslsocket{pid = [_, DistCtrl| _]} = SslSocket} ->
_ = monitor_pid(DistCtrl),
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index c7c96370b3..74511dce4b 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -112,6 +112,10 @@
aes_256_cbc |
aes_128_gcm |
aes_256_gcm |
+ aes_128_ccm |
+ aes_256_ccm |
+ aes_128_ccm_8 |
+ aes_256_ccm_8 |
chacha20_poly1305 |
legacy_cipher().
-type legacy_cipher() :: rc4_128 |
@@ -785,14 +789,14 @@ cipher_suites() ->
%% Description: Returns all supported cipher suites.
%%--------------------------------------------------------------------
cipher_suites(erlang) ->
- [ssl_cipher_format:erl_suite_definition(Suite) || Suite <- available_suites(default)];
+ [ssl_cipher_format:suite_legacy(Suite) || Suite <- available_suites(default)];
cipher_suites(openssl) ->
- [ssl_cipher_format:openssl_suite_name(Suite) ||
+ [ssl_cipher_format:suite_map_to_openssl_str(ssl_cipher_format:suite_bin_to_map(Suite)) ||
Suite <- available_suites(default)];
cipher_suites(all) ->
- [ssl_cipher_format:erl_suite_definition(Suite) || Suite <- available_suites(all)].
+ [ssl_cipher_format:suite_legacy(Suite) || Suite <- available_suites(all)].
%%--------------------------------------------------------------------
-spec cipher_suites(default | all | anonymous, ssl_record:ssl_version() |
@@ -810,7 +814,7 @@ cipher_suites(Base, Version) when Version == 'dtlsv1.2';
Version == 'dtlsv1'->
cipher_suites(Base, dtls_record:protocol_version(Version));
cipher_suites(Base, Version) ->
- [ssl_cipher_format:suite_definition(Suite) || Suite <- supported_suites(Base, Version)].
+ [ssl_cipher_format:suite_bin_to_map(Suite) || Suite <- supported_suites(Base, Version)].
%%--------------------------------------------------------------------
-spec filter_cipher_suites([erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()] ,
@@ -925,7 +929,7 @@ groups(default) ->
%%--------------------------------------------------------------------
getopts(#sslsocket{pid = [Pid|_]}, OptionTags) when is_pid(Pid), is_list(OptionTags) ->
ssl_connection:get_opts(Pid, OptionTags);
-getopts(#sslsocket{pid = {dtls, #config{transport_info = {Transport,_,_,_}}}} = ListenSocket, OptionTags) when is_list(OptionTags) ->
+getopts(#sslsocket{pid = {dtls, #config{transport_info = {Transport,_,_,_,_}}}} = ListenSocket, OptionTags) when is_list(OptionTags) ->
try dtls_socket:getopts(Transport, ListenSocket, OptionTags) of
{ok, _} = Result ->
Result;
@@ -982,7 +986,7 @@ setopts(#sslsocket{pid = [Pid|_]}, Options0) when is_pid(Pid), is_list(Options0)
_:_ ->
{error, {options, {not_a_proplist, Options0}}}
end;
-setopts(#sslsocket{pid = {dtls, #config{transport_info = {Transport,_,_,_}}}} = ListenSocket, Options) when is_list(Options) ->
+setopts(#sslsocket{pid = {dtls, #config{transport_info = {Transport,_,_,_,_}}}} = ListenSocket, Options) when is_list(Options) ->
try dtls_socket:setopts(Transport, ListenSocket, Options) of
ok ->
ok;
@@ -1025,7 +1029,7 @@ getstat(Socket) ->
%%
%% Description: Get one or more statistic options for a socket.
%%--------------------------------------------------------------------
-getstat(#sslsocket{pid = {Listen, #config{transport_info = {Transport, _, _, _}}}}, Options) when is_port(Listen), is_list(Options) ->
+getstat(#sslsocket{pid = {Listen, #config{transport_info = {Transport, _, _, _, _}}}}, Options) when is_port(Listen), is_list(Options) ->
tls_socket:getstat(Transport, Listen, Options);
getstat(#sslsocket{pid = [Pid|_], fd = {Transport, Socket, _, _}}, Options) when is_pid(Pid), is_list(Options) ->
@@ -1162,15 +1166,13 @@ tls_version({3, _} = Version) ->
tls_version({254, _} = Version) ->
dtls_v1:corresponding_tls_version(Version).
-
%%--------------------------------------------------------------------
-spec suite_to_str(erl_cipher_suite()) -> string().
%%
%% Description: Return the string representation of a cipher suite.
%%--------------------------------------------------------------------
suite_to_str(Cipher) ->
- ssl_cipher_format:suite_to_str(Cipher).
-
+ ssl_cipher_format:suite_map_to_str(Cipher).
%%%--------------------------------------------------------------
%%% Internal functions
@@ -1810,10 +1812,10 @@ binary_cipher_suites(Version, []) ->
%% not require explicit configuration
default_binary_suites(Version);
binary_cipher_suites(Version, [Map|_] = Ciphers0) when is_map(Map) ->
- Ciphers = [ssl_cipher_format:suite(C) || C <- Ciphers0],
+ Ciphers = [ssl_cipher_format:suite_map_to_bin(C) || C <- Ciphers0],
binary_cipher_suites(Version, Ciphers);
binary_cipher_suites(Version, [Tuple|_] = Ciphers0) when is_tuple(Tuple) ->
- Ciphers = [ssl_cipher_format:suite(tuple_to_map(C)) || C <- Ciphers0],
+ Ciphers = [ssl_cipher_format:suite_map_to_bin(tuple_to_map(C)) || C <- Ciphers0],
binary_cipher_suites(Version, Ciphers);
binary_cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0) ->
All = ssl_cipher:all_suites(Version) ++
@@ -1828,11 +1830,11 @@ binary_cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0)
end;
binary_cipher_suites(Version, [Head | _] = Ciphers0) when is_list(Head) ->
%% Format: ["RC4-SHA","RC4-MD5"]
- Ciphers = [ssl_cipher_format:openssl_suite(C) || C <- Ciphers0],
+ Ciphers = [ssl_cipher_format:suite_openssl_str_to_map(C) || C <- Ciphers0],
binary_cipher_suites(Version, Ciphers);
binary_cipher_suites(Version, Ciphers0) ->
%% Format: "RC4-SHA:RC4-MD5"
- Ciphers = [ssl_cipher_format:openssl_suite(C) || C <- string:lexemes(Ciphers0, ":")],
+ Ciphers = [ssl_cipher_format:suite_openssl_str_to_map(C) || C <- string:lexemes(Ciphers0, ":")],
binary_cipher_suites(Version, Ciphers).
default_binary_suites(Version) ->
@@ -2137,7 +2139,7 @@ default_option_role(_,_,_) ->
default_cb_info(tls) ->
{gen_tcp, tcp, tcp_closed, tcp_error, tcp_passive};
default_cb_info(dtls) ->
- {gen_udp, udp, udp_closed, udp_error}.
+ {gen_udp, udp, udp_closed, udp_error, udp_passive}.
include_security_info([]) ->
false;
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index fe8736d2df..21db887bb5 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -35,7 +35,7 @@
-include_lib("public_key/include/public_key.hrl").
-export([security_parameters/2, security_parameters/3, security_parameters_1_3/2,
- cipher_init/3, nonce_seed/2, decipher/6, cipher/5, aead_encrypt/5, aead_decrypt/6,
+ cipher_init/3, nonce_seed/2, decipher/6, cipher/5, aead_encrypt/6, aead_decrypt/6,
suites/1, all_suites/1, crypto_support_filters/0,
chacha_suites/1, anonymous_suites/1, psk_suites/1, psk_suites_anon/1,
srp_suites/0, srp_suites_anon/0,
@@ -76,7 +76,7 @@ security_parameters(?TLS_NULL_WITH_NULL_NULL = CipherSuite, SecParams) ->
%%-------------------------------------------------------------------
security_parameters(Version, CipherSuite, SecParams) ->
#{cipher := Cipher, mac := Hash,
- prf := PrfHashAlg} = ssl_cipher_format:suite_definition(CipherSuite),
+ prf := PrfHashAlg} = ssl_cipher_format:suite_bin_to_map(CipherSuite),
SecParams#security_parameters{
cipher_suite = CipherSuite,
bulk_cipher_algorithm = bulk_cipher_algorithm(Cipher),
@@ -91,7 +91,7 @@ security_parameters(Version, CipherSuite, SecParams) ->
security_parameters_1_3(SecParams, CipherSuite) ->
#{cipher := Cipher, prf := PrfHashAlg} =
- ssl_cipher_format:suite_definition(CipherSuite),
+ ssl_cipher_format:suite_bin_to_map(CipherSuite),
SecParams#security_parameters{
cipher_suite = CipherSuite,
bulk_cipher_algorithm = bulk_cipher_algorithm(Cipher),
@@ -106,9 +106,13 @@ security_parameters_1_3(SecParams, CipherSuite) ->
cipher_init(?RC4, IV, Key) ->
State = crypto:stream_init(rc4, Key),
#cipher_state{iv = IV, key = Key, state = State};
-cipher_init(?AES_GCM, IV, Key) ->
+cipher_init(Type, IV, Key) when Type == ?AES_GCM;
+ Type == ?AES_CCM ->
<<Nonce:64>> = random_bytes(8),
#cipher_state{iv = IV, key = Key, nonce = Nonce, tag_len = 16};
+cipher_init(?AES_CCM_8, IV, Key) ->
+ <<Nonce:64>> = random_bytes(8),
+ #cipher_state{iv = IV, key = Key, nonce = Nonce, tag_len = 8};
cipher_init(?CHACHA20_POLY1305, IV, Key) ->
#cipher_state{iv = IV, key = Key, tag_len = 16};
cipher_init(_BCA, IV, Key) ->
@@ -148,14 +152,18 @@ cipher(?AES_CBC, CipherState, Mac, Fragment, Version) ->
crypto:block_encrypt(aes_cbc256, Key, IV, T)
end, block_size(aes_128_cbc), CipherState, Mac, Fragment, Version).
-aead_encrypt(Type, Key, Nonce, Fragment, AdditionalData) ->
- crypto:block_encrypt(aead_type(Type), Key, Nonce, {AdditionalData, Fragment}).
+aead_encrypt(Type, Key, Nonce, Fragment, AdditionalData, TagLen) ->
+ crypto:block_encrypt(aead_type(Type), Key, Nonce, {AdditionalData, Fragment, TagLen}).
aead_decrypt(Type, Key, Nonce, CipherText, CipherTag, AdditionalData) ->
crypto:block_decrypt(aead_type(Type), Key, Nonce, {AdditionalData, CipherText, CipherTag}).
aead_type(?AES_GCM) ->
aes_gcm;
+aead_type(?AES_CCM) ->
+ aes_ccm;
+aead_type(?AES_CCM_8) ->
+ aes_ccm;
aead_type(?CHACHA20_POLY1305) ->
chacha20_poly1305.
@@ -311,8 +319,7 @@ anonymous_suites({254, _} = Version) ->
dtls_v1:anonymous_suites(Version);
anonymous_suites(4) ->
[]; %% Raw public key negotiation may be used instead
-anonymous_suites(N)
- when N >= 3 ->
+anonymous_suites( 3 = N) ->
psk_suites_anon(N) ++
[?TLS_DH_anon_WITH_AES_128_GCM_SHA256,
?TLS_DH_anon_WITH_AES_256_GCM_SHA384,
@@ -347,8 +354,7 @@ psk_suites({3, N}) ->
psk_suites(N);
psk_suites(4) ->
[]; %% TODO Add new PSK, PSK_(EC)DHE suites
-psk_suites(N)
- when N >= 3 ->
+psk_suites(3) ->
[
?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
@@ -369,20 +375,32 @@ psk_suites(_) ->
%%--------------------------------------------------------------------
psk_suites_anon({3, N}) ->
psk_suites_anon(N);
-psk_suites_anon(N)
- when N >= 3 ->
+psk_suites_anon(3) ->
[
?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
?TLS_PSK_WITH_AES_256_GCM_SHA384,
?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
?TLS_PSK_WITH_AES_256_CBC_SHA384,
+ ?TLS_DHE_PSK_WITH_AES_256_CCM,
+ ?TLS_PSK_DHE_WITH_AES_256_CCM_8,
+ ?TLS_PSK_WITH_AES_256_CCM,
+ ?TLS_PSK_WITH_AES_256_CCM_8,
?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256,
+ ?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256,
+ ?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256,
?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
?TLS_PSK_WITH_AES_128_GCM_SHA256,
+ ?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256,
+ ?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256,
?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
- ?TLS_PSK_WITH_AES_128_CBC_SHA256
+ ?TLS_PSK_WITH_AES_128_CBC_SHA256,
+ ?TLS_DHE_PSK_WITH_AES_128_CCM,
+ ?TLS_PSK_DHE_WITH_AES_128_CCM_8,
+ ?TLS_PSK_WITH_AES_128_CCM,
+ ?TLS_PSK_WITH_AES_128_CCM_8,
+ ?TLS_ECDHE_PSK_WITH_RC4_128_SHA
] ++ psk_suites_anon(0);
psk_suites_anon(_) ->
[?TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
@@ -531,7 +549,7 @@ filter_suite(#{key_exchange := KeyExchange,
all_filters(Hash, HashFilters) andalso
all_filters(Prf, PrfFilters);
filter_suite(Suite, Filters) ->
- filter_suite(ssl_cipher_format:suite_definition(Suite), Filters).
+ filter_suite(ssl_cipher_format:suite_bin_to_map(Suite), Filters).
%%--------------------------------------------------------------------
-spec filter_suites([ssl:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()]) ->
@@ -589,7 +607,7 @@ is_acceptable_keyexchange(dhe_rsa, Algos) ->
proplists:get_bool(dh, Algos) andalso
proplists:get_bool(rsa, Algos);
is_acceptable_keyexchange(KeyExchange, Algos) when KeyExchange == ecdh_anon;
- KeyExchange == ecdhe_psk ->
+ KeyExchange == ecdhe_psk ->
proplists:get_bool(ecdh, Algos);
is_acceptable_keyexchange(KeyExchange, Algos) when KeyExchange == ecdh_ecdsa;
KeyExchange == ecdhe_ecdsa ->
@@ -629,6 +647,12 @@ is_acceptable_cipher(Cipher, Algos)
when Cipher == aes_128_gcm;
Cipher == aes_256_gcm ->
proplists:get_bool(aes_gcm, Algos);
+is_acceptable_cipher(Cipher, Algos)
+ when Cipher == aes_128_ccm;
+ Cipher == aes_256_ccm;
+ Cipher == aes_128_ccm_8;
+ Cipher == aes_256_ccm_8 ->
+ proplists:get_bool(aes_ccm, Algos);
is_acceptable_cipher(Cipher, Algos) ->
proplists:get_bool(Cipher, Algos).
@@ -721,6 +745,12 @@ bulk_cipher_algorithm(Cipher) when Cipher == aes_128_cbc;
bulk_cipher_algorithm(Cipher) when Cipher == aes_128_gcm;
Cipher == aes_256_gcm ->
?AES_GCM;
+bulk_cipher_algorithm(Cipher) when Cipher == aes_128_ccm;
+ Cipher == aes_256_ccm ->
+ ?AES_CCM;
+bulk_cipher_algorithm(Cipher) when Cipher == aes_128_ccm_8;
+ Cipher == aes_256_ccm_8 ->
+ ?AES_CCM_8;
bulk_cipher_algorithm(chacha20_poly1305) ->
?CHACHA20_POLY1305.
@@ -735,6 +765,10 @@ type(Cipher) when Cipher == des_cbc;
?BLOCK;
type(Cipher) when Cipher == aes_128_gcm;
Cipher == aes_256_gcm;
+ Cipher == aes_128_ccm;
+ Cipher == aes_256_ccm;
+ Cipher == aes_128_ccm_8;
+ Cipher == aes_256_ccm_8;
Cipher == chacha20_poly1305 ->
?AEAD.
@@ -752,8 +786,16 @@ key_material(aes_256_cbc) ->
32;
key_material(aes_128_gcm) ->
16;
+key_material(aes_128_ccm) ->
+ 16;
+key_material(aes_128_ccm_8) ->
+ 16;
key_material(aes_256_gcm) ->
32;
+key_material(aes_256_ccm_8) ->
+ 32;
+key_material(aes_256_ccm) ->
+ 32;
key_material(chacha20_poly1305) ->
32.
@@ -769,6 +811,10 @@ expanded_key_material(Cipher) when Cipher == aes_128_cbc;
Cipher == aes_256_cbc;
Cipher == aes_128_gcm;
Cipher == aes_256_gcm;
+ Cipher == aes_128_ccm;
+ Cipher == aes_256_ccm;
+ Cipher == aes_128_ccm_8;
+ Cipher == aes_256_ccm_8;
Cipher == chacha20_poly1305 ->
unknown.
@@ -778,22 +824,31 @@ effective_key_bits(des_cbc) ->
56;
effective_key_bits(Cipher) when Cipher == rc4_128;
Cipher == aes_128_cbc;
- Cipher == aes_128_gcm ->
+ Cipher == aes_128_gcm;
+ Cipher == aes_128_ccm;
+ Cipher == aes_128_ccm_8 ->
128;
effective_key_bits('3des_ede_cbc') ->
168;
effective_key_bits(Cipher) when Cipher == aes_256_cbc;
Cipher == aes_256_gcm;
+ Cipher == aes_256_ccm;
+ Cipher == aes_256_ccm_8;
Cipher == chacha20_poly1305 ->
256.
iv_size(Cipher) when Cipher == null;
- Cipher == rc4_128;
- Cipher == chacha20_poly1305->
+ Cipher == rc4_128 ->
0;
iv_size(Cipher) when Cipher == aes_128_gcm;
- Cipher == aes_256_gcm ->
+ Cipher == aes_256_gcm;
+ Cipher == aes_128_ccm;
+ Cipher == aes_256_ccm;
+ Cipher == aes_128_ccm_8;
+ Cipher == aes_256_ccm_8 ->
4;
+iv_size(chacha20_poly1305) ->
+ 12;
iv_size(Cipher) ->
block_size(Cipher).
@@ -804,6 +859,10 @@ block_size(Cipher) when Cipher == aes_128_cbc;
Cipher == aes_256_cbc;
Cipher == aes_128_gcm;
Cipher == aes_256_gcm;
+ Cipher == aes_128_ccm;
+ Cipher == aes_256_ccm;
+ Cipher == aes_128_ccm_8;
+ Cipher == aes_256_ccm_8;
Cipher == chacha20_poly1305 ->
16.
@@ -880,6 +939,11 @@ 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?
diff --git a/lib/ssl/src/ssl_cipher.hrl b/lib/ssl/src/ssl_cipher.hrl
index 00822ad9de..9c5e2f80a9 100644
--- a/lib/ssl/src/ssl_cipher.hrl
+++ b/lib/ssl/src/ssl_cipher.hrl
@@ -601,16 +601,82 @@
%% TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = {0xC0,0x32};
-define(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, <<?BYTE(16#C0), ?BYTE(16#32)>>).
-%%% Chacha20/Poly1305 Suites draft-agl-tls-chacha20poly1305-04
-%% TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = {0xcc, 0x13}
--define(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#13)>>).
+%%% ChaCha20-Poly1305 Cipher Suites for Transport Layer Security (TLS) RFC7905
-%% TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = {0xcc, 0x14}
--define(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#14)>>).
+%% TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = {0xCC, 0xA8}
+-define(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#A8)>>).
+
+%% TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = {0xCC, 0xA9}
+-define(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#A9)>>).
+
+%% TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = {0xCC, 0xAA}
+-define(TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#AA)>>).
+
+%% TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 = {0xCC, 0xAB}
+-define(TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#AB)>>).
+
+%% TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = {0xCC, 0xAC}
+-define(TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#AC)>>).
+
+%% TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = {0xCC, 0xAD}
+-define(TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#AD)>>).
+
+%% TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 = {0xCC, 0xAE}
+-define(TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#AE)>>).
+
+
+
+%% RFC 6655 - TLS-1.2 cipher suites
+
+%% TLS_RSA_WITH_AES_128_CCM = {0xC0,0x9C}
+-define(TLS_RSA_WITH_AES_128_CCM, <<?BYTE(16#C0), ?BYTE(16#9C)>>).
+
+%% TLS_RSA_WITH_AES_256_CCM = {0xC0,0x9D}
+-define(TLS_RSA_WITH_AES_256_CCM, <<?BYTE(16#C0), ?BYTE(16#9D)>>).
+
+%% TLS_DHE_RSA_WITH_AES_256_CCM = {0xC0,0x9E}
+-define(TLS_DHE_RSA_WITH_AES_256_CCM, <<?BYTE(16#C0), ?BYTE(16#9E)>>).
+
+%% TLS_DHE_RSA_WITH_AES_128_CCM = {0xC0,0x9F}
+-define(TLS_DHE_RSA_WITH_AES_128_CCM, <<?BYTE(16#C0), ?BYTE(16#9F)>>).
+
+%% TLS_RSA_WITH_AES_256_CCM_8 = {0xC0,0x9A0}
+-define(TLS_RSA_WITH_AES_256_CCM_8, <<?BYTE(16#C0), ?BYTE(16#A0)>>).
+
+%% TLS_RSA_WITH_AES_128_CCM_8 = {0xC0,0xA1}
+-define(TLS_RSA_WITH_AES_128_CCM_8, <<?BYTE(16#C0), ?BYTE(16#A1)>>).
+
+%% TLS_DHE_RSA_WITH_AES_128_CCM_8 = {0xC0,0xA2}
+-define(TLS_DHE_RSA_WITH_AES_128_CCM_8, <<?BYTE(16#C0), ?BYTE(16#A2)>>).
+
+%% TLS_DHE_RSA_WITH_AES_256_CCM_8 = {0xC0,0xA3}
+-define(TLS_DHE_RSA_WITH_AES_256_CCM_8, <<?BYTE(16#C0), ?BYTE(16#A3)>>).
+
+%% TLS_PSK_WITH_AES_128_CCM = {0xC0,0xA4}
+-define(TLS_PSK_WITH_AES_128_CCM, <<?BYTE(16#C0), ?BYTE(16#A4)>>).
+
+%% TLS_PSK_WITH_AES_256_CCM = {0xC0,0xA5)
+-define(TLS_PSK_WITH_AES_256_CCM, <<?BYTE(16#C0), ?BYTE(16#A5)>>).
+
+%% TLS_DHE_PSK_WITH_AES_128_CCM = {0xC0,0xA6}
+-define(TLS_DHE_PSK_WITH_AES_128_CCM, <<?BYTE(16#C0), ?BYTE(16#A6)>>).
+
+%% TLS_DHE_PSK_WITH_AES_256_CCM = {0xC0,0xA7}
+-define(TLS_DHE_PSK_WITH_AES_256_CCM, <<?BYTE(16#C0), ?BYTE(16#A7)>>).
+
+%% TLS_PSK_WITH_AES_128_CCM_8 = {0xC0,0xA8}
+-define(TLS_PSK_WITH_AES_128_CCM_8, <<?BYTE(16#C0), ?BYTE(16#A8)>>).
+
+%% TLS_PSK_WITH_AES_256_CCM_8 = {0xC0,0xA9)
+-define(TLS_PSK_WITH_AES_256_CCM_8, <<?BYTE(16#C0), ?BYTE(16#A9)>>).
+
+%% TLS_PSK_DHE_WITH_AES_128_CCM_8 = {0xC0,0xAA}
+-define(TLS_PSK_DHE_WITH_AES_128_CCM_8, <<?BYTE(16#C0), ?BYTE(16#AA)>>).
+
+%% TLS_PSK_DHE_WITH_AES_256_CCM_8 = << ?BYTE(0xC0,0xAB}
+-define(TLS_PSK_DHE_WITH_AES_256_CCM_8, <<?BYTE(16#C0),?BYTE(16#AB)>>).
-%% TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = {0xcc, 0x15}
--define(TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#15)>>).
%%% TLS 1.3 cipher suites RFC8446
diff --git a/lib/ssl/src/ssl_cipher_format.erl b/lib/ssl/src/ssl_cipher_format.erl
index b592295d56..887eb6c653 100644
--- a/lib/ssl/src/ssl_cipher_format.erl
+++ b/lib/ssl/src/ssl_cipher_format.erl
@@ -48,48 +48,134 @@
-type openssl_cipher_suite() :: string().
--export([suite_to_str/1, suite_definition/1, suite/1, erl_suite_definition/1,
- openssl_suite/1, openssl_suite_name/1]).
+-export([suite_map_to_bin/1, %% Binary format
+ suite_bin_to_map/1, %% Erlang API format
+ suite_map_to_str/1, %% RFC string
+ suite_str_to_map/1,
+ suite_map_to_openssl_str/1, %% OpenSSL name
+ suite_openssl_str_to_map/1,
+ suite_legacy/1 %% Erlang legacy format
+ ]).
%%--------------------------------------------------------------------
--spec suite_to_str(internal_erl_cipher_suite()) -> string().
+-spec suite_map_to_str(internal_erl_cipher_suite()) -> string().
%%
%% Description: Return the string representation of a cipher suite.
%%--------------------------------------------------------------------
-suite_to_str(#{key_exchange := null,
+suite_map_to_str(#{key_exchange := null,
cipher := null,
mac := null,
prf := null}) ->
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
-suite_to_str(#{key_exchange := any,
+suite_map_to_str(#{key_exchange := any,
cipher := Cipher,
mac := aead,
prf := PRF}) ->
"TLS_" ++ string:to_upper(atom_to_list(Cipher)) ++
"_" ++ string:to_upper(atom_to_list(PRF));
-suite_to_str(#{key_exchange := Kex,
+suite_map_to_str(#{key_exchange := Kex,
cipher := Cipher,
mac := aead,
prf := PRF}) ->
"TLS_" ++ string:to_upper(atom_to_list(Kex)) ++
"_WITH_" ++ string:to_upper(atom_to_list(Cipher)) ++
"_" ++ string:to_upper(atom_to_list(PRF));
-suite_to_str(#{key_exchange := Kex,
+suite_map_to_str(#{key_exchange := Kex,
cipher := Cipher,
mac := Mac}) ->
"TLS_" ++ string:to_upper(atom_to_list(Kex)) ++
"_WITH_" ++ string:to_upper(atom_to_list(Cipher)) ++
"_" ++ string:to_upper(atom_to_list(Mac)).
+suite_str_to_map("TLS_EMPTY_RENEGOTIATION_INFO_SCSV") ->
+ #{key_exchange => null,
+ cipher => null,
+ mac => null,
+ prf => null};
+suite_str_to_map(SuiteStr)->
+ Str0 = string:trim(SuiteStr, leading, "TLS_"),
+ case string:split(Str0, "_WITH_") of
+ [Rest] ->
+ tls_1_3_suite_str_to_map(Rest);
+ [Kex| Rest] ->
+ pre_tls_1_3_suite_str_to_map(Kex, Rest)
+ end.
+
+suite_map_to_openssl_str(#{key_exchange := any,
+ mac := aead} = Suite) ->
+ %% TLS 1.3 OpenSSL finally use RFC names
+ suite_map_to_str(Suite);
+suite_map_to_openssl_str(#{key_exchange := null} = Suite) ->
+ %% TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+ suite_map_to_str(Suite);
+suite_map_to_openssl_str(#{key_exchange := Kex,
+ cipher := chacha20_poly1305 = Cipher,
+ mac := aead}) ->
+ openssl_suite_start(string:to_upper(atom_to_list(Kex)))
+ ++ openssl_cipher_name(Kex, string:to_upper(atom_to_list(Cipher)));
+suite_map_to_openssl_str(#{key_exchange := Kex,
+ cipher := Cipher,
+ mac := aead,
+ prf := PRF}) ->
+ openssl_suite_start(string:to_upper(atom_to_list(Kex)))
+ ++ openssl_cipher_name(Kex, string:to_upper(atom_to_list(Cipher))) ++
+ "-" ++ string:to_upper(atom_to_list(PRF));
+suite_map_to_openssl_str(#{key_exchange := Kex,
+ cipher := Cipher,
+ mac := Mac}) ->
+ openssl_suite_start(string:to_upper(atom_to_list(Kex)))
+ ++ openssl_cipher_name(Kex, string:to_upper(atom_to_list(Cipher))) ++
+ "-" ++ string:to_upper(atom_to_list(Mac)).
+
+
+suite_openssl_str_to_map("TLS_" ++ _ = SuiteStr) ->
+ suite_str_to_map(SuiteStr);
+suite_openssl_str_to_map("DHE-RSA-" ++ Rest) ->
+ suite_openssl_str_to_map("DHE-RSA", Rest);
+suite_openssl_str_to_map("DHE-DSS-" ++ Rest) ->
+ suite_openssl_str_to_map("DHE-DSS", Rest);
+suite_openssl_str_to_map("EDH-RSA-" ++ Rest) ->
+ suite_openssl_str_to_map("DHE-RSA", Rest);
+suite_openssl_str_to_map("EDH-DSS-" ++ Rest) ->
+ suite_openssl_str_to_map("DHE-DSS", Rest);
+suite_openssl_str_to_map("DES" ++ _ = Rest) ->
+ suite_openssl_str_to_map("RSA", Rest);
+suite_openssl_str_to_map("AES" ++ _ = Rest) ->
+ suite_openssl_str_to_map("RSA", Rest);
+suite_openssl_str_to_map("RC4" ++ _ = Rest) ->
+ suite_openssl_str_to_map("RSA", Rest);
+suite_openssl_str_to_map("ECDH-RSA-" ++ Rest) ->
+ suite_openssl_str_to_map("ECDH-RSA", Rest);
+suite_openssl_str_to_map("ECDH-ECDSA-" ++ Rest) ->
+ suite_openssl_str_to_map("ECDH-ECDSA", Rest);
+suite_openssl_str_to_map("ECDHE-RSA-" ++ Rest) ->
+ suite_openssl_str_to_map("ECDHE-RSA", Rest);
+suite_openssl_str_to_map("ECDHE-ECDSA-" ++ Rest) ->
+ suite_openssl_str_to_map("ECDHE-ECDSA", Rest);
+suite_openssl_str_to_map("RSA-PSK-" ++ Rest) ->
+ suite_openssl_str_to_map("RSA-PSK", Rest);
+suite_openssl_str_to_map("RSA-" ++ Rest) ->
+ suite_openssl_str_to_map("RSA", Rest);
+suite_openssl_str_to_map("DHE-PSK-" ++ Rest) ->
+ suite_openssl_str_to_map("DHE-PSK", Rest);
+suite_openssl_str_to_map("ECDHE-PSK-" ++ Rest) ->
+ suite_openssl_str_to_map("ECDHE-PSK", Rest);
+suite_openssl_str_to_map("PSK-" ++ Rest) ->
+ suite_openssl_str_to_map("PSK", Rest);
+suite_openssl_str_to_map("SRP-RSA-" ++ Rest) ->
+ suite_openssl_str_to_map("SRP-RSA", Rest);
+suite_openssl_str_to_map("SRP-" ++ Rest) ->
+ suite_openssl_str_to_map("SRP", Rest).
+
%%--------------------------------------------------------------------
--spec suite_definition(cipher_suite()) -> internal_erl_cipher_suite().
+-spec suite_bin_to_map(cipher_suite()) -> internal_erl_cipher_suite().
%%
%% Description: Return erlang cipher suite definition.
%% Note: Currently not supported suites are commented away.
%% They should be supported or removed in the future.
%%-------------------------------------------------------------------
%% TLS v1.1 suites
-suite_definition(?TLS_NULL_WITH_NULL_NULL) ->
+suite_bin_to_map(?TLS_NULL_WITH_NULL_NULL) ->
#{key_exchange => null,
cipher => null,
mac => null,
@@ -97,111 +183,111 @@ suite_definition(?TLS_NULL_WITH_NULL_NULL) ->
%% RFC 5746 - Not a real cipher suite used to signal empty "renegotiation_info" extension
%% to avoid handshake failure from old servers that do not ignore
%% hello extension data as they should.
-suite_definition(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV) ->
+suite_bin_to_map(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV) ->
#{key_exchange => null,
cipher => null,
mac => null,
prf => null};
-suite_definition(?TLS_RSA_WITH_RC4_128_MD5) ->
+suite_bin_to_map(?TLS_RSA_WITH_RC4_128_MD5) ->
#{key_exchange => rsa,
cipher => rc4_128,
mac => md5,
prf => default_prf};
-suite_definition(?TLS_RSA_WITH_RC4_128_SHA) ->
+suite_bin_to_map(?TLS_RSA_WITH_RC4_128_SHA) ->
#{key_exchange => rsa,
cipher => rc4_128,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_RSA_WITH_DES_CBC_SHA) ->
+suite_bin_to_map(?TLS_RSA_WITH_DES_CBC_SHA) ->
#{key_exchange => rsa,
cipher => des_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => rsa,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_DES_CBC_SHA) ->
+suite_bin_to_map(?TLS_DHE_DSS_WITH_DES_CBC_SHA) ->
#{key_exchange => dhe_dss,
cipher => des_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => dhe_dss,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
+suite_bin_to_map(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
#{key_exchange => dhe_rsa,
cipher => des_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => dhe_rsa,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
%%% TSL V1.1 AES suites
-suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
#{key_exchange => rsa,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
#{key_exchange => dhe_dss,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
#{key_exchange => dhe_rsa,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
#{key_exchange => rsa,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
#{key_exchange => dhe_dss,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
#{key_exchange => dhe_rsa,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
%% TLS v1.2 suites
-%% suite_definition(?TLS_RSA_WITH_NULL_SHA) ->
+%% suite_bin_to_map(?TLS_RSA_WITH_NULL_SHA) ->
%% {rsa, null, sha, default_prf};
-suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
+suite_bin_to_map(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
#{key_exchange => rsa,
cipher => aes_128_cbc,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
+suite_bin_to_map(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
#{key_exchange => rsa,
cipher => aes_256_cbc,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
+suite_bin_to_map(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
#{key_exchange => dhe_dss,
cipher => aes_128_cbc,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
+suite_bin_to_map(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
#{key_exchange => dhe_rsa,
cipher => aes_128_cbc,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
+suite_bin_to_map(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
#{key_exchange => dhe_dss,
cipher => aes_256_cbc,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
+suite_bin_to_map(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
#{key_exchange => dhe_rsa,
cipher => aes_256_cbc,
mac => sha256,
@@ -213,638 +299,683 @@ suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
%% TLS_DH_RSA_WITH_AES_256_CBC_SHA256 DH_RSA AES_256_CBC SHA256
%%% DH-ANON deprecated by TLS spec and not available
%%% by default, but good for testing purposes.
-suite_definition(?TLS_DH_anon_WITH_RC4_128_MD5) ->
+suite_bin_to_map(?TLS_DH_anon_WITH_RC4_128_MD5) ->
#{key_exchange => dh_anon,
cipher => rc4_128,
mac => md5,
prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_DES_CBC_SHA) ->
+suite_bin_to_map(?TLS_DH_anon_WITH_DES_CBC_SHA) ->
#{key_exchange => dh_anon,
cipher => des_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => dh_anon,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_DH_anon_WITH_AES_128_CBC_SHA) ->
#{key_exchange => dh_anon,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_DH_anon_WITH_AES_256_CBC_SHA) ->
#{key_exchange => dh_anon,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA256) ->
+suite_bin_to_map(?TLS_DH_anon_WITH_AES_128_CBC_SHA256) ->
#{key_exchange => dh_anon,
cipher => aes_128_cbc,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA256) ->
+suite_bin_to_map(?TLS_DH_anon_WITH_AES_256_CBC_SHA256) ->
#{key_exchange => dh_anon,
cipher => aes_256_cbc,
mac => sha256,
prf => default_prf};
%%% PSK Cipher Suites RFC 4279
-suite_definition(?TLS_PSK_WITH_RC4_128_SHA) ->
+suite_bin_to_map(?TLS_PSK_WITH_RC4_128_SHA) ->
#{key_exchange => psk,
cipher => rc4_128,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => psk,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
#{key_exchange => psk,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
#{key_exchange => psk,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_RC4_128_SHA) ->
+suite_bin_to_map(?TLS_DHE_PSK_WITH_RC4_128_SHA) ->
#{key_exchange => dhe_psk,
cipher => rc4_128,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => dhe_psk,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA) ->
#{key_exchange => dhe_psk,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA) ->
#{key_exchange => dhe_psk,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_RC4_128_SHA) ->
+suite_bin_to_map(?TLS_RSA_PSK_WITH_RC4_128_SHA) ->
#{key_exchange => rsa_psk,
cipher => rc4_128,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => rsa_psk,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA) ->
#{key_exchange => rsa_psk,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA) ->
#{key_exchange => rsa_psk,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
%%% PSK NULL Cipher Suites RFC 4785
-suite_definition(?TLS_PSK_WITH_NULL_SHA) ->
+suite_bin_to_map(?TLS_PSK_WITH_NULL_SHA) ->
#{key_exchange => psk,
cipher => null,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA) ->
+suite_bin_to_map(?TLS_DHE_PSK_WITH_NULL_SHA) ->
#{key_exchange => dhe_psk,
cipher => null,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA) ->
+suite_bin_to_map(?TLS_RSA_PSK_WITH_NULL_SHA) ->
#{key_exchange => rsa_psk,
cipher => null,
mac => sha,
prf => default_prf};
%%% TLS 1.2 PSK Cipher Suites RFC 5487
-suite_definition(?TLS_PSK_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_PSK_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => psk,
cipher => aes_128_gcm,
mac => aead,
prf => sha256};
-suite_definition(?TLS_PSK_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_PSK_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => psk,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
-suite_definition(?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => dhe_psk,
cipher => aes_128_gcm,
mac => aead,
prf => sha256};
-suite_definition(?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => dhe_psk,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
-suite_definition(?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => rsa_psk,
cipher => aes_128_gcm,
mac => aead,
prf => sha256};
-suite_definition(?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => rsa_psk,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
-suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA256) ->
+suite_bin_to_map(?TLS_PSK_WITH_AES_128_CBC_SHA256) ->
#{key_exchange => psk,
cipher => aes_128_cbc,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA384) ->
+suite_bin_to_map(?TLS_PSK_WITH_AES_256_CBC_SHA384) ->
#{key_exchange => psk,
cipher => aes_256_cbc,
mac => sha384,
prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256) ->
+suite_bin_to_map(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256) ->
#{key_exchange => dhe_psk,
cipher => aes_128_cbc,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384) ->
+suite_bin_to_map(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384) ->
#{key_exchange => dhe_psk,
cipher => aes_256_cbc,
mac => sha384,
prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256) ->
+suite_bin_to_map(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256) ->
#{key_exchange => rsa_psk,
cipher => aes_128_cbc,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384) ->
+suite_bin_to_map(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384) ->
#{key_exchange => rsa_psk,
cipher => aes_256_cbc,
mac => sha384,
prf => default_prf};
-suite_definition(?TLS_PSK_WITH_NULL_SHA256) ->
+suite_bin_to_map(?TLS_PSK_WITH_NULL_SHA256) ->
#{key_exchange => psk,
cipher => null,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_PSK_WITH_NULL_SHA384) ->
+suite_bin_to_map(?TLS_PSK_WITH_NULL_SHA384) ->
#{key_exchange => psk,
cipher => null,
mac => sha384,
prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA256) ->
+suite_bin_to_map(?TLS_DHE_PSK_WITH_NULL_SHA256) ->
#{key_exchange => dhe_psk,
cipher => null,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA384) ->
+suite_bin_to_map(?TLS_DHE_PSK_WITH_NULL_SHA384) ->
#{key_exchange => dhe_psk,
cipher => null,
mac => sha384,
prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA256) ->
+suite_bin_to_map(?TLS_RSA_PSK_WITH_NULL_SHA256) ->
#{key_exchange => rsa_psk,
cipher => null,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA384) ->
+suite_bin_to_map(?TLS_RSA_PSK_WITH_NULL_SHA384) ->
#{key_exchange => rsa_psk,
cipher => null,
mac => sha384,
prf => default_prf};
%%% ECDHE PSK Cipher Suites RFC 5489
-suite_definition(?TLS_ECDHE_PSK_WITH_RC4_128_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_PSK_WITH_RC4_128_SHA) ->
#{key_exchange => ecdhe_psk,
cipher => rc4_128,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => ecdhe_psk,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA) ->
#{key_exchange => ecdhe_psk,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA) ->
#{key_exchange => ecdhe_psk,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256) ->
+suite_bin_to_map(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256) ->
#{key_exchange => ecdhe_psk,
cipher => aes_128_cbc,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384) ->
+suite_bin_to_map(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384) ->
#{key_exchange => ecdhe_psk,
cipher => aes_256_cbc,
mac => sha384,
prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_NULL_SHA256) ->
+suite_bin_to_map(?TLS_ECDHE_PSK_WITH_NULL_SHA256) ->
#{key_exchange => ecdhe_psk,
cipher => null,
mac => sha256,
prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_NULL_SHA384) ->
+suite_bin_to_map(?TLS_ECDHE_PSK_WITH_NULL_SHA384) ->
#{key_exchange => ecdhe_psk,
cipher => null, mac => sha384,
prf => default_prf};
%%% ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites, draft-ietf-tls-ecdhe-psk-aead-05
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => ecdhe_psk,
cipher => aes_128_gcm,
mac => null,
prf => sha256};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => ecdhe_psk,
cipher => aes_256_gcm,
mac => null,
prf => sha384};
-%% suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256) ->
-%% #{key_exchange => ecdhe_psk,
-%% cipher => aes_128_ccm,
-%% mac => null,
-%% prf =>sha256};
-%% suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256) ->
-%% #{key_exchange => ecdhe_psk,
-%% cipher => aes_256_ccm,
-%% mac => null,
-%% prf => sha256};
+suite_bin_to_map(?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_128_ccm,
+ mac => null,
+ prf =>sha256};
+suite_bin_to_map(?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_128_ccm_8,
+ mac => null,
+ prf =>sha256};
%%% SRP Cipher Suites RFC 5054
-suite_definition(?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => srp_anon,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => srp_rsa,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => srp_dss,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_SRP_SHA_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_SRP_SHA_WITH_AES_128_CBC_SHA) ->
#{key_exchange => srp_anon,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
#{key_exchange => srp_rsa,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
#{key_exchange => srp_dss,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_SRP_SHA_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_SRP_SHA_WITH_AES_256_CBC_SHA) ->
#{key_exchange => srp_anon,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
#{key_exchange => srp_rsa,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
#{key_exchange => srp_dss,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
%% RFC 4492 EC TLS suites
-suite_definition(?TLS_ECDH_ECDSA_WITH_NULL_SHA) ->
+suite_bin_to_map(?TLS_ECDH_ECDSA_WITH_NULL_SHA) ->
#{key_exchange => ecdh_ecdsa,
cipher => null,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
+suite_bin_to_map(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
#{key_exchange => ecdh_ecdsa,
cipher => rc4_128,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => ecdh_ecdsa,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
#{key_exchange => ecdh_ecdsa,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
#{key_exchange => ecdh_ecdsa,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_NULL_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_ECDSA_WITH_NULL_SHA) ->
#{key_exchange => ecdhe_ecdsa,
cipher => null,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
#{key_exchange => ecdhe_ecdsa,
cipher => rc4_128,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => ecdhe_ecdsa,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
#{key_exchange => ecdhe_ecdsa,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
#{key_exchange => ecdhe_ecdsa,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_NULL_SHA) ->
+suite_bin_to_map(?TLS_ECDH_RSA_WITH_NULL_SHA) ->
#{key_exchange => ecdh_rsa,
cipher => null,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
+suite_bin_to_map(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
#{key_exchange => ecdh_rsa,
cipher => rc4_128,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => ecdh_rsa,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
#{key_exchange => ecdh_rsa,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
#{key_exchange => ecdh_rsa,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_NULL_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_RSA_WITH_NULL_SHA) ->
#{key_exchange => ecdhe_rsa,
cipher => null,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
#{key_exchange => ecdhe_rsa,
cipher => rc4_128,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => ecdhe_rsa,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
#{key_exchange => ecdhe_rsa,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
#{key_exchange => ecdhe_rsa,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_NULL_SHA) ->
+suite_bin_to_map(?TLS_ECDH_anon_WITH_NULL_SHA) ->
#{key_exchange => ecdh_anon,
cipher => null,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_RC4_128_SHA) ->
+suite_bin_to_map(?TLS_ECDH_anon_WITH_RC4_128_SHA) ->
#{key_exchange => ecdh_anon,
cipher => rc4_128,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA) ->
#{key_exchange => ecdh_anon,
cipher => '3des_ede_cbc',
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_AES_128_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDH_anon_WITH_AES_128_CBC_SHA) ->
#{key_exchange => ecdh_anon,
cipher => aes_128_cbc,
mac => sha,
prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_AES_256_CBC_SHA) ->
+suite_bin_to_map(?TLS_ECDH_anon_WITH_AES_256_CBC_SHA) ->
#{key_exchange => ecdh_anon,
cipher => aes_256_cbc,
mac => sha,
prf => default_prf};
%% RFC 5289 EC TLS suites
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
+suite_bin_to_map(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
#{key_exchange => ecdhe_ecdsa,
cipher => aes_128_cbc,
mac => sha256,
prf => sha256};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
+suite_bin_to_map(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
#{key_exchange => ecdhe_ecdsa,
cipher => aes_256_cbc,
mac => sha384,
prf => sha384};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
+suite_bin_to_map(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
#{key_exchange => ecdh_ecdsa,
cipher => aes_128_cbc,
mac => sha256,
prf => sha256};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
+suite_bin_to_map(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
#{key_exchange => ecdh_ecdsa,
cipher => aes_256_cbc,
mac => sha384,
prf => sha384};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
+suite_bin_to_map(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
#{key_exchange => ecdhe_rsa,
cipher => aes_128_cbc,
mac => sha256,
prf => sha256};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
+suite_bin_to_map(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
#{key_exchange => ecdhe_rsa,
cipher => aes_256_cbc,
mac => sha384,
prf => sha384};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
+suite_bin_to_map(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
#{key_exchange => ecdh_rsa,
cipher => aes_128_cbc,
mac => sha256,
prf => sha256};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
+suite_bin_to_map(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
#{key_exchange => ecdh_rsa,
cipher => aes_256_cbc,
mac => sha384,
prf => sha384};
%% RFC 5288 AES-GCM Cipher Suites
-suite_definition(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => rsa,
cipher => aes_128_gcm,
mac => aead,
prf => sha256};
-suite_definition(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => rsa,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
-suite_definition(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => dhe_rsa,
cipher => aes_128_gcm,
mac => aead,
prf => sha256};
-suite_definition(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => dhe_rsa,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
-suite_definition(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => dh_rsa,
cipher => aes_128_gcm,
mac => aead,
prf => sha256};
-suite_definition(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => dh_rsa,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
-suite_definition(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => dhe_dss,
cipher => aes_128_gcm,
mac => aead,
prf => sha256};
-suite_definition(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => dhe_dss,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
-suite_definition(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => dh_dss,
cipher => aes_128_gcm,
mac => null,
prf => sha256};
-suite_definition(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => dh_dss,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
-suite_definition(?TLS_DH_anon_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_DH_anon_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => dh_anon,
cipher => aes_128_gcm,
mac => aead,
prf => sha256};
-suite_definition(?TLS_DH_anon_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_DH_anon_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => dh_anon,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
%% RFC 5289 ECC AES-GCM Cipher Suites
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => ecdhe_ecdsa,
cipher => aes_128_gcm,
mac => aead,
prf => sha256};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => ecdhe_ecdsa,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => ecdh_ecdsa,
cipher => aes_128_gcm,
mac => aead,
prf => sha256};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => ecdh_ecdsa,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => ecdhe_rsa,
cipher => aes_128_gcm,
mac => aead,
prf => sha256};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => ecdhe_rsa,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
#{key_exchange => ecdh_rsa,
cipher => aes_128_gcm,
mac => aead,
prf => sha256};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
#{key_exchange => ecdh_rsa,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
-%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
-suite_definition(?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
+suite_bin_to_map(?TLS_PSK_WITH_AES_128_CCM) ->
+ #{key_exchange => psk,
+ cipher => aes_128_ccm,
+ mac => aead,
+ prf => sha256};
+suite_bin_to_map(?TLS_PSK_WITH_AES_256_CCM) ->
+ #{key_exchange => psk,
+ cipher => aes_256_ccm,
+ mac => aead,
+ prf => sha256};
+suite_bin_to_map(?TLS_DHE_PSK_WITH_AES_128_CCM) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_128_ccm,
+ mac => aead,
+ prf => sha256};
+suite_bin_to_map(?TLS_DHE_PSK_WITH_AES_256_CCM) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_256_ccm,
+ mac => aead,
+ prf => sha256};
+suite_bin_to_map(?TLS_PSK_WITH_AES_128_CCM_8) ->
+ #{key_exchange => psk,
+ cipher => aes_128_ccm_8,
+ mac => aead,
+ prf => sha256};
+suite_bin_to_map(?TLS_PSK_WITH_AES_256_CCM_8) ->
+ #{key_exchange => psk,
+ cipher => aes_256_ccm_8,
+ mac => aead,
+ prf => sha256};
+suite_bin_to_map(?TLS_PSK_DHE_WITH_AES_128_CCM_8) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_128_ccm_8,
+ mac => aead,
+ prf => sha256};
+suite_bin_to_map(?TLS_PSK_DHE_WITH_AES_256_CCM_8) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_256_ccm_8,
+ mac => aead,
+ prf => sha256};
+suite_bin_to_map(#{key_exchange := psk_dhe,
+ cipher := aes_256_ccm_8,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_PSK_DHE_WITH_AES_256_CCM_8;
+
+% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
+suite_bin_to_map(?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
#{key_exchange => ecdhe_rsa,
cipher => chacha20_poly1305,
mac => aead,
prf => sha256};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) ->
+suite_bin_to_map(?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) ->
#{key_exchange => ecdhe_ecdsa,
cipher => chacha20_poly1305,
mac => aead,
prf => sha256};
-suite_definition(?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
+suite_bin_to_map(?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
#{key_exchange => dhe_rsa,
cipher => chacha20_poly1305,
mac => aead,
prf => sha256};
%% TLS 1.3 Cipher Suites RFC8446
-suite_definition(?TLS_AES_128_GCM_SHA256) ->
+suite_bin_to_map(?TLS_AES_128_GCM_SHA256) ->
#{key_exchange => any,
cipher => aes_128_gcm,
mac => aead,
prf => sha256};
-suite_definition(?TLS_AES_256_GCM_SHA384) ->
+suite_bin_to_map(?TLS_AES_256_GCM_SHA384) ->
#{key_exchange => any,
cipher => aes_256_gcm,
mac => aead,
prf => sha384};
-suite_definition(?TLS_CHACHA20_POLY1305_SHA256) ->
+suite_bin_to_map(?TLS_CHACHA20_POLY1305_SHA256) ->
#{key_exchange => any,
cipher => chacha20_poly1305,
mac => aead,
prf => sha256}.
-%% suite_definition(?TLS_AES_128_CCM_SHA256) ->
-%% #{key_exchange => any,
-%% cipher => aes_128_ccm,
-%% mac => aead,
-%% prf => sha256};
-%% suite_definition(?TLS_AES_128_CCM_8_SHA256) ->
-%% #{key_exchange => any,
+%% suite_bin_to_map(?TLS_AES_128_CCM_SHA256) ->
+%% #{key_exchange => any,
+%% cipher => aes_128_ccm,
+%% mac => aead
+%% prf => sha256};
+%% suite_bin_to_map(?TLS_AES_128_CCM_8_SHA256) ->
+%% #{key_exchange => any,
%% cipher => aes_128_ccm_8,
-%% mac => aead,
-%% prf => sha256}.
-
+%% mac => aead,
+%% prf => sha256}.
%%--------------------------------------------------------------------
--spec erl_suite_definition(cipher_suite() | internal_erl_cipher_suite()) -> old_erl_cipher_suite().
+-spec suite_legacy(cipher_suite() | internal_erl_cipher_suite()) -> old_erl_cipher_suite().
%%
%% Description: Return erlang cipher suite definition. Filters last value
%% for now (compatibility reasons).
%%--------------------------------------------------------------------
-erl_suite_definition(Bin) when is_binary(Bin) ->
- erl_suite_definition(suite_definition(Bin));
-erl_suite_definition(#{key_exchange := KeyExchange, cipher := Cipher,
+suite_legacy(Bin) when is_binary(Bin) ->
+ suite_legacy(suite_bin_to_map(Bin));
+suite_legacy(#{key_exchange := KeyExchange, cipher := Cipher,
mac := Hash, prf := Prf}) ->
case Prf of
default_prf ->
@@ -854,993 +985,896 @@ erl_suite_definition(#{key_exchange := KeyExchange, cipher := Cipher,
end.
%%--------------------------------------------------------------------
--spec suite(internal_erl_cipher_suite()) -> cipher_suite().
+-spec suite_map_to_bin(internal_erl_cipher_suite()) -> cipher_suite().
%%
%% Description: Return TLS cipher suite definition.
%%--------------------------------------------------------------------
%% TLS v1.1 suites
-suite(#{key_exchange := rsa,
+suite_map_to_bin(#{key_exchange := rsa,
cipher := rc4_128,
mac := md5}) ->
?TLS_RSA_WITH_RC4_128_MD5;
-suite(#{key_exchange := rsa,
+suite_map_to_bin(#{key_exchange := rsa,
cipher := rc4_128,
mac := sha}) ->
?TLS_RSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := rsa,
+suite_map_to_bin(#{key_exchange := rsa,
cipher := des_cbc,
mac := sha}) ->
?TLS_RSA_WITH_DES_CBC_SHA;
-suite(#{key_exchange := rsa,
+suite_map_to_bin(#{key_exchange := rsa,
cipher :='3des_ede_cbc',
mac := sha}) ->
?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := dhe_dss,
+suite_map_to_bin(#{key_exchange := dhe_dss,
cipher:= des_cbc,
mac := sha}) ->
?TLS_DHE_DSS_WITH_DES_CBC_SHA;
-suite(#{key_exchange := dhe_dss,
+suite_map_to_bin(#{key_exchange := dhe_dss,
cipher:= '3des_ede_cbc',
mac := sha}) ->
?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := dhe_rsa,
+suite_map_to_bin(#{key_exchange := dhe_rsa,
cipher:= des_cbc,
mac := sha}) ->
?TLS_DHE_RSA_WITH_DES_CBC_SHA;
-suite(#{key_exchange := dhe_rsa,
+suite_map_to_bin(#{key_exchange := dhe_rsa,
cipher:= '3des_ede_cbc',
mac := sha}) ->
?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := dh_anon,
+suite_map_to_bin(#{key_exchange := dh_anon,
cipher:= rc4_128,
mac := md5}) ->
?TLS_DH_anon_WITH_RC4_128_MD5;
-suite(#{key_exchange := dh_anon,
+suite_map_to_bin(#{key_exchange := dh_anon,
cipher:= des_cbc,
mac := sha}) ->
?TLS_DH_anon_WITH_DES_CBC_SHA;
-suite(#{key_exchange := dh_anon,
+suite_map_to_bin(#{key_exchange := dh_anon,
cipher:= '3des_ede_cbc',
mac := sha}) ->
?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
%%% TSL V1.1 AES suites
-suite(#{key_exchange := rsa,
+suite_map_to_bin(#{key_exchange := rsa,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := dhe_dss,
+suite_map_to_bin(#{key_exchange := dhe_dss,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := dhe_rsa,
+suite_map_to_bin(#{key_exchange := dhe_rsa,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := dh_anon,
+suite_map_to_bin(#{key_exchange := dh_anon,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_DH_anon_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := rsa,
+suite_map_to_bin(#{key_exchange := rsa,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := dhe_dss,
+suite_map_to_bin(#{key_exchange := dhe_dss,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := dhe_rsa,
+suite_map_to_bin(#{key_exchange := dhe_rsa,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := dh_anon,
+suite_map_to_bin(#{key_exchange := dh_anon,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_DH_anon_WITH_AES_256_CBC_SHA;
%% TLS v1.2 suites
-suite(#{key_exchange := rsa,
+suite_map_to_bin(#{key_exchange := rsa,
cipher := aes_128_cbc,
mac := sha256}) ->
?TLS_RSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := rsa,
+suite_map_to_bin(#{key_exchange := rsa,
cipher := aes_256_cbc,
mac := sha256}) ->
?TLS_RSA_WITH_AES_256_CBC_SHA256;
-suite(#{key_exchange := dhe_dss,
+suite_map_to_bin(#{key_exchange := dhe_dss,
cipher := aes_128_cbc,
mac := sha256}) ->
?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := dhe_rsa,
+suite_map_to_bin(#{key_exchange := dhe_rsa,
cipher := aes_128_cbc,
mac := sha256}) ->
?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := dhe_dss,
+suite_map_to_bin(#{key_exchange := dhe_dss,
cipher := aes_256_cbc,
mac := sha256}) ->
?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
-suite(#{key_exchange := dhe_rsa,
+suite_map_to_bin(#{key_exchange := dhe_rsa,
cipher := aes_256_cbc,
mac := sha256}) ->
?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
-suite(#{key_exchange := dh_anon,
+suite_map_to_bin(#{key_exchange := dh_anon,
cipher := aes_128_cbc,
mac := sha256}) ->
?TLS_DH_anon_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := dh_anon,
+suite_map_to_bin(#{key_exchange := dh_anon,
cipher := aes_256_cbc,
mac := sha256}) ->
?TLS_DH_anon_WITH_AES_256_CBC_SHA256;
%%% PSK Cipher Suites RFC 4279
-suite(#{key_exchange := psk,
+suite_map_to_bin(#{key_exchange := psk,
cipher := rc4_128,
mac := sha}) ->
?TLS_PSK_WITH_RC4_128_SHA;
-suite(#{key_exchange := psk,
+suite_map_to_bin(#{key_exchange := psk,
cipher := '3des_ede_cbc',
mac := sha}) ->
?TLS_PSK_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := psk,
+suite_map_to_bin(#{key_exchange := psk,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_PSK_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := psk,
+suite_map_to_bin(#{key_exchange := psk,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_PSK_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := dhe_psk,
+suite_map_to_bin(#{key_exchange := dhe_psk,
cipher := rc4_128,
mac := sha}) ->
?TLS_DHE_PSK_WITH_RC4_128_SHA;
-suite(#{key_exchange := dhe_psk,
+suite_map_to_bin(#{key_exchange := dhe_psk,
cipher := '3des_ede_cbc',
mac := sha}) ->
?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := dhe_psk,
+suite_map_to_bin(#{key_exchange := dhe_psk,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_DHE_PSK_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := dhe_psk,
+suite_map_to_bin(#{key_exchange := dhe_psk,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_DHE_PSK_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := rsa_psk,
+suite_map_to_bin(#{key_exchange := rsa_psk,
cipher := rc4_128,
mac := sha}) ->
?TLS_RSA_PSK_WITH_RC4_128_SHA;
-suite(#{key_exchange := rsa_psk,
+suite_map_to_bin(#{key_exchange := rsa_psk,
cipher := '3des_ede_cbc',
mac := sha}) ->
?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := rsa_psk,
+suite_map_to_bin(#{key_exchange := rsa_psk,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_RSA_PSK_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := rsa_psk,
+suite_map_to_bin(#{key_exchange := rsa_psk,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_RSA_PSK_WITH_AES_256_CBC_SHA;
%%% PSK NULL Cipher Suites RFC 4785
-suite(#{key_exchange := psk,
+suite_map_to_bin(#{key_exchange := psk,
cipher := null,
mac := sha}) ->
?TLS_PSK_WITH_NULL_SHA;
-suite(#{key_exchange := dhe_psk,
+suite_map_to_bin(#{key_exchange := dhe_psk,
cipher := null,
mac := sha}) ->
?TLS_DHE_PSK_WITH_NULL_SHA;
-suite(#{key_exchange := rsa_psk,
+suite_map_to_bin(#{key_exchange := rsa_psk,
cipher := null,
mac := sha}) ->
?TLS_RSA_PSK_WITH_NULL_SHA;
%%% TLS 1.2 PSK Cipher Suites RFC 5487
-suite(#{key_exchange := psk,
+suite_map_to_bin(#{key_exchange := psk,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_PSK_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := psk,
+suite_map_to_bin(#{key_exchange := psk,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_PSK_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dhe_psk,
+suite_map_to_bin(#{key_exchange := dhe_psk,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dhe_psk,
+suite_map_to_bin(#{key_exchange := dhe_psk,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := rsa_psk,
+suite_map_to_bin(#{key_exchange := rsa_psk,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := rsa_psk,
+suite_map_to_bin(#{key_exchange := rsa_psk,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := psk,
+suite_map_to_bin(#{key_exchange := psk,
cipher := aes_128_cbc,
mac := sha256}) ->
?TLS_PSK_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := psk,
+suite_map_to_bin(#{key_exchange := psk,
cipher := aes_256_cbc,
mac := sha384}) ->
?TLS_PSK_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := dhe_psk,
+suite_map_to_bin(#{key_exchange := dhe_psk,
cipher := aes_128_cbc,
mac := sha256}) ->
?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := dhe_psk,
+suite_map_to_bin(#{key_exchange := dhe_psk,
cipher := aes_256_cbc,
mac := sha384}) ->
?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := rsa_psk,
+suite_map_to_bin(#{key_exchange := rsa_psk,
cipher := aes_128_cbc,
mac := sha256}) ->
?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := rsa_psk,
+suite_map_to_bin(#{key_exchange := rsa_psk,
cipher := aes_256_cbc,
mac := sha384}) ->
?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := psk,
+suite_map_to_bin(#{key_exchange := psk,
cipher := null,
mac := sha256}) ->
?TLS_PSK_WITH_NULL_SHA256;
-suite(#{key_exchange := psk,
+suite_map_to_bin(#{key_exchange := psk,
cipher := null,
mac := sha384}) ->
?TLS_PSK_WITH_NULL_SHA384;
-suite(#{key_exchange := dhe_psk,
+suite_map_to_bin(#{key_exchange := dhe_psk,
cipher := null,
mac := sha256}) ->
?TLS_DHE_PSK_WITH_NULL_SHA256;
-suite(#{key_exchange := dhe_psk,
+suite_map_to_bin(#{key_exchange := dhe_psk,
cipher := null,
mac := sha384}) ->
?TLS_DHE_PSK_WITH_NULL_SHA384;
-suite(#{key_exchange := rsa_psk,
+suite_map_to_bin(#{key_exchange := rsa_psk,
cipher := null,
mac := sha256}) ->
?TLS_RSA_PSK_WITH_NULL_SHA256;
-suite(#{key_exchange := rsa_psk,
+suite_map_to_bin(#{key_exchange := rsa_psk,
cipher := null,
mac := sha384}) ->
?TLS_RSA_PSK_WITH_NULL_SHA384;
%%% ECDHE PSK Cipher Suites RFC 5489
-suite(#{key_exchange := ecdhe_psk,
+suite_map_to_bin(#{key_exchange := ecdhe_psk,
cipher := rc4_128,
mac := sha}) ->
?TLS_ECDHE_PSK_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdhe_psk,
+suite_map_to_bin(#{key_exchange := ecdhe_psk,
cipher :='3des_ede_cbc',
mac := sha}) ->
?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdhe_psk,
+suite_map_to_bin(#{key_exchange := ecdhe_psk,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdhe_psk,
+suite_map_to_bin(#{key_exchange := ecdhe_psk,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdhe_psk,
+suite_map_to_bin(#{key_exchange := ecdhe_psk,
cipher := aes_128_cbc,
mac := sha256}) ->
?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdhe_psk,
+suite_map_to_bin(#{key_exchange := ecdhe_psk,
cipher := aes_256_cbc,
mac := sha384}) ->
?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := ecdhe_psk,
+suite_map_to_bin(#{key_exchange := ecdhe_psk,
cipher := null,
mac := sha256}) ->
?TLS_ECDHE_PSK_WITH_NULL_SHA256;
-suite(#{key_exchange := ecdhe_psk,
+suite_map_to_bin(#{key_exchange := ecdhe_psk,
cipher := null,
mac := sha384}) ->
?TLS_ECDHE_PSK_WITH_NULL_SHA384;
%%% ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites, draft-ietf-tls-ecdhe-psk-aead-05
-suite(#{key_exchange := ecdhe_psk,
+suite_map_to_bin(#{key_exchange := ecdhe_psk,
cipher := aes_128_gcm,
mac := null,
prf := sha256}) ->
?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdhe_psk,
+suite_map_to_bin(#{key_exchange := ecdhe_psk,
cipher := aes_256_gcm,
mac := null,
prf := sha384}) ->
?TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384;
- %% suite(#{key_exchange := ecdhe_psk,
- %% cipher := aes_128_ccm,
- %% mac := null,
- %% prf := sha256}) ->
- %% ?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256;
- %% suite(#{key_exchange := ecdhe_psk,
- %% cipher := aes_256_ccm,
- %% mac := null,
- %% prf := sha256}) ->
- %% ?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256;
+suite_map_to_bin(#{key_exchange := ecdhe_psk,
+ cipher := aes_128_ccm_8,
+ mac := null,
+ prf := sha256}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256;
+suite_map_to_bin(#{key_exchange := ecdhe_psk,
+ cipher := aes_128_ccm,
+ mac := null,
+ prf := sha256}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256;
%%% SRP Cipher Suites RFC 5054
-suite(#{key_exchange := srp_anon,
+suite_map_to_bin(#{key_exchange := srp_anon,
cipher := '3des_ede_cbc',
mac := sha}) ->
?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := srp_rsa,
+suite_map_to_bin(#{key_exchange := srp_rsa,
cipher := '3des_ede_cbc',
mac := sha}) ->
?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := srp_dss,
+suite_map_to_bin(#{key_exchange := srp_dss,
cipher := '3des_ede_cbc',
mac := sha}) ->
?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := srp_anon,
+suite_map_to_bin(#{key_exchange := srp_anon,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_SRP_SHA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := srp_rsa,
+suite_map_to_bin(#{key_exchange := srp_rsa,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := srp_dss,
+suite_map_to_bin(#{key_exchange := srp_dss,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := srp_anon,
+suite_map_to_bin(#{key_exchange := srp_anon,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_SRP_SHA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := srp_rsa,
+suite_map_to_bin(#{key_exchange := srp_rsa,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := srp_dss,
+suite_map_to_bin(#{key_exchange := srp_dss,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
%%% RFC 4492 EC TLS suites
-suite(#{key_exchange := ecdh_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdh_ecdsa,
cipher := null,
mac := sha}) ->
?TLS_ECDH_ECDSA_WITH_NULL_SHA;
-suite(#{key_exchange := ecdh_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdh_ecdsa,
cipher := rc4_128,
mac := sha}) ->
?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdh_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdh_ecdsa,
cipher := '3des_ede_cbc',
mac := sha}) ->
?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdh_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdh_ecdsa,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdh_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdh_ecdsa,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdhe_ecdsa,
cipher := null,
mac := sha}) ->
?TLS_ECDHE_ECDSA_WITH_NULL_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdhe_ecdsa,
cipher := rc4_128,
mac := sha}) ->
?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdhe_ecdsa,
cipher := '3des_ede_cbc',
mac := sha}) ->
?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdhe_ecdsa,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdhe_ecdsa,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdh_rsa,
+suite_map_to_bin(#{key_exchange := ecdh_rsa,
cipher := null,
mac := sha}) ->
?TLS_ECDH_RSA_WITH_NULL_SHA;
-suite(#{key_exchange := ecdh_rsa,
+suite_map_to_bin(#{key_exchange := ecdh_rsa,
cipher := rc4_128,
mac := sha}) ->
?TLS_ECDH_RSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdh_rsa,
+suite_map_to_bin(#{key_exchange := ecdh_rsa,
cipher := '3des_ede_cbc', mac := sha}) ->
?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdh_rsa,
+suite_map_to_bin(#{key_exchange := ecdh_rsa,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdh_rsa,
+suite_map_to_bin(#{key_exchange := ecdh_rsa,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdhe_rsa,
+suite_map_to_bin(#{key_exchange := ecdhe_rsa,
cipher := null,
mac := sha}) ->
?TLS_ECDHE_RSA_WITH_NULL_SHA;
-suite(#{key_exchange := ecdhe_rsa,
+suite_map_to_bin(#{key_exchange := ecdhe_rsa,
cipher := rc4_128,
mac := sha}) ->
?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdhe_rsa,
+suite_map_to_bin(#{key_exchange := ecdhe_rsa,
cipher := '3des_ede_cbc',
mac := sha}) ->
?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdhe_rsa,
+suite_map_to_bin(#{key_exchange := ecdhe_rsa,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdhe_rsa,
+suite_map_to_bin(#{key_exchange := ecdhe_rsa,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdh_anon,
+suite_map_to_bin(#{key_exchange := ecdh_anon,
cipher := null,
mac := sha}) ->
?TLS_ECDH_anon_WITH_NULL_SHA;
-suite(#{key_exchange := ecdh_anon,
+suite_map_to_bin(#{key_exchange := ecdh_anon,
cipher := rc4_128,
mac := sha}) ->
?TLS_ECDH_anon_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdh_anon,
+suite_map_to_bin(#{key_exchange := ecdh_anon,
cipher := '3des_ede_cbc',
mac := sha}) ->
?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdh_anon,
+suite_map_to_bin(#{key_exchange := ecdh_anon,
cipher := aes_128_cbc,
mac := sha}) ->
?TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdh_anon,
+suite_map_to_bin(#{key_exchange := ecdh_anon,
cipher := aes_256_cbc,
mac := sha}) ->
?TLS_ECDH_anon_WITH_AES_256_CBC_SHA;
%%% RFC 5289 EC TLS suites
-suite(#{key_exchange := ecdhe_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdhe_ecdsa,
cipher := aes_128_cbc,
mac:= sha256,
prf := sha256}) ->
?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdhe_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdhe_ecdsa,
cipher := aes_256_cbc,
mac := sha384,
prf := sha384}) ->
?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := ecdh_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdh_ecdsa,
cipher := aes_128_cbc,
mac := sha256,
prf := sha256}) ->
?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdh_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdh_ecdsa,
cipher := aes_256_cbc,
mac := sha384,
prf := sha384}) ->
?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := ecdhe_rsa,
+suite_map_to_bin(#{key_exchange := ecdhe_rsa,
cipher := aes_128_cbc,
mac := sha256,
prf := sha256}) ->
?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdhe_rsa,
+suite_map_to_bin(#{key_exchange := ecdhe_rsa,
cipher := aes_256_cbc,
mac := sha384,
prf := sha384}) ->
?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := ecdh_rsa,
+suite_map_to_bin(#{key_exchange := ecdh_rsa,
cipher := aes_128_cbc,
mac := sha256,
prf := sha256}) ->
?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdh_rsa,
+suite_map_to_bin(#{key_exchange := ecdh_rsa,
cipher := aes_256_cbc,
mac := sha384,
prf := sha384}) ->
?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
%% RFC 5288 AES-GCM Cipher Suites
-suite(#{key_exchange := rsa,
+suite_map_to_bin(#{key_exchange := rsa,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := rsa,
+suite_map_to_bin(#{key_exchange := rsa,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_RSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dhe_rsa,
+suite_map_to_bin(#{key_exchange := dhe_rsa,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dhe_rsa,
+suite_map_to_bin(#{key_exchange := dhe_rsa,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dh_rsa,
+suite_map_to_bin(#{key_exchange := dh_rsa,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dh_rsa,
+suite_map_to_bin(#{key_exchange := dh_rsa,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dhe_dss,
+suite_map_to_bin(#{key_exchange := dhe_dss,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dhe_dss,
+suite_map_to_bin(#{key_exchange := dhe_dss,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dh_dss,
+suite_map_to_bin(#{key_exchange := dh_dss,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dh_dss,
+suite_map_to_bin(#{key_exchange := dh_dss,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dh_anon,
+suite_map_to_bin(#{key_exchange := dh_anon,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_DH_anon_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dh_anon,
+suite_map_to_bin(#{key_exchange := dh_anon,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_DH_anon_WITH_AES_256_GCM_SHA384;
%% RFC 5289 ECC AES-GCM Cipher Suites
-suite(#{key_exchange := ecdhe_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdhe_ecdsa,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdhe_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdhe_ecdsa,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := ecdh_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdh_ecdsa,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdh_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdh_ecdsa,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := ecdhe_rsa,
+suite_map_to_bin(#{key_exchange := ecdhe_rsa,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdhe_rsa,
+suite_map_to_bin(#{key_exchange := ecdhe_rsa,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := ecdh_rsa,
+suite_map_to_bin(#{key_exchange := ecdh_rsa,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdh_rsa,
+suite_map_to_bin(#{key_exchange := ecdh_rsa,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
-suite(#{key_exchange := ecdhe_rsa,
+suite_map_to_bin(#{key_exchange := ecdhe_rsa,
cipher := chacha20_poly1305,
mac := aead,
prf := sha256}) ->
?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
-suite(#{key_exchange := ecdhe_ecdsa,
+suite_map_to_bin(#{key_exchange := ecdhe_ecdsa,
cipher := chacha20_poly1305,
mac := aead,
prf := sha256}) ->
?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
-suite(#{key_exchange := dhe_rsa,
+suite_map_to_bin(#{key_exchange := dhe_rsa,
cipher := chacha20_poly1305,
mac := aead,
prf := sha256}) ->
?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
+
+%% RFC 6655 - TLS-1.2 cipher suites
+suite_map_to_bin(#{key_exchange := psk,
+ cipher := aes_128_ccm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_PSK_WITH_AES_128_CCM;
+suite_map_to_bin(#{key_exchange := psk,
+ cipher := aes_256_ccm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_PSK_WITH_AES_256_CCM;
+suite_map_to_bin(#{key_exchange := dhe_psk,
+ cipher := aes_128_ccm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_PSK_WITH_AES_128_CCM;
+suite_map_to_bin(#{key_exchange := dhe_psk,
+ cipher := aes_256_ccm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_PSK_WITH_AES_256_CCM;
+suite_map_to_bin(#{key_exchange := rsa,
+ cipher := aes_128_ccm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_RSA_WITH_AES_128_CCM;
+suite_map_to_bin(#{key_exchange := rsa,
+ cipher := aes_256_ccm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_RSA_WITH_AES_256_CCM;
+suite_map_to_bin(#{key_exchange := dhe_rsa,
+ cipher := aes_128_ccm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_128_CCM;
+suite_map_to_bin(#{key_exchange := dhe_rsa,
+ cipher := aes_256_ccm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_256_CCM;
+
+suite_map_to_bin(#{key_exchange := psk,
+ cipher := aes_128_ccm_8,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_PSK_WITH_AES_128_CCM_8;
+suite_map_to_bin(#{key_exchange := psk,
+ cipher := aes_256_ccm_8,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_PSK_WITH_AES_256_CCM_8;
+suite_map_to_bin(#{key_exchange := dhe_psk,
+ cipher := aes_128_ccm_8,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_PSK_DHE_WITH_AES_128_CCM_8;
+suite_map_to_bin(#{key_exchange := dhe_psk,
+ cipher := aes_256_ccm_8,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_PSK_DHE_WITH_AES_256_CCM_8;
+suite_map_to_bin(#{key_exchange := rsa,
+ cipher := aes_128_ccm_8,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_RSA_WITH_AES_128_CCM_8;
+suite_map_to_bin(#{key_exchange := rsa,
+ cipher := aes_256_ccm_8,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_RSA_WITH_AES_256_CCM_8;
+suite_map_to_bin(#{key_exchange := dhe_rsa,
+ cipher := aes_128_ccm_8,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_128_CCM_8;
+suite_map_to_bin(#{key_exchange := dhe_rsa,
+ cipher := aes_256_ccm_8,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_256_CCM_8;
+
%% TLS 1.3 Cipher Suites RFC8446
-suite(#{key_exchange := any,
+suite_map_to_bin(#{key_exchange := any,
cipher := aes_128_gcm,
mac := aead,
prf := sha256}) ->
?TLS_AES_128_GCM_SHA256;
-suite(#{key_exchange := any,
+suite_map_to_bin(#{key_exchange := any,
cipher := aes_256_gcm,
mac := aead,
prf := sha384}) ->
?TLS_AES_256_GCM_SHA384;
-suite(#{key_exchange := any,
+suite_map_to_bin(#{key_exchange := any,
cipher := chacha20_poly1305,
mac := aead,
prf := sha256}) ->
?TLS_CHACHA20_POLY1305_SHA256.
-%% suite(#{key_exchange := any,
+%% suite_map_to_bin(#{key_exchange := any,
%% cipher := aes_128_ccm,
%% mac := aead,
%% prf := sha256}) ->
%% ?TLS_AES_128_CCM_SHA256;
-%% suite(#{key_exchange := any,
+%% suite_map_to_bin(#{key_exchange := any,
%% cipher := aes_128_ccm_8,
%% mac := aead,
%% prf := sha256}) ->
%% ?TLS_AES_128_CCM_8_SHA256.
-%%--------------------------------------------------------------------
--spec openssl_suite(openssl_cipher_suite()) -> cipher_suite().
-%%
-%% Description: Return TLS cipher suite definition.
-%%--------------------------------------------------------------------
-%% translate constants <-> openssl-strings
-openssl_suite("DHE-RSA-AES256-SHA256") ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
-openssl_suite("DHE-DSS-AES256-SHA256") ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
-openssl_suite("AES256-SHA256") ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA256;
-openssl_suite("DHE-RSA-AES128-SHA256") ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("DHE-DSS-AES128-SHA256") ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
-openssl_suite("AES128-SHA256") ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("DHE-RSA-AES256-SHA") ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
-openssl_suite("DHE-DSS-AES256-SHA") ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
-openssl_suite("AES256-SHA") ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA;
-openssl_suite("EDH-RSA-DES-CBC3-SHA") ->
- ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("EDH-DSS-DES-CBC3-SHA") ->
- ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("DES-CBC3-SHA") ->
- ?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("DHE-RSA-AES128-SHA") ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("DHE-DSS-AES128-SHA") ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
-openssl_suite("AES128-SHA") ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("RC4-SHA") ->
- ?TLS_RSA_WITH_RC4_128_SHA;
-openssl_suite("RC4-MD5") ->
- ?TLS_RSA_WITH_RC4_128_MD5;
-openssl_suite("EDH-RSA-DES-CBC-SHA") ->
- ?TLS_DHE_RSA_WITH_DES_CBC_SHA;
-openssl_suite("DES-CBC-SHA") ->
- ?TLS_RSA_WITH_DES_CBC_SHA;
-
-%%% SRP Cipher Suites RFC 5054
-
-openssl_suite("SRP-DSS-AES-256-CBC-SHA") ->
- ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
-openssl_suite("SRP-RSA-AES-256-CBC-SHA") ->
- ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
-openssl_suite("SRP-DSS-3DES-EDE-CBC-SHA") ->
- ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("SRP-RSA-3DES-EDE-CBC-SHA") ->
- ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("SRP-DSS-AES-128-CBC-SHA") ->
- ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
-openssl_suite("SRP-RSA-AES-128-CBC-SHA") ->
- ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
-
-%% RFC 4492 EC TLS suites
-openssl_suite("ECDH-ECDSA-RC4-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
-openssl_suite("ECDH-ECDSA-DES-CBC3-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDH-ECDSA-AES128-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDH-ECDSA-AES256-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
-
-openssl_suite("ECDHE-ECDSA-RC4-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
-openssl_suite("ECDHE-ECDSA-DES-CBC3-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDHE-ECDSA-AES128-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDHE-ECDSA-AES256-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
-openssl_suite("ECDHE-RSA-RC4-SHA") ->
- ?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
-openssl_suite("ECDHE-RSA-DES-CBC3-SHA") ->
- ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDHE-RSA-AES128-SHA") ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDHE-RSA-AES256-SHA") ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
-openssl_suite("ECDH-RSA-RC4-SHA") ->
- ?TLS_ECDH_RSA_WITH_RC4_128_SHA;
-openssl_suite("ECDH-RSA-DES-CBC3-SHA") ->
- ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDH-RSA-AES128-SHA") ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDH-RSA-AES256-SHA") ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
+tls_1_3_suite_str_to_map(CipherStr) ->
+ {Cipher, Mac, Prf} = cipher_str_to_algs(CipherStr, ""),
+ #{key_exchange => any,
+ mac => Mac,
+ cipher => Cipher,
+ prf => Prf
+ }.
-%% RFC 5289 EC TLS suites
-openssl_suite("ECDHE-ECDSA-AES128-SHA256") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDHE-ECDSA-AES256-SHA384") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
-openssl_suite("ECDH-ECDSA-AES128-SHA256") ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDH-ECDSA-AES256-SHA384") ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
-openssl_suite("ECDHE-RSA-AES128-SHA256") ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDHE-RSA-AES256-SHA384") ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
-openssl_suite("ECDH-RSA-AES128-SHA256") ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDH-RSA-AES256-SHA384") ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
+pre_tls_1_3_suite_str_to_map(KexStr, Rest) ->
+ Kex = algo_str_to_atom(KexStr),
+ [CipherStr, AlgStr] = string:split(Rest, "_", trailing),
+ {Cipher, Mac, Prf} = cipher_str_to_algs(CipherStr, AlgStr),
+ #{key_exchange => Kex,
+ mac => Mac,
+ cipher => Cipher,
+ prf => Prf
+ }.
+
+cipher_str_to_algs(CipherStr, "CCM"= End) -> %% PRE TLS 1.3
+ Cipher = algo_str_to_atom(CipherStr ++ "_" ++ End),
+ {Cipher, aead, sha256};
+cipher_str_to_algs(CipherStr, "8" = End) -> %% PRE TLS 1.3
+ Cipher = algo_str_to_atom(CipherStr ++ "_" ++ End),
+ {Cipher, aead, sha256};
+cipher_str_to_algs(CipherStr, "CHACHA20_POLY1305" = End) -> %% PRE TLS 1.3
+ Cipher = algo_str_to_atom(CipherStr ++ "_" ++ End),
+ {Cipher, aead, sha256};
+cipher_str_to_algs(CipherStr0, "") -> %% TLS 1.3
+ [CipherStr, AlgStr] = string:split(CipherStr0, "_", trailing),
+ Hash = algo_str_to_atom(AlgStr),
+ Cipher = algo_str_to_atom(CipherStr),
+ {Cipher, aead, Hash};
+cipher_str_to_algs(CipherStr, HashStr) -> %% PRE TLS 1.3
+ Hash = algo_str_to_atom(HashStr),
+ Cipher = algo_str_to_atom(CipherStr),
+ case is_aead_cipher(CipherStr) of
+ true ->
+ {Cipher, aead, Hash};
+ false ->
+ {Cipher, Hash, default_prf}
+ end.
-%% RFC 5288 AES-GCM Cipher Suites
-openssl_suite("AES128-GCM-SHA256") ->
- ?TLS_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("AES256-GCM-SHA384") ->
- ?TLS_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("DHE-RSA-AES128-GCM-SHA256") ->
- ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("DHE-RSA-AES256-GCM-SHA384") ->
- ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("DH-RSA-AES128-GCM-SHA256") ->
- ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("DH-RSA-AES256-GCM-SHA384") ->
- ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("DHE-DSS-AES128-GCM-SHA256") ->
- ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
-openssl_suite("DHE-DSS-AES256-GCM-SHA384") ->
- ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
-openssl_suite("DH-DSS-AES128-GCM-SHA256") ->
- ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
-openssl_suite("DH-DSS-AES256-GCM-SHA384") ->
- ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
+%% PRE TLS 1.3
+is_aead_cipher("CHACHA20_POLY1305") ->
+ true;
+is_aead_cipher(CipherStr) ->
+ [_, Rest] = string:split(CipherStr, "_", trailing),
+ (Rest == "GCM") orelse (Rest == "CCM") orelse (Rest == "8").
-%% RFC 5289 ECC AES-GCM Cipher Suites
-openssl_suite("ECDHE-ECDSA-AES128-GCM-SHA256") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDHE-ECDSA-AES256-GCM-SHA384") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("ECDH-ECDSA-AES128-GCM-SHA256") ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDH-ECDSA-AES256-GCM-SHA384") ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("ECDHE-RSA-AES128-GCM-SHA256") ->
- ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDHE-RSA-AES256-GCM-SHA384") ->
- ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("ECDH-RSA-AES128-GCM-SHA256") ->
- ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDH-RSA-AES256-GCM-SHA384") ->
- ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
+openssl_is_aead_cipher("CHACHA20-POLY1305") ->
+ true;
+openssl_is_aead_cipher(CipherStr) ->
+ case string:split(CipherStr, "-", trailing) of
+ [_, Rest] ->
+ (Rest == "GCM") orelse (Rest == "CCM") orelse (Rest == "8");
+ [_] ->
+ false
+ end.
-%% TLS 1.3 Cipher Suites RFC8446
-openssl_suite("TLS_AES_128_GCM_SHA256") ->
- ?TLS_AES_128_GCM_SHA256;
-openssl_suite("TLS_AES_256_GCM_SHA384") ->
- ?TLS_AES_256_GCM_SHA384;
-openssl_suite("TLS_CHACHA20_POLY1305_SHA256") ->
- ?TLS_CHACHA20_POLY1305_SHA256.
-%% openssl_suite("TLS_AES_128_CCM_SHA256") ->
-%% ?TLS_AES_128_CCM_SHA256;
-%% openssl_suite("TLS_AES_128_CCM_8_SHA256") ->
-%% ?TLS_AES_128_CCM_8_SHA256.
+algo_str_to_atom(AlgoStr) ->
+ erlang:list_to_existing_atom(string:to_lower(AlgoStr)).
-%%--------------------------------------------------------------------
--spec openssl_suite_name(cipher_suite()) -> openssl_cipher_suite() | internal_erl_cipher_suite().
-%%
-%% Description: Return openssl cipher suite name if possible
-%%-------------------------------------------------------------------
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
- "DHE-RSA-AES256-SHA";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
- "DHE-DSS-AES256-SHA";
-openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
- "AES256-SHA";
-openssl_suite_name(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "EDH-RSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
- "EDH-DSS-DES-CBC3-SHA";
-openssl_suite_name(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "DES-CBC3-SHA";
-openssl_suite_name( ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
- "DHE-RSA-AES128-SHA";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
- "DHE-DSS-AES128-SHA";
-openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
- "AES128-SHA";
-openssl_suite_name(?TLS_RSA_WITH_RC4_128_SHA) ->
- "RC4-SHA";
-openssl_suite_name(?TLS_RSA_WITH_RC4_128_MD5) ->
- "RC4-MD5";
-openssl_suite_name(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
- "EDH-RSA-DES-CBC-SHA";
-openssl_suite_name(?TLS_RSA_WITH_DES_CBC_SHA) ->
- "DES-CBC-SHA";
-openssl_suite_name(?TLS_RSA_WITH_NULL_SHA256) ->
- "NULL-SHA256";
-openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
- "AES128-SHA256";
-openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
- "AES256-SHA256";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_CBC_SHA256) ->
- "DH-DSS-AES128-SHA256";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_CBC_SHA256) ->
- "DH-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
- "DHE-DSS-AES128-SHA256";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
- "DHE-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_CBC_SHA256) ->
- "DH-DSS-AES256-SHA256";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_CBC_SHA256) ->
- "DH-RSA-AES256-SHA256";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
- "DHE-DSS-AES256-SHA256";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
- "DHE-RSA-AES256-SHA256";
+openssl_cipher_name(Kex, "AES_128_CBC" ++ _ = CipherStr) when Kex == rsa;
+ Kex == dhe_rsa;
+ Kex == ecdhe_rsa;
+ Kex == ecdhe_ecdsa ->
+ openssl_name_concat(CipherStr);
+openssl_cipher_name(Kex, "AES_256_CBC" ++ _ = CipherStr) when Kex == rsa;
+ Kex == dhe_rsa;
+ Kex == ecdhe_rsa;
+ Kex == ecdhe_ecdsa ->
+ openssl_name_concat(CipherStr);
+openssl_cipher_name(Kex, "AES_128_CBC" ++ _ = CipherStr) when Kex == srp;
+ Kex == srp_rsa ->
+ lists:append(string:replace(CipherStr, "_", "-", all));
+openssl_cipher_name(Kex, "AES_256_CBC" ++ _ = CipherStr) when Kex == srp;
+ Kex == srp_rsa ->
+ lists:append(string:replace(CipherStr, "_", "-", all));
+openssl_cipher_name(_, "AES_128_CBC" ++ _ = CipherStr) ->
+ openssl_name_concat(CipherStr) ++ "-CBC";
+openssl_cipher_name(_, "AES_256_CBC" ++ _ = CipherStr) ->
+ openssl_name_concat(CipherStr) ++ "-CBC";
+openssl_cipher_name(_, "AES_128_GCM" ++ _ = CipherStr) ->
+ openssl_name_concat(CipherStr) ++ "-GCM";
+openssl_cipher_name(_, "AES_256_GCM" ++ _ = CipherStr) ->
+ openssl_name_concat(CipherStr) ++ "-GCM";
+openssl_cipher_name(_, "RC4" ++ _) ->
+ "RC4";
+openssl_cipher_name(_, CipherStr) ->
+ lists:append(string:replace(CipherStr, "_", "-", all)).
-%%% PSK Cipher Suites RFC 4279
-openssl_suite_name(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
- "PSK-AES256-CBC-SHA";
-openssl_suite_name(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
- "PSK-3DES-EDE-CBC-SHA";
-openssl_suite_name(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
- "PSK-AES128-CBC-SHA";
-openssl_suite_name(?TLS_PSK_WITH_RC4_128_SHA) ->
- "PSK-RC4-SHA";
+openssl_suite_start(Kex) ->
+ case openssl_kex_name(Kex) of
+ "" ->
+ "";
+ Name ->
+ Name ++ "-"
+ end.
-%%% SRP Cipher Suites RFC 5054
+openssl_kex_name("RSA") ->
+ "";
+openssl_kex_name(Kex) ->
+ lists:append(string:replace(Kex, "_", "-", all)).
-openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "SRP-RSA-3DES-EDE-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
- "SRP-DSS-3DES-EDE-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
- "SRP-RSA-AES-128-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
- "SRP-DSS-AES-128-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
- "SRP-RSA-AES-256-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
- "SRP-DSS-AES-256-CBC-SHA";
+kex_name_from_openssl(Kex) ->
+ lists:append(string:replace(Kex, "-", "_", all)).
-%% RFC 4492 EC TLS suites
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
- "ECDH-ECDSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDH-ECDSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
- "ECDH-ECDSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
- "ECDH-ECDSA-AES256-SHA";
+cipher_name_from_openssl("AES128") ->
+ "AES_128_CBC";
+cipher_name_from_openssl("AES256") ->
+ "AES_256_CBC";
+cipher_name_from_openssl("AES128-CBC") ->
+ "AES_128_CBC";
+cipher_name_from_openssl("AES256-CBC") ->
+ "AES_256_CBC";
+cipher_name_from_openssl("AES-128-CBC") ->
+ "AES_128_CBC";
+cipher_name_from_openssl("AES-256-CBC") ->
+ "AES_256_CBC";
+cipher_name_from_openssl("AES128-GCM") ->
+ "AES_128_GCM";
+cipher_name_from_openssl("AES256-GCM") ->
+ "AES_256_GCM";
+cipher_name_from_openssl("RC4") ->
+ "RC4_128";
+cipher_name_from_openssl(Str) ->
+ Str.
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
- "ECDHE-ECDSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDHE-ECDSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
- "ECDHE-ECDSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
- "ECDHE-ECDSA-AES256-SHA";
+openssl_name_concat(Str0) ->
+ [Str, _] = string:split(Str0, "_", trailing),
+ [Part1, Part2] = string:split(Str, "_", trailing),
+ Part1 ++ Part2.
-openssl_suite_name(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
- "ECDH-RSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDH-RSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
- "ECDH-RSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
- "ECDH-RSA-AES256-SHA";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
- "ECDHE-RSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDHE-RSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
- "ECDHE-RSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
- "ECDHE-RSA-AES256-SHA";
+suite_openssl_str_to_map(Kex0, Rest) ->
+ Kex = algo_str_to_atom(kex_name_from_openssl(Kex0)),
+ [CipherStr, AlgStr] = string:split(Rest, "-", trailing),
+ {Cipher, Mac, Prf} = openssl_cipher_str_to_algs(CipherStr, AlgStr),
+ #{key_exchange => Kex,
+ mac => Mac,
+ cipher => Cipher,
+ prf => Prf
+ }.
-%% RFC 5289 EC TLS suites
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
- "ECDHE-ECDSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
- "ECDHE-ECDSA-AES256-SHA384";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
- "ECDH-ECDSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
- "ECDH-ECDSA-AES256-SHA384";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
- "ECDHE-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
- "ECDHE-RSA-AES256-SHA384";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
- "ECDH-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
- "ECDH-RSA-AES256-SHA384";
+%% Does only need own implementation PRE TLS 1.3
+openssl_cipher_str_to_algs(CipherStr, "CCM"= End) ->
+ Cipher = algo_str_to_atom(CipherStr ++ "_" ++ End),
+ {Cipher, aead, sha256};
+openssl_cipher_str_to_algs(CipherStr, "8" = End) ->
+ Cipher = algo_str_to_atom(CipherStr ++ "_" ++ End),
+ {Cipher, aead, sha256};
+openssl_cipher_str_to_algs(CipherStr, "POLY1305" = End) ->
+ Cipher = algo_str_to_atom(CipherStr ++ "_" ++ End),
+ {Cipher, aead, sha256};
+openssl_cipher_str_to_algs(CipherStr, HashStr) ->
+ Hash = algo_str_to_atom(HashStr),
+ Cipher = algo_str_to_atom(cipher_name_from_openssl(CipherStr)),
+ case openssl_is_aead_cipher(CipherStr) of
+ true ->
+ {Cipher, aead, Hash};
+ false ->
+ {Cipher, Hash, openssl_prf(Hash)}
+ end.
-%% RFC 5288 AES-GCM Cipher Suites
-openssl_suite_name(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
- "AES128-GCM-SHA256";
-openssl_suite_name(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
- "AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
- "DHE-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
- "DHE-RSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
- "DH-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
- "DH-RSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
- "DHE-DSS-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
- "DHE-DSS-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
- "DH-DSS-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
- "DH-DSS-AES256-GCM-SHA384";
+openssl_prf(sha256)->
+ sha256;
+openssl_prf(sha384) ->
+ sha384;
+openssl_prf(_) ->
+ default_prf.
-%% RFC 5289 ECC AES-GCM Cipher Suites
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
- "ECDHE-ECDSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
- "ECDHE-ECDSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
- "ECDH-ECDSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
- "ECDH-ECDSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
- "ECDHE-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
- "ECDHE-RSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
- "ECDH-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
- "ECDH-RSA-AES256-GCM-SHA384";
-%% TLS 1.3 Cipher Suites RFC8446
-openssl_suite_name(?TLS_AES_128_GCM_SHA256) ->
- "TLS_AES_128_GCM_SHA256";
-openssl_suite_name(?TLS_AES_256_GCM_SHA384) ->
- "TLS_AES_256_GCM_SHA384";
-openssl_suite_name(?TLS_CHACHA20_POLY1305_SHA256) ->
- "TLS_CHACHA20_POLY1305_SHA256";
-%% openssl_suite(?TLS_AES_128_CCM_SHA256) ->
-%% "TLS_AES_128_CCM_SHA256";
-%% openssl_suite(?TLS_AES_128_CCM_8_SHA256) ->
-%% "TLS_AES_128_CCM_8_SHA256";
-%% No oppenssl name
-openssl_suite_name(Cipher) ->
- suite_definition(Cipher).
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 1e97fe046b..6e325b504c 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -703,7 +703,7 @@ handle_session(#server_hello{cipher_suite = CipherSuite,
handshake_env = #handshake_env{negotiated_protocol = CurrentProtocol} = HsEnv,
connection_env = #connection_env{negotiated_version = ReqVersion} = CEnv} = State0) ->
#{key_exchange := KeyAlgorithm} =
- ssl_cipher_format:suite_definition(CipherSuite),
+ ssl_cipher_format:suite_bin_to_map(CipherSuite),
PremasterSecret = make_premaster_secret(ReqVersion, KeyAlgorithm),
@@ -1573,7 +1573,7 @@ connection_info(#state{static_env = #static_env{protocol_cb = Connection},
connection_env = #connection_env{negotiated_version = {_,_} = Version},
ssl_options = Opts}) ->
RecordCB = record_cb(Connection),
- CipherSuiteDef = #{key_exchange := KexAlg} = ssl_cipher_format:suite_definition(CipherSuite),
+ CipherSuiteDef = #{key_exchange := KexAlg} = ssl_cipher_format:suite_bin_to_map(CipherSuite),
IsNamedCurveSuite = lists:member(KexAlg,
[ecdh_ecdsa, ecdhe_ecdsa, ecdh_rsa, ecdhe_rsa, ecdh_anon]),
CurveInfo = case ECCCurve of
@@ -1584,7 +1584,7 @@ connection_info(#state{static_env = #static_env{protocol_cb = Connection},
end,
[{protocol, RecordCB:protocol_version(Version)},
{session_id, SessionId},
- {cipher_suite, ssl_cipher_format:erl_suite_definition(CipherSuiteDef)},
+ {cipher_suite, ssl_cipher_format:suite_legacy(CipherSuiteDef)},
{selected_cipher_suite, CipherSuiteDef},
{sni_hostname, SNIHostname} | CurveInfo] ++ ssl_options_list(Opts).
@@ -1711,7 +1711,7 @@ resumed_server_hello(#state{session = Session,
server_hello(ServerHello, State0, Connection) ->
CipherSuite = ServerHello#server_hello.cipher_suite,
- #{key_exchange := KeyAlgorithm} = ssl_cipher_format:suite_definition(CipherSuite),
+ #{key_exchange := KeyAlgorithm} = ssl_cipher_format:suite_bin_to_map(CipherSuite),
#state{handshake_env = HsEnv} = State = Connection:queue_handshake(ServerHello, State0),
State#state{handshake_env = HsEnv#handshake_env{kex_algorithm = KeyAlgorithm}}.
@@ -1726,7 +1726,7 @@ handle_peer_cert(Role, PeerCert, PublicKeyInfo,
State1 = State0#state{handshake_env = HsEnv#handshake_env{public_key_info = PublicKeyInfo},
session =
Session#session{peer_certificate = PeerCert}},
- #{key_exchange := KeyAlgorithm} = ssl_cipher_format:suite_definition(CipherSuite),
+ #{key_exchange := KeyAlgorithm} = ssl_cipher_format:suite_bin_to_map(CipherSuite),
State = handle_peer_cert_key(Role, PeerCert, PublicKeyInfo, KeyAlgorithm, State1),
Connection:next_event(certify, no_record, State).
@@ -2728,7 +2728,7 @@ ssl_options_list([ciphers = Key | Keys], [Value | Values], Acc) ->
ssl_options_list(Keys, Values,
[{Key, lists:map(
fun(Suite) ->
- ssl_cipher_format:suite_definition(Suite)
+ ssl_cipher_format:suite_bin_to_map(Suite)
end, Value)}
| Acc]);
ssl_options_list([Key | Keys], [Value | Values], Acc) ->
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 6c95a7edf8..dc037bb1ea 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -182,7 +182,7 @@ client_certificate_verify(OwnCert, MasterSecret, Version,
%% Description: Creates a certificate_request message, called by the server.
%%--------------------------------------------------------------------
certificate_request(CipherSuite, CertDbHandle, CertDbRef, HashSigns, Version) ->
- Types = certificate_types(ssl_cipher_format:suite_definition(CipherSuite), Version),
+ Types = certificate_types(ssl_cipher_format:suite_bin_to_map(CipherSuite), Version),
Authorities = certificate_authorities(CertDbHandle, CertDbRef),
#certificate_request{
certificate_types = Types,
@@ -883,7 +883,7 @@ available_suites(ServerCert, UserSuites, Version, undefined, Curve) ->
filter_unavailable_ecc_suites(Curve, Suites);
available_suites(ServerCert, UserSuites, Version, HashSigns, Curve) ->
Suites = available_suites(ServerCert, UserSuites, Version, undefined, Curve),
- filter_hashsigns(Suites, [ssl_cipher_format:suite_definition(Suite) || Suite <- Suites], HashSigns,
+ filter_hashsigns(Suites, [ssl_cipher_format:suite_bin_to_map(Suite) || Suite <- Suites], HashSigns,
Version, []).
available_signature_algs(undefined, _) ->
@@ -1085,7 +1085,7 @@ add_common_extensions(Version,
{EcPointFormats, EllipticCurves} =
case advertises_ec_ciphers(
- lists:map(fun ssl_cipher_format:suite_definition/1,
+ lists:map(fun ssl_cipher_format:suite_bin_to_map/1,
CipherSuites)) of
true ->
client_ecc_extensions(SupportedECCs);
@@ -2421,7 +2421,7 @@ decode_extensions(<<?UINT16(?KEY_SHARE_EXT), ?UINT16(Len),
decode_extensions(<<?UINT16(?KEY_SHARE_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>,
Version, MessageType = hello_retry_request, Acc) ->
- <<?UINT16(Group),Rest/binary>> = ExtData,
+ <<?UINT16(Group)>> = ExtData,
decode_extensions(Rest, Version, MessageType,
Acc#{key_share =>
#key_share_hello_retry_request{
@@ -2990,7 +2990,7 @@ handle_renegotiation_info(_RecordCB, ConnectionStates, SecureRenegotation) ->
cert_curve(_, _, no_suite) ->
{no_curve, no_suite};
cert_curve(Cert, ECCCurve0, CipherSuite) ->
- case ssl_cipher_format:suite_definition(CipherSuite) of
+ case ssl_cipher_format:suite_bin_to_map(CipherSuite) of
#{key_exchange := Kex} when Kex == ecdh_ecdsa;
Kex == ecdh_rsa ->
OtpCert = public_key:pkix_decode_cert(Cert, otp),
diff --git a/lib/ssl/src/ssl_logger.erl b/lib/ssl/src/ssl_logger.erl
index f497315235..987693b96b 100644
--- a/lib/ssl/src/ssl_logger.erl
+++ b/lib/ssl/src/ssl_logger.erl
@@ -206,10 +206,14 @@ parse_handshake(Direction, #encrypted_extensions{} = EncryptedExtensions) ->
parse_cipher_suites([_|_] = Ciphers) ->
[format_cipher(C) || C <- Ciphers].
-format_cipher(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV) ->
- 'TLS_EMPTY_RENEGOTIATION_INFO_SCSV';
format_cipher(C0) ->
- list_to_atom(ssl_cipher_format:openssl_suite_name(C0)).
+ try ssl_cipher_format:suite_bin_to_map(C0) of
+ Map ->
+ ssl_cipher_format:suite_map_to_str(Map)
+ catch
+ error:function_clause ->
+ format_uknown_cipher_suite(C0)
+ end.
get_client_version(Version, Extensions) ->
CHVersions = maps:get(client_hello_versions, Extensions, undefined),
@@ -436,3 +440,7 @@ number_to_hex(N) ->
H ->
lists:reverse(H)
end.
+
+format_uknown_cipher_suite(<<?BYTE(X), ?BYTE(Y)>>) ->
+ "0x" ++ number_to_hex(X) ++ "0x" ++ number_to_hex(Y).
+
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index 91f1876980..867d2cfc5a 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -395,7 +395,7 @@ decipher_aead(Type, #cipher_state{key = Key} = CipherState, AAD0, CipherFragment
try
Nonce = decrypt_nonce(Type, CipherState, CipherFragment),
{AAD, CipherText, CipherTag} = aead_ciphertext_split(Type, CipherState, CipherFragment, AAD0),
- case ssl_cipher:aead_decrypt(Type, Key, Nonce, CipherText, CipherTag, AAD) of
+ case ssl_cipher:aead_decrypt(Type, Key, Nonce, CipherText, CipherTag, AAD) of
Content when is_binary(Content) ->
Content;
_ ->
@@ -471,34 +471,43 @@ initial_security_params(ConnectionEnd) ->
-define(end_additional_data(AAD, Len), << (begin(AAD)end)/binary, ?UINT16(begin(Len)end) >>).
-do_cipher_aead(?CHACHA20_POLY1305 = Type, Fragment, #cipher_state{key=Key} = CipherState, AAD0) ->
+do_cipher_aead(?CHACHA20_POLY1305 = Type, Fragment, #cipher_state{key=Key, tag_len = TagLen} = CipherState, AAD0) ->
AAD = ?end_additional_data(AAD0, erlang:iolist_size(Fragment)),
- Nonce = encrypt_nonce(Type, CipherState),
- {Content, CipherTag} = ssl_cipher:aead_encrypt(Type, Key, Nonce, Fragment, AAD),
+ Nonce = chacha_nonce(CipherState),
+ {Content, CipherTag} = ssl_cipher:aead_encrypt(Type, Key, Nonce, Fragment, AAD, TagLen),
{<<Content/binary, CipherTag/binary>>, CipherState};
-do_cipher_aead(Type, Fragment, #cipher_state{key=Key, nonce = ExplicitNonce} = CipherState, AAD0) ->
+do_cipher_aead(Type, Fragment, #cipher_state{key=Key, tag_len = TagLen, nonce = ExplicitNonce} = CipherState, AAD0) ->
AAD = ?end_additional_data(AAD0, erlang:iolist_size(Fragment)),
Nonce = encrypt_nonce(Type, CipherState),
- {Content, CipherTag} = ssl_cipher:aead_encrypt(Type, Key, Nonce, Fragment, AAD),
+ {Content, CipherTag} = ssl_cipher:aead_encrypt(Type, Key, Nonce, Fragment, AAD, TagLen),
{<<ExplicitNonce:64/integer, Content/binary, CipherTag/binary>>, CipherState#cipher_state{nonce = ExplicitNonce + 1}}.
-encrypt_nonce(?CHACHA20_POLY1305, #cipher_state{nonce = Nonce, iv = IV}) ->
- crypto:exor(<<?UINT32(0), Nonce/binary>>, IV);
-encrypt_nonce(?AES_GCM, #cipher_state{iv = IV, nonce = ExplicitNonce}) ->
+
+chacha_nonce(#cipher_state{nonce = Nonce, iv = IV}) ->
+ crypto:exor(<<?UINT32(0), Nonce/binary>>, IV).
+
+encrypt_nonce(Type, #cipher_state{iv = IV, nonce = ExplicitNonce}) when Type == ?AES_GCM;
+ Type == ?AES_CCM;
+ Type == ?AES_CCM_8 ->
<<Salt:4/bytes, _/binary>> = IV,
<<Salt/binary, ExplicitNonce:64/integer>>.
-decrypt_nonce(?CHACHA20_POLY1305, #cipher_state{nonce = Nonce, iv = IV}, _) ->
- crypto:exor(<<Nonce:96/unsigned-big-integer>>, IV);
-decrypt_nonce(?AES_GCM, #cipher_state{iv = <<Salt:4/bytes, _/binary>>}, <<ExplicitNonce:8/bytes, _/binary>>) ->
- <<Salt/binary, ExplicitNonce/binary>>.
+decrypt_nonce(?CHACHA20_POLY1305, CipherState, _) ->
+ chacha_nonce(CipherState);
+decrypt_nonce(Type, #cipher_state{iv = <<Salt:4/bytes, _/binary>>}, <<ExplicitNonce:8/bytes, _/binary>>) when
+ Type == ?AES_GCM;
+ Type == ?AES_CCM;
+ Type == ?AES_CCM_8 ->
+ <<Salt/binary, ExplicitNonce/binary>>.
-compile({inline, [aead_ciphertext_split/4]}).
aead_ciphertext_split(?CHACHA20_POLY1305, #cipher_state{tag_len = Len}, CipherTextFragment, AAD) ->
CipherLen = byte_size(CipherTextFragment) - Len,
<<CipherText:CipherLen/bytes, CipherTag:Len/bytes>> = CipherTextFragment,
{?end_additional_data(AAD, CipherLen), CipherText, CipherTag};
-aead_ciphertext_split(?AES_GCM, #cipher_state{tag_len = Len}, CipherTextFragment, AAD) ->
+aead_ciphertext_split(Type, #cipher_state{tag_len = Len}, CipherTextFragment, AAD) when Type == ?AES_GCM;
+ Type == ?AES_CCM;
+ Type == ?AES_CCM_8 ->
CipherLen = byte_size(CipherTextFragment) - (Len + 8), %% 8 is length of explicit Nonce
<< _:8/bytes, CipherText:CipherLen/bytes, CipherTag:Len/bytes>> = CipherTextFragment,
{?end_additional_data(AAD, CipherLen), CipherText, CipherTag}.
diff --git a/lib/ssl/src/ssl_record.hrl b/lib/ssl/src/ssl_record.hrl
index eb718fd20c..6d4d47cedb 100644
--- a/lib/ssl/src/ssl_record.hrl
+++ b/lib/ssl/src/ssl_record.hrl
@@ -96,6 +96,11 @@
-define(AES_CBC, 7).
-define(AES_GCM, 8).
-define(CHACHA20_POLY1305, 9).
+%% Following two are not defined in any RFC but we want to have the
+%% same type of handling internaly, all of these "bulk_cipher_algorithm"
+%% enums are only used internaly anyway.
+-define(AES_CCM, 10).
+-define(AES_CCM_8, 11).
%% CipherType
-define(STREAM, 0).
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index fde73cdef1..a05858221a 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -934,7 +934,7 @@ wait_sh(Type, Event, State) ->
callback_mode() ->
state_functions.
-terminate({shutdown, sender_died, Reason}, _StateName,
+terminate({shutdown, {sender_died, Reason}}, _StateName,
#state{static_env = #static_env{socket = Socket,
transport_cb = Transport}}
= State) ->
@@ -1119,7 +1119,7 @@ handle_info({CloseTag, Socket}, StateName,
end;
handle_info({'EXIT', Sender, Reason}, _,
#state{protocol_specific = #{sender := Sender}} = State) ->
- {stop, {shutdown, sender_died, Reason}, State};
+ {stop, {shutdown, {sender_died, Reason}}, State};
handle_info(Msg, StateName, State) ->
ssl_connection:StateName(info, Msg, State, ?MODULE).
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index e7cee1956b..74ab0d5923 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -294,7 +294,7 @@ handle_client_hello(Version,
no_suite ->
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_ciphers);
_ ->
- #{key_exchange := KeyExAlg} = ssl_cipher_format:suite_definition(CipherSuite),
+ #{key_exchange := KeyExAlg} = ssl_cipher_format:suite_bin_to_map(CipherSuite),
case ssl_handshake:select_hashsign({ClientHashSigns, ClientSignatureSchemes},
Cert, KeyExAlg,
SupportedHashSigns,
diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl
index 0efedf3400..8a4ad922e1 100644
--- a/lib/ssl/src/tls_handshake_1_3.erl
+++ b/lib/ssl/src/tls_handshake_1_3.erl
@@ -887,7 +887,7 @@ calculate_handshake_secrets(ClientKey, SelectedGroup, KeyShare,
tls_v1:server_handshake_traffic_secret(HKDFAlgo, HandshakeSecret, lists:reverse(Messages)),
%% Calculate traffic keys
- #{cipher := Cipher} = ssl_cipher_format:suite_definition(CipherSuite),
+ #{cipher := Cipher} = ssl_cipher_format:suite_bin_to_map(CipherSuite),
{ReadKey, ReadIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, ClientHSTrafficSecret),
{WriteKey, WriteIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, ServerHSTrafficSecret),
@@ -922,7 +922,7 @@ calculate_traffic_secrets(#state{connection_states = ConnectionStates,
tls_v1:server_application_traffic_secret_0(HKDFAlgo, MasterSecret, lists:reverse(Messages)),
%% Calculate traffic keys
- #{cipher := Cipher} = ssl_cipher_format:suite_definition(CipherSuite),
+ #{cipher := Cipher} = ssl_cipher_format:suite_bin_to_map(CipherSuite),
{ReadKey, ReadIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, ClientAppTrafficSecret0),
{WriteKey, WriteIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, ServerAppTrafficSecret0),
@@ -1323,7 +1323,9 @@ get_signature_scheme_list(#signature_algorithms_cert{
ClientSignatureSchemes;
get_signature_scheme_list(#signature_algorithms{
signature_scheme_list = ClientSignatureSchemes}) ->
- ClientSignatureSchemes.
+ %% Filter unassigned and legacy elements
+ lists:filter(fun (E) -> is_atom(E) andalso E =/= unassigned end,
+ ClientSignatureSchemes).
get_supported_groups(#supported_groups{supported_groups = Groups}) ->
Groups.
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index 9f0c588cb6..a5c550a429 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -602,16 +602,18 @@ encode_fragments(_Type, _Version, _Data, CS, _CompS, _CipherS, _Seq, _CipherFrag
%% 1/n-1 splitting countermeasure Rizzo/Duong-Beast, RC4 chiphers are
%% not vulnerable to this attack.
-split_iovec([<<FirstByte:8, Rest/binary>>|Data], Version, BCA, one_n_minus_one)
+split_iovec(Data, Version, BCA, one_n_minus_one)
when (BCA =/= ?RC4) andalso ({3, 1} == Version orelse
{3, 0} == Version) ->
- [[FirstByte]|split_iovec([Rest|Data])];
+ {Part, RestData} = split_iovec(Data, 1, []),
+ [Part|split_iovec(RestData)];
%% 0/n splitting countermeasure for clients that are incompatible with 1/n-1
%% splitting.
split_iovec(Data, Version, BCA, zero_n)
when (BCA =/= ?RC4) andalso ({3, 1} == Version orelse
{3, 0} == Version) ->
- [<<>>|split_iovec(Data)];
+ {Part, RestData} = split_iovec(Data, 0, []),
+ [Part|split_iovec(RestData)];
split_iovec(Data, _Version, _BCA, _BeatMitigation) ->
split_iovec(Data).
@@ -621,16 +623,16 @@ split_iovec(Data) ->
{Part,Rest} = split_iovec(Data, ?MAX_PLAIN_TEXT_LENGTH, []),
[Part|split_iovec(Rest)].
%%
-split_iovec([Bin|Data], SplitSize, Acc) ->
+split_iovec([Bin|Data] = Bin_Data, SplitSize, Acc) ->
BinSize = byte_size(Bin),
if
+ BinSize =< SplitSize ->
+ split_iovec(Data, SplitSize - BinSize, [Bin|Acc]);
+ SplitSize == 0 ->
+ {lists:reverse(Acc), Bin_Data};
SplitSize < BinSize ->
{Last, Rest} = erlang:split_binary(Bin, SplitSize),
- {lists:reverse(Acc, [Last]), [Rest|Data]};
- BinSize < SplitSize ->
- split_iovec(Data, SplitSize - BinSize, [Bin|Acc]);
- true -> % Perfect match
- {lists:reverse(Acc, [Bin]), Data}
+ {lists:reverse(Acc, [Last]), [Rest|Data]}
end;
split_iovec([], _SplitSize, Acc) ->
{lists:reverse(Acc),[]}.
diff --git a/lib/ssl/src/tls_record_1_3.erl b/lib/ssl/src/tls_record_1_3.erl
index 97331e1510..74321a1ae2 100644
--- a/lib/ssl/src/tls_record_1_3.erl
+++ b/lib/ssl/src/tls_record_1_3.erl
@@ -252,7 +252,7 @@ cipher_aead(Fragment, BulkCipherAlgo, Key, Seq, IV, TagLen) ->
AAD = additional_data(erlang:iolist_size(Fragment) + TagLen),
Nonce = nonce(Seq, IV),
{Content, CipherTag} =
- ssl_cipher:aead_encrypt(BulkCipherAlgo, Key, Nonce, Fragment, AAD),
+ ssl_cipher:aead_encrypt(BulkCipherAlgo, Key, Nonce, Fragment, AAD, TagLen),
<<Content/binary, CipherTag/binary>>.
encode_tls_cipher_text(#tls_cipher_text{opaque_type = Type,
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index fc483b0a94..f7fae16088 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -64,8 +64,9 @@ MODULES = \
ssl_sni_SUITE \
ssl_eqc_SUITE \
ssl_rfc_5869_SUITE \
- make_certs\
- x509_test
+ make_certs \
+ x509_test \
+ inet_crypto_dist
ERL_FILES = $(MODULES:%=%.erl)
diff --git a/lib/ssl/test/inet_crypto_dist.erl b/lib/ssl/test/inet_crypto_dist.erl
new file mode 100644
index 0000000000..5aafaac983
--- /dev/null
+++ b/lib/ssl/test/inet_crypto_dist.erl
@@ -0,0 +1,1323 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019. 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%
+%%
+%% -------------------------------------------------------------------------
+%%
+%% Module for encrypted Erlang protocol - a minimal encrypted
+%% distribution protocol based on only a shared secret
+%% and the crypto application
+%%
+-module(inet_crypto_dist).
+-define(DIST_NAME, inet_crypto).
+-define(DIST_PROTO, crypto).
+-define(DRIVER, inet_tcp).
+-define(FAMILY, inet).
+
+-define(PROTOCOL, inet_crypto_dist_v1).
+-define(DEFAULT_BLOCK_CRYPTO, aes_128_gcm).
+-define(DEFAULT_HASH_ALGORITHM, sha256).
+-define(DEFAULT_REKEY_INTERVAL, 32768).
+
+-export([listen/1, accept/1, accept_connection/5,
+ setup/5, close/1, select/1, is_node_name/1]).
+-export([is_supported/0]).
+
+%% Generalized dist API, for sibling IPv6 module inet6_crypto_dist
+-export([gen_listen/2, gen_accept/2, gen_accept_connection/6,
+ gen_setup/6, gen_close/2, gen_select/2]).
+
+-export([nodelay/0]).
+
+%% Debug
+%%%-compile(export_all).
+-export([dbg/0, test_server/0, test_client/1]).
+
+-include_lib("kernel/include/net_address.hrl").
+-include_lib("kernel/include/dist.hrl").
+-include_lib("kernel/include/dist_util.hrl").
+
+%% Test if crypto has got enough capabilities for this module to run
+%%
+is_supported() ->
+ try {crypto:cipher_info(?DEFAULT_BLOCK_CRYPTO),
+ crypto:hash_info(?DEFAULT_HASH_ALGORITHM)}
+ of
+ {#{block_size := _, iv_length := _, key_length := _},
+ #{size := _}} ->
+ true
+ catch
+ error:undef ->
+ false
+ end.
+
+%% -------------------------------------------------------------------------
+%% Erlang distribution plugin structure explained to myself
+%% -------
+%% These are the processes involved in the distribution:
+%% * net_kernel
+%% * The Acceptor
+%% * The Controller | Handshaker | Ticker
+%% * The DistCtrl process that may be split into:
+%% + The Output controller
+%% + The Input controller
+%% For the regular inet_tcp_dist distribution module, DistCtrl
+%% is not one or two processes, but one port - a gen_tcp socket
+%%
+%% When the VM is started with the argument "-proto_dist inet_crypto"
+%% net_kernel registers the module inet_crypto_dist as distribution
+%% module. net_kernel calls listen/1 to create a listen socket
+%% and then accept/1 with the listen socket as argument to spawn
+%% the Acceptor process, which is linked to net_kernel. Apparently
+%% the listen socket is owned by net_kernel - I wonder if it could
+%% be owned by the Acceptor process instead...
+%%
+%% The Acceptor process calls blocking accept on the listen socket
+%% and when an incoming socket is returned it spawns the DistCtrl
+%% process a linked to the Acceptor. The ownership of the accepted
+%% socket is transferred to the DistCtrl process.
+%% A message is sent to net_kernel to inform it that an incoming
+%% connection has appeared and the Acceptor awaits a reply from net_kernel.
+%%
+%% net_kernel then calls accept_connection/5 to spawn the Controller |
+%% Handshaker | Ticker process that is linked to net_kernel.
+%% The Controller then awaits a message from the Acceptor process.
+%%
+%% When net_kernel has spawned the Controller it replies with a message
+%% to the Acceptor that then calls DistCtrl to changes its links
+%% so DistCtrl ends up linked to the Controller and not to the Acceptor.
+%% The Acceptor then sends a message to the Controller. The Controller
+%% then changes role into the Handshaker creates a #hs_data{} record
+%% and calls dist_util:handshake_other_started/1. After this
+%% the Acceptor goes back into a blocking accept on the listen socket.
+%%
+%% For the regular distribution inet_tcp_dist DistCtrl is a gen_tcp socket
+%% and when it is a process it also acts as a socket. The #hs_data{}
+%% record used by dist_util presents a set of funs that are used
+%% by dist_util to perform the distribution handshake. These funs
+%% make sure to transfer the handshake messages through the DistCtrl
+%% "socket".
+%%
+%% When the handshake is finished a fun for this purpose in #hs_data{}
+%% is called, which tells DistCtrl that it does not need to be prepared
+%% for any more #hs_data{} handshake calls. The DistCtrl process in this
+%% module then spawns the Input controller process that gets ownership
+%% of the connection's gen_tcp socket and changes into {active, N} mode
+%% so now it gets all incoming traffic and delivers that to the VM.
+%% The original DistCtrl process changes role into the Output controller
+%% process and starts asking the VM for outbound messages and transfers
+%% them on the connection socket.
+%%
+%% The Handshaker now changes into the Ticker role, and uses only two
+%% functions in the #hs_data{} record; one to get socket statistics
+%% and one to send a tick. None of these may block for any reason
+%% in particular not for a congested socket since that would destroy
+%% connection supervision.
+%%
+%%
+%% For an connection net_kernel calls setup/5 which spawns the
+%% Controller process as linked to net_kernel. This Controller process
+%% connects to the other node's listen socket and when that is succesful
+%% spawns the DistCtrl process as linked to the controller and transfers
+%% socket ownership to it.
+%%
+%% Then the Controller creates the #hs_data{} record and calls
+%% dist_util:handshake_we_started/1 which changes the process role
+%% into Handshaker.
+%%
+%% When the distribution handshake is finished the procedure is just
+%% as for an incoming connection above.
+%%
+%%
+%% To sum it up.
+%%
+%% There is an Acceptor process that is linked to net_kernel and
+%% informs it when new connections arrive.
+%%
+%% net_kernel spawns Controllers for incoming and for outgoing connections.
+%% these Controllers use the DistCtrl processes to do distribution
+%% handshake and after that becomes Tickers that supervise the connection.
+%%
+%% The Controller | Handshaker | Ticker is linked to net_kernel, and to
+%% DistCtrl, one or both. If any of these connection processes would die
+%% all others should be killed by the links. Therefore none of them may
+%% terminate with reason 'normal'.
+%% -------------------------------------------------------------------------
+
+%% -------------------------------------------------------------------------
+%% select/1 is called by net_kernel to ask if this distribution protocol
+%% is willing to handle Node
+%%
+
+select(Node) ->
+ gen_select(Node, ?DRIVER).
+
+gen_select(Node, Driver) ->
+ case dist_util:split_node(Node) of
+ {node, _, Host} ->
+ case Driver:getaddr(Host) of
+ {ok, _} -> true;
+ _ -> false
+ end;
+ _ ->
+ false
+ end.
+
+%% -------------------------------------------------------------------------
+
+is_node_name(Node) ->
+ dist_util:is_node_name(Node).
+
+%% -------------------------------------------------------------------------
+%% Called by net_kernel to create a listen socket for this
+%% distribution protocol. This listen socket is used by
+%% the Acceptor process.
+%%
+
+listen(Name) ->
+ gen_listen(Name, ?DRIVER).
+
+gen_listen(Name, Driver) ->
+ case inet_tcp_dist:gen_listen(Driver, Name) of
+ {ok, {Socket, Address, Creation}} ->
+ inet:setopts(Socket, [binary, {nodelay, true}]),
+ {ok,
+ {Socket, Address#net_address{protocol = ?DIST_PROTO}, Creation}};
+ Other ->
+ Other
+ end.
+
+%% -------------------------------------------------------------------------
+%% Called by net_kernel to spawn the Acceptor process that awaits
+%% new connection in a blocking accept and informs net_kernel
+%% when a new connection has appeared, and starts the DistCtrl
+%% "socket" process for the connection.
+%%
+
+accept(Listen) ->
+ gen_accept(Listen, ?DRIVER).
+
+gen_accept(Listen, Driver) ->
+ NetKernel = self(),
+ %%
+ %% Spawn Acceptor process
+ %%
+ Config = config(),
+ monitor_dist_proc(
+ spawn_opt(
+ fun () ->
+ accept_loop(Listen, Driver, NetKernel, Config)
+ end,
+ [link, {priority, max}])).
+
+accept_loop(Listen, Driver, NetKernel, Config) ->
+ case Driver:accept(Listen) of
+ {ok, Socket} ->
+ wait_for_code_server(),
+ Timeout = net_kernel:connecttime(),
+ DistCtrl = start_dist_ctrl(Socket, Config, Timeout),
+ %% DistCtrl is a "socket"
+ NetKernel !
+ {accept,
+ self(), DistCtrl, Driver:family(), ?DIST_PROTO},
+ receive
+ {NetKernel, controller, Controller} ->
+ call_dist_ctrl(DistCtrl, {controller, Controller, self()}),
+ Controller ! {self(), controller, Socket};
+ {NetKernel, unsupported_protocol} ->
+ exit(unsupported_protocol)
+ end,
+ accept_loop(Listen, Driver, NetKernel, Config);
+ AcceptError ->
+ exit({accept, AcceptError})
+ end.
+
+wait_for_code_server() ->
+ %% This is an ugly hack. Starting encryption on a connection
+ %% requires the crypto module to be loaded. Loading the crypto
+ %% module triggers its on_load function, which calls
+ %% code:priv_dir/1 to find the directory where its NIF library is.
+ %% However, distribution is started earlier than the code server,
+ %% so the code server is not necessarily started yet, and
+ %% code:priv_dir/1 might fail because of that, if we receive
+ %% an incoming connection on the distribution port early enough.
+ %%
+ %% If the on_load function of a module fails, the module is
+ %% unloaded, and the function call that triggered loading it fails
+ %% with 'undef', which is rather confusing.
+ %%
+ %% So let's avoid that by waiting for the code server to start.
+ %%
+ case whereis(code_server) of
+ undefined ->
+ timer:sleep(10),
+ wait_for_code_server();
+ Pid when is_pid(Pid) ->
+ ok
+ end.
+
+%% -------------------------------------------------------------------------
+%% Called by net_kernel when a new connection has appeared, to spawn
+%% a Controller process that performs the handshake with the new node,
+%% and then becomes the Ticker connection supervisor.
+%% -------------------------------------------------------------------------
+
+accept_connection(Acceptor, DistCtrl, MyNode, Allowed, SetupTime) ->
+ gen_accept_connection(
+ Acceptor, DistCtrl, MyNode, Allowed, SetupTime, ?DRIVER).
+
+gen_accept_connection(
+ Acceptor, DistCtrl, MyNode, Allowed, SetupTime, Driver) ->
+ NetKernel = self(),
+ %%
+ %% Spawn Controller/handshaker/ticker process
+ %%
+ monitor_dist_proc(
+ spawn_opt(
+ fun() ->
+ do_accept(
+ Acceptor, DistCtrl,
+ MyNode, Allowed, SetupTime, Driver, NetKernel)
+ end,
+ [link, {priority, max}])).
+
+do_accept(
+ Acceptor, DistCtrl, MyNode, Allowed, SetupTime, Driver, NetKernel) ->
+ receive
+ {Acceptor, controller, Socket} ->
+ Timer = dist_util:start_timer(SetupTime),
+ HSData =
+ hs_data_common(
+ NetKernel, MyNode, DistCtrl, Timer,
+ Socket, Driver:family()),
+ HSData_1 =
+ HSData#hs_data{
+ this_node = MyNode,
+ this_flags = 0,
+ allowed = Allowed},
+ dist_util:handshake_other_started(trace(HSData_1))
+ end.
+
+%% -------------------------------------------------------------------------
+%% Called by net_kernel to spawn a Controller process that sets up
+%% a new connection to another Erlang node, performs the handshake
+%% with the other it, and then becomes the Ticker process
+%% that supervises the connection.
+%% -------------------------------------------------------------------------
+
+setup(Node, Type, MyNode, LongOrShortNames, SetupTime) ->
+ gen_setup(Node, Type, MyNode, LongOrShortNames, SetupTime, ?DRIVER).
+
+gen_setup(Node, Type, MyNode, LongOrShortNames, SetupTime, Driver) ->
+ NetKernel = self(),
+ %%
+ %% Spawn Controller/handshaker/ticker process
+ %%
+ monitor_dist_proc(
+ spawn_opt(
+ setup_fun(
+ Node, Type, MyNode, LongOrShortNames, SetupTime, Driver, NetKernel),
+ [link, {priority, max}])).
+
+-spec setup_fun(_,_,_,_,_,_,_) -> fun(() -> no_return()).
+setup_fun(
+ Node, Type, MyNode, LongOrShortNames, SetupTime, Driver, NetKernel) ->
+ fun() ->
+ do_setup(
+ Node, Type, MyNode, LongOrShortNames, SetupTime,
+ Driver, NetKernel)
+ end.
+
+-spec do_setup(_,_,_,_,_,_,_) -> no_return().
+do_setup(
+ Node, Type, MyNode, LongOrShortNames, SetupTime, Driver, NetKernel) ->
+ {Name, Address} = split_node(Driver, Node, LongOrShortNames),
+ ErlEpmd = net_kernel:epmd_module(),
+ {ARMod, ARFun} = get_address_resolver(ErlEpmd, Driver),
+ Timer = trace(dist_util:start_timer(SetupTime)),
+ case ARMod:ARFun(Name, Address, Driver:family()) of
+ {ok, Ip, TcpPort, Version} ->
+ do_setup_connect(
+ Node, Type, MyNode, Timer, Driver, NetKernel,
+ Ip, TcpPort, Version);
+ {ok, Ip} ->
+ case ErlEpmd:port_please(Name, Ip) of
+ {port, TcpPort, Version} ->
+ do_setup_connect(
+ Node, Type, MyNode, Timer, Driver, NetKernel,
+ Ip, TcpPort, Version);
+ Other ->
+ ?shutdown2(
+ Node,
+ trace(
+ {port_please_failed, ErlEpmd, Name, Ip, Other}))
+ end;
+ Other ->
+ ?shutdown2(
+ Node,
+ trace({getaddr_failed, Driver, Address, Other}))
+ end.
+
+-spec do_setup_connect(_,_,_,_,_,_,_,_,_) -> no_return().
+
+do_setup_connect(
+ Node, Type, MyNode, Timer, Driver, NetKernel,
+ Ip, TcpPort, Version) ->
+ dist_util:reset_timer(Timer),
+ ConnectOpts =
+ trace(
+ connect_options(
+ [binary, {active, false}, {packet, 2}, {nodelay, true}])),
+ case Driver:connect(Ip, TcpPort, ConnectOpts) of
+ {ok, Socket} ->
+ Config = config(),
+ DistCtrl =
+ start_dist_ctrl(Socket, Config, net_kernel:connecttime()),
+ %% DistCtrl is a "socket"
+ HSData =
+ hs_data_common(
+ NetKernel, MyNode, DistCtrl, Timer,
+ Socket, Driver:family()),
+ HSData_1 =
+ HSData#hs_data{
+ other_node = Node,
+ this_flags = 0,
+ other_version = Version,
+ request_type = Type},
+ dist_util:handshake_we_started(trace(HSData_1));
+ ConnectError ->
+ ?shutdown2(Node,
+ trace({connect_failed, Ip, TcpPort, ConnectError}))
+ end.
+
+%% -------------------------------------------------------------------------
+%% close/1 is only called by net_kernel on the socket returned by listen/1.
+
+close(Socket) ->
+ gen_close(Socket, ?DRIVER).
+
+gen_close(Socket, Driver) ->
+ trace(Driver:close(Socket)).
+
+%% -------------------------------------------------------------------------
+
+
+hs_data_common(NetKernel, MyNode, DistCtrl, Timer, Socket, Family) ->
+ %% Field 'socket' below is set to DistCtrl, which makes
+ %% the distribution handshake process (ticker) call
+ %% the funs below with DistCtrl as the S argument.
+ %% So, S =:= DistCtrl below...
+ #hs_data{
+ kernel_pid = NetKernel,
+ this_node = MyNode,
+ socket = DistCtrl,
+ timer = Timer,
+ %%
+ f_send =
+ fun (S, Packet) when S =:= DistCtrl ->
+ call_dist_ctrl(S, {send, Packet})
+ end,
+ f_recv =
+ fun (S, 0, infinity) when S =:= DistCtrl ->
+ case call_dist_ctrl(S, recv) of
+ {ok, Bin} when is_binary(Bin) ->
+ {ok, binary_to_list(Bin)};
+ Error ->
+ Error
+ end
+ end,
+ f_setopts_pre_nodeup =
+ fun (S) when S =:= DistCtrl ->
+ ok
+ end,
+ f_setopts_post_nodeup =
+ fun (S) when S =:= DistCtrl ->
+ ok
+ end,
+ f_getll =
+ fun (S) when S =:= DistCtrl ->
+ {ok, S} %% DistCtrl is the distribution port
+ end,
+ f_address =
+ fun (S, Node) when S =:= DistCtrl ->
+ case call_dist_ctrl(S, peername) of
+ {ok, Address} ->
+ case dist_util:split_node(Node) of
+ {node, _, Host} ->
+ #net_address{
+ address = Address,
+ host = Host,
+ protocol = ?DIST_PROTO,
+ family = Family};
+ _ ->
+ {error, no_node}
+ end
+ end
+ end,
+ f_handshake_complete =
+ fun (S, _Node, DistHandle) when S =:= DistCtrl ->
+ call_dist_ctrl(S, {handshake_complete, DistHandle})
+ end,
+ %%
+ %% mf_tick/1, mf_getstat/1, mf_setopts/2 and mf_getopts/2
+ %% are called by the ticker any time after f_handshake_complete/3
+ %% so they may not block the caller even for congested socket
+ mf_tick =
+ fun (S) when S =:= DistCtrl ->
+ S ! dist_tick
+ end,
+ mf_getstat =
+ fun (S) when S =:= DistCtrl ->
+ case
+ inet:getstat(Socket, [recv_cnt, send_cnt, send_pend])
+ of
+ {ok, Stat} ->
+ split_stat(Stat, 0, 0, 0);
+ Error ->
+ Error
+ end
+ end,
+ mf_setopts =
+ fun (S, Opts) when S =:= DistCtrl ->
+ inet:setopts(Socket, setopts_filter(Opts))
+ end,
+ mf_getopts =
+ fun (S, Opts) when S =:= DistCtrl ->
+ inet:getopts(Socket, Opts)
+ end}.
+
+setopts_filter(Opts) ->
+ [Opt ||
+ Opt <- Opts,
+ case Opt of
+ {K, _} when K =:= active; K =:= deliver; K =:= packet -> false;
+ K when K =:= list; K =:= binary -> false;
+ K when K =:= inet; K =:= inet6 -> false;
+ _ -> true
+ end].
+
+split_stat([{recv_cnt, R}|Stat], _, W, P) ->
+ split_stat(Stat, R, W, P);
+split_stat([{send_cnt, W}|Stat], R, _, P) ->
+ split_stat(Stat, R, W, P);
+split_stat([{send_pend, P}|Stat], R, W, _) ->
+ split_stat(Stat, R, W, P);
+split_stat([], R, W, P) ->
+ {ok, R, W, P}.
+
+%% ------------------------------------------------------------
+%% Determine if EPMD module supports address resolving. Default
+%% is to use inet_tcp:getaddr/2.
+%% ------------------------------------------------------------
+get_address_resolver(EpmdModule, _Driver) ->
+ case erlang:function_exported(EpmdModule, address_please, 3) of
+ true -> {EpmdModule, address_please};
+ _ -> {erl_epmd, address_please}
+ end.
+
+
+%% If Node is illegal terminate the connection setup!!
+split_node(Driver, Node, LongOrShortNames) ->
+ case dist_util:split_node(Node) of
+ {node, Name, Host} ->
+ check_node(Driver, Node, Name, Host, LongOrShortNames);
+ {host, _} ->
+ error_logger:error_msg(
+ "** Nodename ~p illegal, no '@' character **~n",
+ [Node]),
+ ?shutdown2(Node, trace({illegal_node_n@me, Node}));
+ _ ->
+ error_logger:error_msg(
+ "** Nodename ~p illegal **~n", [Node]),
+ ?shutdown2(Node, trace({illegal_node_name, Node}))
+ end.
+
+check_node(Driver, Node, Name, Host, LongOrShortNames) ->
+ case string:split(Host, ".", all) of
+ [_] when LongOrShortNames =:= longnames ->
+ case Driver:parse_address(Host) of
+ {ok, _} ->
+ {Name, Host};
+ _ ->
+ error_logger:error_msg(
+ "** System running to use "
+ "fully qualified hostnames **~n"
+ "** Hostname ~s is illegal **~n",
+ [Host]),
+ ?shutdown2(Node, trace({not_longnames, Host}))
+ end;
+ [_, _|_] when LongOrShortNames =:= shortnames ->
+ error_logger:error_msg(
+ "** System NOT running to use "
+ "fully qualified hostnames **~n"
+ "** Hostname ~s is illegal **~n",
+ [Host]),
+ ?shutdown2(Node, trace({not_shortnames, Host}));
+ _ ->
+ {Name, Host}
+ end.
+
+%% -------------------------------------------------------------------------
+
+connect_options(Opts) ->
+ case application:get_env(kernel, inet_dist_connect_options) of
+ {ok, ConnectOpts} ->
+ Opts ++ setopts_filter(ConnectOpts);
+ _ ->
+ Opts
+ end.
+
+%% we may not always want the nodelay behaviour
+%% for performance reasons
+nodelay() ->
+ case application:get_env(kernel, dist_nodelay) of
+ undefined ->
+ {nodelay, true};
+ {ok, true} ->
+ {nodelay, true};
+ {ok, false} ->
+ {nodelay, false};
+ _ ->
+ {nodelay, true}
+ end.
+
+config() ->
+ case init:get_argument(?DIST_NAME) of
+ error ->
+ error({missing_argument, ?DIST_NAME});
+ {ok, [[String]]} ->
+ {ok, Tokens, _} = erl_scan:string(String ++ "."),
+ case erl_parse:parse_term(Tokens) of
+ {ok, #{secret := Secret} = Config}
+ when is_binary(Secret); is_list(Secret) ->
+ Config;
+ {ok, #{} = Config} ->
+ error({missing_secret, [{?DIST_NAME,Config}]});
+ _ ->
+ error({bad_argument_value, [{?DIST_NAME,String}]})
+ end;
+ {ok, Value} ->
+ error({malformed_argument, [{?DIST_NAME,Value}]})
+ end.
+
+%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% The DistCtrl process(es).
+%%
+%% At net_kernel handshake_complete spawns off the input controller that
+%% takes over the socket ownership, and itself becomes the output controller
+%%
+%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%% XXX Missing to "productified":
+%%% * Cryptoanalysis by experts
+%%% * Proof of usefulness
+%%% * Unifying exit reasons using a death_row() function
+%%% * Verification (and rejection) of other end's crypto parameters
+%%% * OTP:ification (proc_lib?)
+%%% * An application to belong to (crypto|kernel?)
+%%% * Secret on file (cookie as default?), parameter handling
+%%% * Restart and/or code reload policy
+
+%% Debug client and server
+
+test_config() ->
+ #{secret => <<"Secret Cluster Password 123456">>}.
+
+test_server() ->
+ {ok, Listen} = gen_tcp:listen(0, [{packet, 2}, {active, false}, binary]),
+ {ok, Port} = inet:port(Listen),
+ io:format(?MODULE_STRING":test_client(~w).~n", [Port]),
+ {ok, Socket} = gen_tcp:accept(Listen),
+ test(Socket).
+
+test_client(Port) ->
+ {ok, Socket} =
+ gen_tcp:connect(
+ localhost, Port, [{packet, 2}, {active, false}, binary]),
+ test(Socket).
+
+test(Socket) ->
+ start_dist_ctrl(Socket, test_config(), 10000).
+
+%% -------------------------------------------------------------------------
+
+start_dist_ctrl(Socket, Config, Timeout) ->
+ Protocol = ?PROTOCOL,
+ Controller = self(),
+ Server =
+ monitor_dist_proc(
+ spawn_opt(
+ fun () ->
+ receive
+ {?MODULE, From, start} ->
+ {SendParams, RecvParams} =
+ init(Socket, Config, Protocol),
+ reply(From, self()),
+ handshake(SendParams, 0, RecvParams, 0, Controller)
+ end
+ end,
+ [link,
+ {priority, max},
+ {message_queue_data, off_heap},
+ {fullsweep_after, 0}])),
+ ok = gen_tcp:controlling_process(Socket, Server),
+ call_dist_ctrl(Server, start, Timeout).
+
+
+call_dist_ctrl(Server, Msg) ->
+ call_dist_ctrl(Server, Msg, infinity).
+%%
+call_dist_ctrl(Server, Msg, Timeout) ->
+ Ref = erlang:monitor(process, Server),
+ Server ! {?MODULE, {Ref, self()}, Msg},
+ receive
+ {Ref, Res} ->
+ erlang:demonitor(Ref, [flush]),
+ Res;
+ {'DOWN', Ref, process, Server, Reason} ->
+ exit({?PROTOCOL, Reason})
+ after Timeout ->
+ exit(Server, timeout),
+ receive
+ {'DOWN', Ref, process, Server, _} ->
+ exit({?PROTOCOL, timeout})
+ end
+ end.
+
+reply({Ref, Pid}, Msg) ->
+ Pid ! {Ref, Msg},
+ ok.
+
+%% -------------------------------------------------------------------------
+
+-record(params,
+ {protocol, % Encryption protocol tag
+ socket,
+ dist_handle,
+ hash_algorithm,
+ block_crypto,
+ rekey_interval,
+ iv,
+ key,
+ tag_len}).
+
+-define(TCP_ACTIVE, 64).
+-define(CHUNK_SIZE, (65536 - 512)).
+%% The start chunk starts with zeros, so it seems logical to not have
+%% a chunk type with value 0
+-define(HANDSHAKE_CHUNK, 1).
+-define(DATA_CHUNK, 2).
+-define(TICK_CHUNK, 3).
+-define(REKEY_CHUNK, 4).
+
+%% -------------------------------------------------------------------------
+%% Crypto strategy
+%% -------
+%% The crypto strategy is as simple as possible to get an encrypted
+%% connection as benchmark reference. It is geared around AEAD
+%% ciphers in particular AES-GCM.
+%%
+%% The init message and the start message must fit in the TCP buffers
+%% since both sides start with sending the init message, waits
+%% for the other end's init message, sends the start message
+%% and waits for the other end's start message. So if the send
+%% blocks we have a deadlock.
+%%
+%% The init message is unencrypted and contains the block cipher and hash
+%% algorithms the sender will use, the IV and a key salt. Both sides'
+%% key salt is used with the mutual secret as input to the hash algorithm
+%% to create different encryption/decryption keys for both directions.
+%%
+%% The start message is the first encrypted message and contains just
+%% encrypted zeros the width of the key, with the header of the init
+%% message as AAD data. Successfully decrypting this message
+%% verifies that we have an encrypted channel.
+%%
+%% Subsequent encrypted messages has the sequence number and the length
+%% of the message as AAD data. These messages has got a message type
+%% differentiating data from ticks. Ticks have a random size in an
+%% attempt to make them less obvious to spot.
+%%
+%% The only reaction to errors is to crash noisily wich will bring
+%% down the connection and hopefully produce something useful
+%% in the local log, but all the other end sees is a closed connection.
+%% -------------------------------------------------------------------------
+
+init(Socket, Config, Protocol) ->
+ Secret = maps:get(secret, Config),
+ HashAlgorithm =
+ maps:get(hash_algorithm, Config, ?DEFAULT_HASH_ALGORITHM),
+ BlockCrypto =
+ maps:get(block_crypto, Config, ?DEFAULT_BLOCK_CRYPTO),
+ RekeyInterval =
+ maps:get(rekey_interval, Config, ?DEFAULT_REKEY_INTERVAL),
+ %%
+ SendParams =
+ init_params(
+ Socket, Protocol, HashAlgorithm, BlockCrypto, RekeyInterval),
+ send_init(SendParams, Secret).
+
+send_init(
+ #params{
+ protocol = Protocol,
+ socket = Socket,
+ block_crypto = BlockCrypto,
+ iv = IVLen,
+ key = KeyLen,
+ hash_algorithm = HashAlgorithm} = SendParams,
+ Secret) ->
+ %%
+ ProtocolString = atom_to_binary(Protocol, utf8),
+ BlockCryptoString = atom_to_binary(BlockCrypto, utf8),
+ HashAlgorithmString = atom_to_binary(HashAlgorithm, utf8),
+ SendHeader =
+ <<ProtocolString/binary, 0,
+ HashAlgorithmString/binary, 0,
+ BlockCryptoString/binary, 0>>,
+ <<IV:IVLen/binary, KeySalt:KeyLen/binary>> = IV_KeySalt =
+ crypto:strong_rand_bytes(IVLen + KeyLen),
+ InitPacket = [SendHeader, IV_KeySalt],
+ ok = gen_tcp:send(Socket, InitPacket),
+ recv_init(SendParams#params{iv = IV, key = KeySalt}, Secret, SendHeader).
+
+recv_init(
+ #params{
+ socket = Socket,
+ hash_algorithm = SendHashAlgorithm,
+ key = SendKeySalt} = SendParams, Secret, SendHeader) ->
+ %%
+ {ok, InitPacket} = gen_tcp:recv(Socket, 0),
+ [ProtocolString, Rest_1] = binary:split(InitPacket, <<0>>),
+ Protocol = binary_to_existing_atom(ProtocolString, utf8),
+ case Protocol of
+ ?PROTOCOL ->
+ [HashAlgorithmString, Rest_2] = binary:split(Rest_1, <<0>>),
+ HashAlgorithm = binary_to_existing_atom(HashAlgorithmString, utf8),
+ [BlockCryptoString, Rest_3] = binary:split(Rest_2, <<0>>),
+ BlockCrypto = binary_to_existing_atom(BlockCryptoString, utf8),
+ #params{
+ hash_algorithm = RecvHashAlgorithm,
+ iv = RecvIVLen,
+ key = RecvKeyLen} = RecvParams =
+ init_params(
+ Socket, Protocol, HashAlgorithm, BlockCrypto, undefined),
+ <<RecvIV:RecvIVLen/binary,
+ RecvKeySalt:RecvKeyLen/binary>> = Rest_3,
+ SendKey =
+ hash_key(SendHashAlgorithm, SendKeySalt, [RecvKeySalt, Secret]),
+ RecvKey =
+ hash_key(RecvHashAlgorithm, RecvKeySalt, [SendKeySalt, Secret]),
+ SendParams_1 = SendParams#params{key = SendKey},
+ RecvParams_1 = RecvParams#params{iv = RecvIV, key = RecvKey},
+ RecvHeaderLen = byte_size(InitPacket) - RecvIVLen - RecvKeyLen,
+ <<RecvHeader:RecvHeaderLen/binary, _/binary>> = InitPacket,
+ send_start(SendParams_1, SendHeader),
+ RecvRekeyInterval = recv_start(RecvParams_1, RecvHeader),
+ {SendParams_1,
+ RecvParams_1#params{rekey_interval = RecvRekeyInterval}}
+ end.
+
+send_start(
+ #params{
+ socket = Socket,
+ block_crypto = BlockCrypto,
+ rekey_interval= RekeyInterval,
+ iv = IV,
+ key = Key,
+ tag_len = TagLen}, AAD) ->
+ %%
+ KeyLen = byte_size(Key),
+ Zeros = binary:copy(<<0>>, KeyLen),
+ {Ciphertext, CipherTag} =
+ crypto:block_encrypt(
+ crypto_cipher_name(BlockCrypto),
+ Key, IV, {AAD, [Zeros, <<RekeyInterval:32>>], TagLen}),
+ ok = gen_tcp:send(Socket, [Ciphertext, CipherTag]).
+
+recv_start(
+ #params{
+ socket = Socket,
+ block_crypto = BlockCrypto,
+ iv = IV,
+ key = Key,
+ tag_len = TagLen}, AAD) ->
+ {ok, Packet} = gen_tcp:recv(Socket, 0),
+ KeyLen = byte_size(Key),
+ PacketLen = KeyLen + 4,
+ <<Ciphertext:PacketLen/binary, CipherTag:TagLen/binary>> = Packet,
+ Zeros = binary:copy(<<0>>, KeyLen),
+ case
+ crypto:block_decrypt(
+ crypto_cipher_name(BlockCrypto),
+ Key, IV, {AAD, Ciphertext, CipherTag})
+ of
+ <<Zeros:KeyLen/binary, RekeyInterval:32>>
+ when 1 =< RekeyInterval ->
+ RekeyInterval;
+ _ ->
+ error(decrypt_error)
+ end.
+
+init_params(Socket, Protocol, HashAlgorithm, BlockCrypto, RekeyInterval) ->
+ #{block_size := 1,
+ iv_length := IVLen,
+ key_length := KeyLen} = crypto:cipher_info(BlockCrypto),
+ case crypto:hash_info(HashAlgorithm) of
+ #{size := HashSize} when HashSize >= KeyLen ->
+ #params{
+ socket = Socket,
+ protocol = Protocol,
+ hash_algorithm = HashAlgorithm,
+ block_crypto = BlockCrypto,
+ rekey_interval = RekeyInterval,
+ iv = IVLen,
+ key = KeyLen,
+ tag_len = 16}
+ end.
+
+crypto_cipher_name(BlockCrypto) ->
+ case BlockCrypto of
+ aes_128_gcm -> aes_gcm;
+ aes_192_gcm -> aes_gcm;
+ aes_256_gcm -> aes_gcm
+ end.
+
+hash_key(HashAlgorithm, KeySalt, OtherSalt) ->
+ KeyLen = byte_size(KeySalt),
+ <<Key:KeyLen/binary, _/binary>> =
+ crypto:hash(HashAlgorithm, [KeySalt, OtherSalt]),
+ Key.
+
+%% -------------------------------------------------------------------------
+%% net_kernel distribution handshake in progress
+%%
+
+handshake(
+ SendParams, SendSeq,
+ #params{socket = Socket} = RecvParams, RecvSeq, Controller) ->
+ receive
+ {?MODULE, From, {controller, Controller_1, Parent}} ->
+ Result = link(Controller_1),
+ true = unlink(Parent),
+ reply(From, Result),
+ handshake(SendParams, SendSeq, RecvParams, RecvSeq, Controller_1);
+ {?MODULE, From, {handshake_complete, DistHandle}} ->
+ reply(From, ok),
+ InputHandler =
+ monitor_dist_proc(
+ spawn_opt(
+ fun () ->
+ link(Controller),
+ receive
+ DistHandle ->
+ ok =
+ inet:setopts(
+ Socket,
+ [{active, ?TCP_ACTIVE},
+ nodelay()]),
+ input_handler(
+ RecvParams#params{
+ dist_handle = DistHandle},
+ RecvSeq, empty_q(), infinity)
+ end
+ end,
+ [link,
+ {priority, normal},
+ {message_queue_data, off_heap},
+ {fullsweep_after, 0}])),
+ _ = monitor(process, InputHandler), % For the benchmark test
+ ok = gen_tcp:controlling_process(Socket, InputHandler),
+ ok = erlang:dist_ctrl_input_handler(DistHandle, InputHandler),
+ InputHandler ! DistHandle,
+ process_flag(priority, normal),
+ erlang:dist_ctrl_get_data_notification(DistHandle),
+ crypto:rand_seed_alg(crypto_cache),
+ output_handler(
+ SendParams#params{dist_handle = DistHandle}, SendSeq);
+ %%
+ {?MODULE, From, {send, Data}} ->
+ {SendParams_1, SendSeq_1} =
+ encrypt_and_send_chunk(
+ SendParams, SendSeq, [?HANDSHAKE_CHUNK, Data]),
+ reply(From, ok),
+ handshake(
+ SendParams_1, SendSeq_1, RecvParams, RecvSeq, Controller);
+ {?MODULE, From, recv} ->
+ {RecvParams_1, RecvSeq_1, Reply} =
+ recv_and_decrypt_chunk(RecvParams, RecvSeq),
+ reply(From, Reply),
+ handshake(
+ SendParams, SendSeq, RecvParams_1, RecvSeq_1, Controller);
+ {?MODULE, From, peername} ->
+ reply(From, inet:peername(Socket)),
+ handshake(SendParams, SendSeq, RecvParams, RecvSeq, Controller);
+ %%
+ _Alien ->
+ handshake(SendParams, SendSeq, RecvParams, RecvSeq, Controller)
+ end.
+
+recv_and_decrypt_chunk(#params{socket = Socket} = RecvParams, RecvSeq) ->
+ case gen_tcp:recv(Socket, 0) of
+ {ok, Chunk} ->
+ case decrypt_chunk(RecvParams, RecvSeq, Chunk) of
+ <<?HANDSHAKE_CHUNK, Cleartext/binary>> ->
+ {RecvParams, RecvSeq + 1, {ok, Cleartext}};
+ #params{} = RecvParams_1 ->
+ recv_and_decrypt_chunk(RecvParams_1, 0);
+ _ ->
+ error(decrypt_error)
+ end;
+ Error ->
+ {RecvParams, RecvSeq, Error}
+ end.
+
+%% -------------------------------------------------------------------------
+%% Output handler process
+%%
+%% The game here is to flush all dist_data and dist_tick messages,
+%% prioritize dist_data over dist_tick, and to not use selective receive
+
+output_handler(Params, Seq) ->
+ receive
+ Msg ->
+ case Msg of
+ dist_data ->
+ output_handler_data(Params, Seq);
+ dist_tick ->
+ output_handler_tick(Params, Seq);
+ _Other ->
+ %% Ignore
+ output_handler(Params, Seq)
+ end
+ end.
+
+output_handler_data(Params, Seq) ->
+ receive
+ Msg ->
+ case Msg of
+ dist_data ->
+ output_handler_data(Params, Seq);
+ dist_tick ->
+ output_handler_data(Params, Seq);
+ _Other ->
+ %% Ignore
+ output_handler_data(Params, Seq)
+ end
+ after 0 ->
+ DistHandle = Params#params.dist_handle,
+ Q = get_data(DistHandle, empty_q()),
+ {Params_1, Seq_1} = output_handler_send(Params, Seq, Q, true),
+ erlang:dist_ctrl_get_data_notification(DistHandle),
+ output_handler(Params_1, Seq_1)
+ end.
+
+output_handler_tick(Params, Seq) ->
+ receive
+ Msg ->
+ case Msg of
+ dist_data ->
+ output_handler_data(Params, Seq);
+ dist_tick ->
+ output_handler_tick(Params, Seq);
+ _Other ->
+ %% Ignore
+ output_handler_tick(Params, Seq)
+ end
+ after 0 ->
+ TickSize = 8 + rand:uniform(56),
+ TickData = binary:copy(<<0>>, TickSize),
+ {Params_1, Seq_1} =
+ encrypt_and_send_chunk(Params, Seq, [?TICK_CHUNK, TickData]),
+ output_handler(Params_1, Seq_1)
+ end.
+
+output_handler_send(
+ #params{dist_handle = DistHandle} = Params, Seq, {_, Size, _} = Q, Retry) ->
+ %%
+ if
+ ?CHUNK_SIZE < Size ->
+ {Cleartext, Q_1} = deq_iovec(?CHUNK_SIZE, Q),
+ {Params_1, Seq_1} =
+ encrypt_and_send_chunk(Params, Seq, [?DATA_CHUNK, Cleartext]),
+ output_handler_send(Params_1, Seq_1, Q_1, Retry);
+ Retry ->
+ Q_1 = get_data(DistHandle, Q),
+ output_handler_send(Params, Seq, Q_1, false);
+ true ->
+ {Cleartext, _} = deq_iovec(Size, Q),
+ encrypt_and_send_chunk(Params, Seq, [?DATA_CHUNK, Cleartext])
+ end.
+
+%% -------------------------------------------------------------------------
+%% Input handler process
+%%
+%% Here is T 0 or infinity to steer if we should try to receive
+%% more data or not; start with infinity, and when we get some
+%% data try with 0 to see if more is waiting
+
+input_handler(#params{socket = Socket} = Params, Seq, Q, T) ->
+ receive
+ Msg ->
+ case Msg of
+ {tcp_passive, Socket} ->
+ ok = inet:setopts(Socket, [{active, ?TCP_ACTIVE}]),
+ Q_1 =
+ case T of
+ 0 ->
+ deliver_data(Params#params.dist_handle, Q);
+ infinity ->
+ Q
+ end,
+ input_handler(Params, Seq, Q_1, infinity);
+ {tcp, Socket, Chunk} ->
+ input_chunk(Params, Seq, Q, Chunk);
+ {tcp_closed, Socket} ->
+ error(connection_closed);
+ _Other ->
+ %% Ignore...
+ input_handler(Params, Seq, Q, T)
+ end
+ after T ->
+ Q_1 = deliver_data(Params#params.dist_handle, Q),
+ input_handler(Params, Seq, Q_1, infinity)
+ end.
+
+input_chunk(Params, Seq, Q, Chunk) ->
+ case decrypt_chunk(Params, Seq, Chunk) of
+ <<?DATA_CHUNK, Cleartext/binary>> ->
+ input_handler(Params, Seq + 1, enq_binary(Cleartext, Q), 0);
+ <<?TICK_CHUNK, _/binary>> ->
+ input_handler(Params, Seq + 1, Q, 0);
+ #params{} = Params_1 ->
+ input_handler(Params_1, 0, Q, 0);
+ _ ->
+ error(decrypt_error)
+ end.
+
+%% -------------------------------------------------------------------------
+%% erlang:dist_ctrl_* helpers
+
+%% Get data for sending from the VM and place it in a queue
+%%
+get_data(DistHandle, {Front, Size, Rear}) ->
+ get_data(DistHandle, Front, Size, Rear).
+%%
+get_data(DistHandle, Front, Size, Rear) ->
+ case erlang:dist_ctrl_get_data(DistHandle) of
+ none ->
+ {Front, Size, Rear};
+ Bin when is_binary(Bin) ->
+ Len = byte_size(Bin),
+ get_data(
+ DistHandle, Front, Size + 4 + Len,
+ [Bin, <<Len:32>>|Rear]);
+ [Bin1, Bin2] ->
+ Len = byte_size(Bin1) + byte_size(Bin2),
+ get_data(
+ DistHandle, Front, Size + 4 + Len,
+ [Bin2, Bin1, <<Len:32>>|Rear]);
+ Iovec ->
+ Len = iolist_size(Iovec),
+ get_data(
+ DistHandle, Front, Size + 4 + Len,
+ lists:reverse(Iovec, [<<Len:32>>|Rear]))
+ end.
+
+%% De-packet and deliver received data to the VM from a queue
+%%
+deliver_data(DistHandle, Q) ->
+ case Q of
+ {[], Size, []} ->
+ Size = 0, % Assert
+ Q;
+ {[], Size, Rear} ->
+ [Bin|Front] = lists:reverse(Rear),
+ deliver_data(DistHandle, Front, Size, [], Bin);
+ {[Bin|Front], Size, Rear} ->
+ deliver_data(DistHandle, Front, Size, Rear, Bin)
+ end.
+%%
+deliver_data(DistHandle, Front, Size, Rear, Bin) ->
+ case Bin of
+ <<DataSizeA:32, DataA:DataSizeA/binary,
+ DataSizeB:32, DataB:DataSizeB/binary, Rest/binary>> ->
+ erlang:dist_ctrl_put_data(DistHandle, DataA),
+ erlang:dist_ctrl_put_data(DistHandle, DataB),
+ deliver_data(
+ DistHandle,
+ Front, Size - (4 + DataSizeA + 4 + DataSizeB), Rear,
+ Rest);
+ <<DataSize:32, Data:DataSize/binary, Rest/binary>> ->
+ erlang:dist_ctrl_put_data(DistHandle, Data),
+ deliver_data(DistHandle, Front, Size - (4 + DataSize), Rear, Rest);
+ <<DataSize:32, FirstData/binary>> ->
+ TotalSize = 4 + DataSize,
+ if
+ TotalSize =< Size ->
+ BinSize = byte_size(Bin),
+ {MoreData, Q} =
+ deq_iovec(
+ TotalSize - BinSize,
+ Front, Size - BinSize, Rear),
+ erlang:dist_ctrl_put_data(DistHandle, [FirstData|MoreData]),
+ deliver_data(DistHandle, Q);
+ true -> % Incomplete data
+ {[Bin|Front], Size, Rear}
+ end;
+ <<_/binary>> ->
+ BinSize = byte_size(Bin),
+ if
+ 4 =< Size -> % Fragmented header - extract a header bin
+ {RestHeader, {Front_1, _Size_1, Rear_1}} =
+ deq_iovec(4 - BinSize, Front, Size - BinSize, Rear),
+ Header = iolist_to_binary([Bin|RestHeader]),
+ deliver_data(DistHandle, Front_1, Size, Rear_1, Header);
+ true -> % Incomplete header
+ {[Bin|Front], Size, Rear}
+ end
+ end.
+
+%% -------------------------------------------------------------------------
+%% Encryption and decryption helpers
+
+encrypt_and_send_chunk(
+ #params{
+ socket = Socket, rekey_interval = Seq,
+ key = Key, iv = IV, hash_algorithm = HashAlgorithm} = Params,
+ Seq, Cleartext) ->
+ %%
+ KeyLen = byte_size(Key),
+ IVLen = byte_size(IV),
+ Chunk = <<IV_1:IVLen/binary, KeySalt:KeyLen/binary>> =
+ crypto:strong_rand_bytes(IVLen + KeyLen),
+ ok = gen_tcp:send(Socket, encrypt_chunk(Params, Seq, [?REKEY_CHUNK, Chunk])),
+ Key_1 = hash_key(HashAlgorithm, Key, KeySalt),
+ Params_1 = Params#params{key = Key_1, iv = IV_1},
+ ok = gen_tcp:send(Socket, encrypt_chunk(Params_1, 0, Cleartext)),
+ {Params_1, 1};
+encrypt_and_send_chunk(#params{socket = Socket} = Params, Seq, Cleartext) ->
+ ok = gen_tcp:send(Socket, encrypt_chunk(Params, Seq, Cleartext)),
+ {Params, Seq + 1}.
+
+encrypt_chunk(
+ #params{
+ block_crypto = BlockCrypto,
+ iv = IV, key = Key, tag_len = TagLen}, Seq, Cleartext) ->
+ %%
+ ChunkLen = iolist_size(Cleartext) + TagLen,
+ AAD = <<Seq:32, ChunkLen:32>>,
+ {Ciphertext, CipherTag} =
+ crypto:block_encrypt(
+ crypto_cipher_name(BlockCrypto), Key, IV, {AAD, Cleartext, TagLen}),
+ Chunk = [Ciphertext,CipherTag],
+ Chunk.
+
+decrypt_chunk(
+ #params{
+ block_crypto = BlockCrypto,
+ iv = IV, key = Key, tag_len = TagLen} = Params, Seq, Chunk) ->
+ %%
+ ChunkLen = byte_size(Chunk),
+ true = TagLen =< ChunkLen, % Assert
+ AAD = <<Seq:32, ChunkLen:32>>,
+ CiphertextLen = ChunkLen - TagLen,
+ <<Ciphertext:CiphertextLen/binary, CipherTag:TagLen/binary>> = Chunk,
+ block_decrypt(
+ Params, Seq, crypto_cipher_name(BlockCrypto),
+ Key, IV, {AAD, Ciphertext, CipherTag}).
+
+block_decrypt(
+ #params{rekey_interval = Seq} = Params, Seq, CipherName, Key, IV, Data) ->
+ %%
+ KeyLen = byte_size(Key),
+ IVLen = byte_size(IV),
+ case crypto:block_decrypt(CipherName, Key, IV, Data) of
+ <<?REKEY_CHUNK, IV_1:IVLen/binary, KeySalt:KeyLen/binary>> ->
+ Key_1 = hash_key(Params#params.hash_algorithm, Key, KeySalt),
+ Params#params{iv = IV_1, key = Key_1};
+ _ ->
+ error(decrypt_error)
+ end;
+block_decrypt(_Params, _Seq, CipherName, Key, IV, Data) ->
+ crypto:block_decrypt(CipherName, Key, IV, Data).
+
+%% -------------------------------------------------------------------------
+%% Queue of binaries i.e an iovec queue
+
+empty_q() ->
+ {[], 0, []}.
+
+enq_binary(Bin, {Front, Size, Rear}) ->
+ {Front, Size + byte_size(Bin), [Bin|Rear]}.
+
+deq_iovec(GetSize, {Front, Size, Rear}) when GetSize =< Size ->
+ deq_iovec(GetSize, Front, Size, Rear, []).
+%%
+deq_iovec(GetSize, Front, Size, Rear) ->
+ deq_iovec(GetSize, Front, Size, Rear, []).
+%%
+deq_iovec(GetSize, [], Size, Rear, Acc) ->
+ deq_iovec(GetSize, lists:reverse(Rear), Size, [], Acc);
+deq_iovec(GetSize, [Bin|Front], Size, Rear, Acc) ->
+ BinSize = byte_size(Bin),
+ if
+ BinSize < GetSize ->
+ deq_iovec(
+ GetSize - BinSize, Front, Size - BinSize, Rear, [Bin|Acc]);
+ GetSize < BinSize ->
+ {Bin1,Bin2} = erlang:split_binary(Bin, GetSize),
+ {lists:reverse(Acc, [Bin1]), {[Bin2|Front], Size - GetSize, Rear}};
+ true ->
+ {lists:reverse(Acc, [Bin]), {Front, Size - BinSize, Rear}}
+ end.
+
+%% -------------------------------------------------------------------------
+
+%% Trace point
+trace(Term) -> Term.
+
+%% Keep an eye on this Pid (debug)
+monitor_dist_proc(Pid) ->
+%%% spawn(
+%%% fun () ->
+%%% MRef = erlang:monitor(process, Pid),
+%%% receive
+%%% {'DOWN', MRef, _, _, normal} ->
+%%% error_logger:error_report(
+%%% [dist_proc_died,
+%%% {reason, normal},
+%%% {pid, Pid}]);
+%%% {'DOWN', MRef, _, _, Reason} ->
+%%% error_logger:info_report(
+%%% [dist_proc_died,
+%%% {reason, Reason},
+%%% {pid, Pid}])
+%%% end
+%%% end),
+ Pid.
+
+dbg() ->
+ dbg:stop(),
+ dbg:tracer(),
+ dbg:p(all, c),
+ dbg:tpl(?MODULE, cx),
+ dbg:tpl(erlang, dist_ctrl_get_data_notification, cx),
+ dbg:tpl(erlang, dist_ctrl_get_data, cx),
+ dbg:tpl(erlang, dist_ctrl_put_data, cx),
+ ok.
diff --git a/lib/ssl/test/ssl.spec b/lib/ssl/test/ssl.spec
index 24272327c3..15587abecd 100644
--- a/lib/ssl/test/ssl.spec
+++ b/lib/ssl/test/ssl.spec
@@ -6,5 +6,7 @@
{skip_groups,dir,ssl_bench_SUITE,payload,"Benchmarks run separately"}.
{skip_groups,dir,ssl_bench_SUITE,pem_cache,"Benchmarks run separately"}.
{skip_groups,dir,ssl_dist_bench_SUITE,setup,"Benchmarks run separately"}.
+{skip_groups,dir,ssl_dist_bench_SUITE,roundtrip,"Benchmarks run separately"}.
{skip_groups,dir,ssl_dist_bench_SUITE,throughput,"Benchmarks run separately"}.
+{skip_groups,dir,ssl_dist_bench_SUITE,sched_utilization,"Benchmarks run separately"}.
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 03ee97de5d..7b98209b31 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -2775,8 +2775,8 @@ make_sure_expired(Host, Port, Id) ->
server_does_not_want_to_reuse_session() ->
[{doc,"Test reuse of sessions (short handshake)"}].
server_does_not_want_to_reuse_session(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server =
diff --git a/lib/ssl/test/ssl_cipher_suite_SUITE.erl b/lib/ssl/test/ssl_cipher_suite_SUITE.erl
index 3a23293e26..8805df7b52 100644
--- a/lib/ssl/test/ssl_cipher_suite_SUITE.erl
+++ b/lib/ssl/test/ssl_cipher_suite_SUITE.erl
@@ -85,11 +85,7 @@ groups() ->
{rsa_psk, [], [rsa_psk_3des_ede_cbc,
rsa_psk_rc4_128,
rsa_psk_aes_128_cbc,
- %% rsa_psk_aes_128_ccm,
- %% rsa_psk_aes_128_ccm_8,
rsa_psk_aes_256_cbc
- %% rsa_psk_aes_256_ccm,
- %% rsa_psk_aes_256_ccm_8
]},
{dh_anon, [], [dh_anon_rc4_128,
dh_anon_3des_ede_cbc,
@@ -101,26 +97,33 @@ groups() ->
ecdh_anon_aes_128_cbc,
ecdh_anon_aes_256_cbc
]},
- {srp, [], [srp_3des_ede_cbc,
- srp_aes_128_cbc,
- srp_aes_256_cbc]},
+ {srp_anon, [], [srp_anon_3des_ede_cbc,
+ srp_anon_aes_128_cbc,
+ srp_anon_aes_256_cbc]},
{psk, [], [psk_3des_ede_cbc,
psk_rc4_128,
psk_aes_128_cbc,
- %% psk_aes_128_ccm,
- %% psk_aes_128_ccm_8,
- psk_aes_256_cbc
- %% psk_aes_256_ccm,
- %% psk_aes_256_ccm_8
+ psk_aes_128_ccm,
+ psk_aes_128_ccm_8,
+ psk_aes_256_cbc,
+ psk_aes_256_ccm,
+ psk_aes_256_ccm_8
]},
{dhe_psk, [], [dhe_psk_3des_ede_cbc,
dhe_psk_rc4_128,
dhe_psk_aes_128_cbc,
- %% dhe_psk_aes_128_ccm,
- %% dhe_psk_aes_128_ccm_8,
- dhe_psk_aes_256_cbc
- %% dhe_psk_aes_256_ccm,
- %% dhe_psk_aes_256_ccm_8
+ dhe_psk_aes_128_ccm,
+ dhe_psk_aes_128_ccm_8,
+ dhe_psk_aes_256_cbc,
+ dhe_psk_aes_256_ccm,
+ dhe_psk_aes_256_ccm_8
+ ]},
+ {ecdhe_psk, [], [ecdhe_psk_3des_ede_cbc,
+ ecdhe_psk_rc4_128,
+ ecdhe_psk_aes_128_cbc,
+ ecdhe_psk_aes_128_ccm,
+ ecdhe_psk_aes_128_ccm_8,
+ ecdhe_psk_aes_256_cbc
]}
].
@@ -148,7 +151,8 @@ anonymous() ->
{group, ecdh_anon},
{group, psk},
{group, dhe_psk},
- {group, srp}
+ {group, ecdhe_psk},
+ {group, srp_anon}
].
@@ -169,8 +173,16 @@ end_per_suite(_Config) ->
%%--------------------------------------------------------------------
init_per_group(GroupName, Config) when GroupName == ecdh_anon;
GroupName == ecdhe_rsa;
- GroupName == ecdhe_ecdsa ->
- case ssl_test_lib:sufficient_crypto_support(ec_cipher) of
+ GroupName == ecdhe_psk ->
+ case proplists:get_bool(ecdh, proplists:get_value(public_keys, crypto:supports())) of
+ true ->
+ init_certs(GroupName, Config);
+ false ->
+ {skip, "Missing EC crypto support"}
+ end;
+init_per_group(ecdhe_ecdsa = GroupName, Config) ->
+ PKAlg = proplists:get_value(public_keys, crypto:supports()),
+ case lists:member(ecdh, PKAlg) andalso lists:member(ecdsa, PKAlg) of
true ->
init_certs(GroupName, Config);
false ->
@@ -192,7 +204,7 @@ init_per_group(srp_dss = GroupName, Config) ->
false ->
{skip, "Missing DSS_SRP crypto support"}
end;
-init_per_group(GroupName, Config) when GroupName == srp;
+init_per_group(GroupName, Config) when GroupName == srp_anon;
GroupName == srp_rsa ->
PKAlg = proplists:get_value(public_keys, crypto:supports()),
case lists:member(srp, PKAlg) of
@@ -225,15 +237,17 @@ end_per_group(GroupName, Config) ->
Config
end.
init_per_testcase(TestCase, Config) when TestCase == psk_3des_ede_cbc;
- TestCase == srp_3des_ede_cbc;
+ TestCase == srp_anon_3des_ede_cbc;
TestCase == dhe_psk_3des_ede_cbc;
+ TestCase == ecdhe_psk_3des_ede_cbc;
TestCase == srp_rsa_3des_ede_cbc;
+ TestCase == srp_dss_3des_ede_cbc;
TestCase == rsa_psk_3des_ede_cbc;
TestCase == rsa_3des_ede_cbc;
TestCase == dhe_rsa_3des_ede_cbc;
TestCase == dhe_dss_3des_ede_cbc;
TestCase == ecdhe_rsa_3des_ede_cbc;
- TestCase == srp_dss_3des_ede_cbc;
+ TestCase == srp_anon_dss_3des_ede_cbc;
TestCase == dh_anon_3des_ede_cbc;
TestCase == ecdh_anon_3des_ede_cbc;
TestCase == ecdhe_ecdsa_3des_ede_cbc ->
@@ -246,6 +260,7 @@ init_per_testcase(TestCase, Config) when TestCase == psk_3des_ede_cbc;
{skip, "Missing 3DES crypto support"}
end;
init_per_testcase(TestCase, Config) when TestCase == psk_rc4_128;
+ TestCase == ecdhe_psk_rc4_128;
TestCase == dhe_psk_rc4_128;
TestCase == rsa_psk_rc4_128;
TestCase == rsa_rc4_128;
@@ -260,7 +275,33 @@ init_per_testcase(TestCase, Config) when TestCase == psk_rc4_128;
_ ->
{skip, "Missing RC4 crypto support"}
end;
-init_per_testcase(TestCase, Config) ->
+init_per_testcase(TestCase, Config) when TestCase == psk_aes_128_ccm_8;
+ TestCase == rsa_psk_aes_128_ccm_8;
+ TestCase == psk_aes_128_ccm_8;
+ TestCase == dhe_psk_aes_128_ccm_8;
+ TestCase == ecdhe_psk_aes_128_ccm_8 ->
+ SupCiphers = proplists:get_value(ciphers, crypto:supports()),
+ case lists:member(aes_128_ccm, SupCiphers) of
+ true ->
+ ct:timetrap({seconds, 5}),
+ Config;
+ _ ->
+ {skip, "Missing AES_128_CCM crypto support"}
+ end;
+init_per_testcase(TestCase, Config) when TestCase == psk_aes_256_ccm_8;
+ TestCase == rsa_psk_aes_256_ccm_8;
+ TestCase == psk_aes_256_ccm_8;
+ TestCase == dhe_psk_aes_256_ccm_8;
+ TestCase == ecdhe_psk_aes_256_ccm_8 ->
+ SupCiphers = proplists:get_value(ciphers, crypto:supports()),
+ case lists:member(aes_256_ccm, SupCiphers) of
+ true ->
+ ct:timetrap({seconds, 5}),
+ Config;
+ _ ->
+ {skip, "Missing AES_256_CCM crypto support"}
+ end;
+init_per_testcase(TestCase, Config) ->
Cipher = test_cipher(TestCase, Config),
%%Reason = io_lib:format("Missing ~p crypto support", [Cipher]),
SupCiphers = proplists:get_value(ciphers, crypto:supports()),
@@ -284,6 +325,10 @@ init_certs(srp_rsa, Config) ->
[{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, undefined}} | ServerOpts],
client_config => [{srp_identity, {"Test-User", "secret"}} | ClientOpts]}} |
proplists:delete(tls_config, Config)];
+init_certs(srp_anon, Config) ->
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, undefined}}],
+ client_config => [{srp_identity, {"Test-User", "secret"}}]}} |
+ proplists:delete(tls_config, Config)];
init_certs(rsa_psk, Config) ->
ClientExt = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]),
{ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
@@ -341,7 +386,8 @@ init_certs(GroupName, Config) when GroupName == dhe_ecdsa;
client_config => ClientOpts}} |
proplists:delete(tls_config, Config)];
init_certs(GroupName, Config) when GroupName == psk;
- GroupName == dhe_psk ->
+ GroupName == dhe_psk;
+ GroupName == ecdhe_psk ->
PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
[{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}],
client_config => [{psk_identity, "Test-User"},
@@ -549,14 +595,14 @@ ecdh_anon_aes_128_cbc(Config) when is_list(Config) ->
ecdh_anon_aes_256_cbc(Config) when is_list(Config) ->
run_ciphers_test(ecdh_anon, 'aes_256_cbc', Config).
-srp_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(srp, '3des_ede_cbc', Config).
+srp_anon_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_anon, '3des_ede_cbc', Config).
-srp_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(srp, 'aes_128_cbc', Config).
+srp_anon_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_anon, 'aes_128_cbc', Config).
-srp_aes_256_cbc(Config) when is_list(Config) ->
- run_ciphers_test(srp, 'aes_256_cbc', Config).
+srp_anon_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_anon, 'aes_256_cbc', Config).
dhe_psk_des_cbc(Config) when is_list(Config) ->
run_ciphers_test(dhe_psk, 'des_cbc', Config).
@@ -591,6 +637,33 @@ dhe_psk_aes_128_ccm_8(Config) when is_list(Config) ->
dhe_psk_aes_256_ccm_8(Config) when is_list(Config) ->
run_ciphers_test(dhe_psk, 'aes_256_ccm_8', Config).
+ecdhe_psk_des_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'des_cbc', Config).
+
+ecdhe_psk_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'rc4_128', Config).
+
+ecdhe_psk_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, '3des_ede_cbc', Config).
+
+ecdhe_psk_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_128_cbc', Config).
+
+ecdhe_psk_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_256_cbc', Config).
+
+ecdhe_psk_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_128_gcm', Config).
+
+ecdhe_psk_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_256_gcm', Config).
+
+ecdhe_psk_aes_128_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_128_ccm', Config).
+
+ecdhe_psk_aes_128_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_128_ccm_8', Config).
+
psk_des_cbc(Config) when is_list(Config) ->
run_ciphers_test(psk, 'des_cbc', Config).
@@ -676,7 +749,7 @@ cipher_suite_test(CipherSuite, Version, Config) ->
ssl_test_lib:close(Client).
erlang_cipher_suite(Suite) when is_list(Suite)->
- ssl_cipher_format:suite_definition(ssl_cipher_format:openssl_suite(Suite));
+ ssl_cipher_format:suite_definition(ssl_cipher_format:suite_openssl_str_to_map(Suite));
erlang_cipher_suite(Suite) ->
Suite.
diff --git a/lib/ssl/test/ssl_dist_bench_SUITE.erl b/lib/ssl/test/ssl_dist_bench_SUITE.erl
index 7e7de5c9bf..1fea6f6f72 100644
--- a/lib/ssl/test/ssl_dist_bench_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_bench_SUITE.erl
@@ -49,10 +49,14 @@
suite() -> [{ct_hooks, [{ts_install_cth, [{nodenames, 2}]}]}].
-all() -> [{group, ssl}, {group, plain}].
+all() ->
+ [{group, ssl},
+ {group, crypto},
+ {group, plain}].
groups() ->
[{ssl, all_groups()},
+ {crypto, all_groups()},
{plain, all_groups()},
%%
{setup, [{repeat, 1}], [setup]},
@@ -164,6 +168,17 @@ end_per_suite(Config) ->
init_per_group(ssl, Config) ->
[{ssl_dist, true}, {ssl_dist_prefix, "SSL"}|Config];
+init_per_group(crypto, Config) ->
+ case inet_crypto_dist:is_supported() of
+ true ->
+ [{ssl_dist, false}, {ssl_dist_prefix, "Crypto"},
+ {ssl_dist_args,
+ "-proto_dist inet_crypto "
+ "-inet_crypto '#{secret => \"123456\"}'"}
+ |Config];
+ false ->
+ {skip, "Not supported on this OTP version"}
+ end;
init_per_group(plain, Config) ->
[{ssl_dist, false}, {ssl_dist_prefix, "Plain"}|Config];
init_per_group(_GroupName, Config) ->
@@ -374,29 +389,46 @@ sched_utilization(A, B, Prefix, HA, HB, SSL) ->
[A] = ssl_apply(HB, erlang, nodes, []),
msacc:print(ClientMsacc),
msacc:print(ServerMsacc),
- ct:pal("Got ~p msgs",[length(Msgs)]),
- report(Prefix++" Sched Utilization Client",
- 10000 * msacc:stats(system_runtime,ClientMsacc) /
- msacc:stats(system_realtime,ClientMsacc), "util 0.01 %"),
- report(Prefix++" Sched Utilization Server",
- 10000 * msacc:stats(system_runtime,ServerMsacc) /
- msacc:stats(system_realtime,ServerMsacc), "util 0.01 %"),
- ok.
+ ct:pal("Got ~p busy_dist_port msgs",[length(Msgs)]),
+ ct:log("Stats of B from A: ~p",
+ [ssl_apply(HA, net_kernel, node_info, [B])]),
+ ct:log("Stats of A from B: ~p",
+ [ssl_apply(HB, net_kernel, node_info, [A])]),
+ SchedUtilClient =
+ round(10000 * msacc:stats(system_runtime,ClientMsacc) /
+ msacc:stats(system_realtime,ClientMsacc)),
+ SchedUtilServer =
+ round(10000 * msacc:stats(system_runtime,ServerMsacc) /
+ msacc:stats(system_realtime,ServerMsacc)),
+ Verdict =
+ case Msgs of
+ [] ->
+ "";
+ _ ->
+ " ???"
+ end,
+ {comment, ClientComment} =
+ report(Prefix ++ " Sched Utilization Client" ++ Verdict,
+ SchedUtilClient, "/100 %" ++ Verdict),
+ {comment, ServerComment} =
+ report(Prefix++" Sched Utilization Server" ++ Verdict,
+ SchedUtilServer, "/100 %" ++ Verdict),
+ {comment, "Client " ++ ClientComment ++ ", Server " ++ ServerComment}.
%% Runs on node A and spawns a server on node B
%% We want to avoid getting busy_dist_port as it hides the true SU usage
%% of the receiver and sender.
sched_util_runner(A, B, true) ->
- sched_util_runner(A, B, 50);
+ sched_util_runner(A, B, 250);
sched_util_runner(A, B, false) ->
sched_util_runner(A, B, 250);
sched_util_runner(A, B, Senders) ->
Payload = payload(5),
[A] = rpc:call(B, erlang, nodes, []),
- ServerPid =
- erlang:spawn(
- B,
- fun () -> throughput_server() end),
+ ServerPids =
+ [erlang:spawn_link(
+ B, fun () -> throughput_server() end)
+ || _ <- lists:seq(1, Senders)],
ServerMsacc =
erlang:spawn(
B,
@@ -404,24 +436,28 @@ sched_util_runner(A, B, Senders) ->
receive
{start,Pid} ->
msacc:start(10000),
- Pid ! {ServerPid,msacc:stats()}
+ receive
+ {done,Pid} ->
+ Pid ! {self(),msacc:stats()}
+ end
end
end),
- spawn_link(
- fun() ->
- %% We spawn 250 senders which should mean that we
- %% have a load of 250 msgs/msec
- [spawn_link(
- fun() ->
- throughput_client(ServerPid,Payload)
- end) || _ <- lists:seq(1, Senders)]
- end),
-
erlang:system_monitor(self(),[busy_dist_port]),
+ %% We spawn 250 senders which should mean that we
+ %% have a load of 250 msgs/msec
+ [spawn_link(
+ fun() ->
+ throughput_client(Pid, Payload)
+ end) || Pid <- ServerPids],
+ %%
+ receive after 1000 -> ok end,
ServerMsacc ! {start,self()},
msacc:start(10000),
ClientMsaccStats = msacc:stats(),
- ServerMsaccStats = receive {ServerPid,Stats} -> Stats end,
+ receive after 1000 -> ok end,
+ ServerMsacc ! {done,self()},
+ ServerMsaccStats = receive {ServerMsacc,Stats} -> Stats end,
+ %%
{ClientMsaccStats,ServerMsaccStats, flush()}.
flush() ->
@@ -522,15 +558,20 @@ throughput(A, B, Prefix, HA, HB, Packets, Size) ->
+ byte_size(erlang:term_to_binary([0|<<>>])), % Benchmark overhead
Bytes = Packets * (Size + Overhead),
io:format("~w bytes, ~.4g s~n", [Bytes,Time/1000000]),
+ SizeString = integer_to_list(Size),
ClientMsaccStats =:= undefined orelse
- io:format(
- "Sender core usage ratio: ~.4g ns/byte~n",
- [msacc:stats(system_runtime, ClientMsaccStats)*1000/Bytes]),
+ report(
+ Prefix ++ " Sender_RelativeCoreLoad_" ++ SizeString,
+ round(msacc:stats(system_runtime, ClientMsaccStats)
+ * 1000000 / Bytes),
+ "ps/byte"),
ServerMsaccStats =:= undefined orelse
begin
- io:format(
- "Receiver core usage ratio: ~.4g ns/byte~n",
- [msacc:stats(system_runtime, ServerMsaccStats)*1000/Bytes]),
+ report(
+ Prefix ++ " Receiver_RelativeCoreLoad_" ++ SizeString,
+ round(msacc:stats(system_runtime, ServerMsaccStats)
+ * 1000000 / Bytes),
+ "ps/byte"),
msacc:print(ServerMsaccStats)
end,
io:format("******* ClientProf:~n", []), prof_print(ClientProf),
@@ -538,7 +579,7 @@ throughput(A, B, Prefix, HA, HB, Packets, Size) ->
io:format("******* Server GC Before:~n~p~n", [Server_GC_Before]),
io:format("******* Server GC After:~n~p~n", [Server_GC_After]),
Speed = round((Bytes * 1000000) / (1024 * Time)),
- report(Prefix++" Throughput_"++integer_to_list(Size), Speed, "kB/s").
+ report(Prefix ++ " Throughput_" ++ SizeString, Speed, "kB/s").
%% Runs on node A and spawns a server on node B
throughput_runner(A, B, Rounds, Size) ->
@@ -546,11 +587,12 @@ throughput_runner(A, B, Rounds, Size) ->
[A] = rpc:call(B, erlang, nodes, []),
ClientPid = self(),
ServerPid =
- erlang:spawn(
+ erlang:spawn_opt(
B,
- fun () -> throughput_server(ClientPid, Rounds) end),
+ fun () -> throughput_server(ClientPid, Rounds) end,
+ [{message_queue_data, off_heap}]),
ServerMon = erlang:monitor(process, ServerPid),
- msacc:available() andalso
+ msacc_available() andalso
begin
msacc:stop(),
msacc:reset(),
@@ -562,7 +604,7 @@ throughput_runner(A, B, Rounds, Size) ->
throughput_client(ServerPid, ServerMon, Payload, Rounds),
prof_stop(),
MsaccStats =
- case msacc:available() of
+ case msacc_available() of
true ->
MStats = msacc:stats(),
msacc:stop(),
@@ -602,7 +644,7 @@ throughput_server(Pid, N) ->
GC_Before = get_server_gc_info(),
%% dbg:tracer(port, dbg:trace_port(file, "throughput_server_gc.log")),
%% dbg:p(TLSDistReceiver, garbage_collection),
- msacc:available() andalso
+ msacc_available() andalso
begin
msacc:stop(),
msacc:reset(),
@@ -615,7 +657,7 @@ throughput_server(Pid, N) ->
throughput_server_loop(_Pid, GC_Before, 0) ->
prof_stop(),
MsaccStats =
- case msacc:available() of
+ case msacc_available() of
true ->
msacc:stop(),
MStats = msacc:stats(),
@@ -632,8 +674,13 @@ throughput_server_loop(_Pid, GC_Before, 0) ->
server_gc_after => get_server_gc_info()});
throughput_server_loop(Pid, GC_Before, N) ->
receive
- {Pid, N, _} ->
- throughput_server_loop(Pid, GC_Before, N-1)
+ Msg ->
+ case Msg of
+ {Pid, N, _} ->
+ throughput_server_loop(Pid, GC_Before, N - 1);
+ Other ->
+ erlang:error({self(),?FUNCTION_NAME,Other})
+ end
end.
get_server_gc_info() ->
@@ -773,7 +820,7 @@ get_node_args(Tag, Config) ->
true ->
proplists:get_value(Tag, Config);
false ->
- ""
+ proplists:get_value(ssl_dist_args, Config, "")
end.
@@ -828,3 +875,6 @@ report(Name, Value, Unit) ->
term_to_string(Term) ->
unicode:characters_to_list(
io_lib:write(Term, [{encoding, unicode}])).
+
+msacc_available() ->
+ msacc:available().
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
index 7f33fe3204..b71b15b028 100644
--- a/lib/ssl/test/ssl_session_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -186,7 +186,7 @@ session_cleanup() ->
session_cleanup(Config) when is_list(Config) ->
process_flag(trap_exit, true),
ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server =
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 22169035f3..798bdf0416 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -51,20 +51,20 @@ node_to_hostip(Node) ->
Address.
start_server(Args) ->
- Result = spawn_link(?MODULE, run_server, [Args]),
+ Node = proplists:get_value(node, Args),
+ Result = spawn_link(Node, ?MODULE, run_server, [Args]),
receive
{listen, up} ->
Result
end.
run_server(Opts) ->
- Node = proplists:get_value(node, Opts),
Port = proplists:get_value(port, Opts),
Options = proplists:get_value(options, Opts),
Pid = proplists:get_value(from, Opts),
Transport = proplists:get_value(transport, Opts, ssl),
ct:log("~p:~p~nssl:listen(~p, ~p)~n", [?MODULE,?LINE, Port, Options]),
- {ok, ListenSocket} = rpc:call(Node, Transport, listen, [Port, Options]),
+ {ok, ListenSocket} = Transport:listen(Port, Options),
Pid ! {listen, up},
send_selected_port(Pid, Port, ListenSocket),
run_server(ListenSocket, Opts).
@@ -90,13 +90,12 @@ do_run_server(_, ok = Result, Opts) ->
Pid = proplists:get_value(from, Opts),
Pid ! {self(), Result};
do_run_server(ListenSocket, AcceptSocket, Opts) ->
- Node = proplists:get_value(node, Opts),
Pid = proplists:get_value(from, Opts),
Transport = proplists:get_value(transport, Opts, ssl),
{Module, Function, Args} = proplists:get_value(mfa, Opts),
ct:log("~p:~p~nServer: apply(~p,~p,~p)~n",
[?MODULE,?LINE, Module, Function, [AcceptSocket | Args]]),
- case rpc:call(Node, Module, Function, [AcceptSocket | Args]) of
+ case apply(Module, Function, [AcceptSocket | Args]) of
no_result_msg ->
ok;
Msg ->
@@ -110,8 +109,8 @@ do_run_server(ListenSocket, AcceptSocket, Opts) ->
run_server(ListenSocket, [MFA | proplists:delete(mfa, Opts)]);
close ->
ct:log("~p:~p~nServer closing ~p ~n", [?MODULE,?LINE, self()]),
- Result = rpc:call(Node, Transport, close, [AcceptSocket], 500),
- Result1 = rpc:call(Node, Transport, close, [ListenSocket], 500),
+ Result = Transport:close(AcceptSocket),
+ Result1 = Transport:close(ListenSocket),
ct:log("~p:~p~nResult ~p : ~p ~n", [?MODULE,?LINE, Result, Result1]);
{ssl_closed, _} ->
ok
@@ -132,41 +131,37 @@ connect(#sslsocket{} = ListenSocket, Opts) ->
remove_close_msg(ReconnectTimes),
AcceptSocket
end;
-connect(ListenSocket, Opts) ->
- Node = proplists:get_value(node, Opts),
+connect(ListenSocket, _Opts) ->
ct:log("~p:~p~ngen_tcp:accept(~p)~n", [?MODULE,?LINE, ListenSocket]),
- {ok, AcceptSocket} = rpc:call(Node, gen_tcp, accept,
- [ListenSocket]),
+ {ok, AcceptSocket} = gen_tcp:accept(ListenSocket),
AcceptSocket.
connect(_, _, 0, AcceptSocket, _, _, _) ->
AcceptSocket;
connect(ListenSocket, Node, _N, _, Timeout, SslOpts, cancel) ->
ct:log("ssl:transport_accept(~p)~n", [ListenSocket]),
- {ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept,
- [ListenSocket]),
+ {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
ct:log("~p:~p~nssl:handshake(~p,~p,~p)~n", [?MODULE,?LINE, AcceptSocket, SslOpts,Timeout]),
- case rpc:call(Node, ssl, handshake, [AcceptSocket, SslOpts, Timeout]) of
+ case ssl:handshake(AcceptSocket, SslOpts, Timeout) of
{ok, Socket0, Ext} ->
ct:log("Ext ~p:~n", [Ext]),
ct:log("~p:~p~nssl:handshake_cancel(~p)~n", [?MODULE,?LINE, Socket0]),
- rpc:call(Node, ssl, handshake_cancel, [Socket0]);
+ ssl:handshake_cancel(Socket0);
Result ->
ct:log("~p:~p~nssl:handshake@~p ret ~p",[?MODULE,?LINE, Node,Result]),
Result
end;
connect(ListenSocket, Node, N, _, Timeout, SslOpts, [_|_] =ContOpts) ->
ct:log("ssl:transport_accept(~p)~n", [ListenSocket]),
- {ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept,
- [ListenSocket]),
+ {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
ct:log("~p:~p~nssl:handshake(~p,~p,~p)~n", [?MODULE,?LINE, AcceptSocket, SslOpts,Timeout]),
- case rpc:call(Node, ssl, handshake, [AcceptSocket, SslOpts, Timeout]) of
+ case ssl:handshake(AcceptSocket, SslOpts, Timeout) of
{ok, Socket0, Ext} ->
ct:log("Ext ~p:~n", [Ext]),
ct:log("~p:~p~nssl:handshake_continue(~p,~p,~p)~n", [?MODULE,?LINE, Socket0, ContOpts,Timeout]),
- case rpc:call(Node, ssl, handshake_continue, [Socket0, ContOpts, Timeout]) of
+ case ssl:handshake_continue(Socket0, ContOpts, Timeout) of
{ok, Socket} ->
connect(ListenSocket, Node, N-1, Socket, Timeout, SslOpts, ContOpts);
Error ->
@@ -179,35 +174,35 @@ connect(ListenSocket, Node, N, _, Timeout, SslOpts, [_|_] =ContOpts) ->
end;
connect(ListenSocket, Node, N, _, Timeout, [], ContOpts) ->
ct:log("ssl:transport_accept(~p)~n", [ListenSocket]),
- {ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept,
- [ListenSocket]),
+ {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
ct:log("~p:~p~nssl:ssl_accept(~p, ~p)~n", [?MODULE,?LINE, AcceptSocket, Timeout]),
- case rpc:call(Node, ssl, ssl_accept, [AcceptSocket, Timeout]) of
- ok ->
- connect(ListenSocket, Node, N-1, AcceptSocket, Timeout, [], ContOpts);
+ case ssl:handshake(AcceptSocket, Timeout) of
+ {ok, Socket} ->
+ connect(ListenSocket, Node, N-1, Socket, Timeout, [], ContOpts);
Result ->
- ct:log("~p:~p~nssl:ssl_accept@~p ret ~p",[?MODULE,?LINE, Node,Result]),
+ ct:log("~p:~p~nssl:handshake@~p ret ~p",[?MODULE,?LINE, Node,Result]),
Result
end;
-connect(ListenSocket, Node, _, _, Timeout, Opts, _) ->
+connect(ListenSocket, _Node, _, _, Timeout, Opts, _) ->
ct:log("ssl:transport_accept(~p)~n", [ListenSocket]),
- {ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept,
- [ListenSocket]),
- ct:log("ssl:ssl_accept(~p,~p, ~p)~n", [AcceptSocket, Opts, Timeout]),
- rpc:call(Node, ssl, ssl_accept, [AcceptSocket, Opts, Timeout]),
+ {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
+ ct:log("ssl:handshake(~p,~p, ~p)~n", [AcceptSocket, Opts, Timeout]),
+ ssl:handshake(AcceptSocket, Opts, Timeout),
AcceptSocket.
start_server_transport_abuse_socket(Args) ->
- Result = spawn_link(?MODULE, transport_accept_abuse, [Args]),
+ Node = proplists:get_value(node, Args),
+ Result = spawn_link(Node, ?MODULE, transport_accept_abuse, [Args]),
receive
{listen, up} ->
Result
end.
start_server_transport_control(Args) ->
- Result = spawn_link(?MODULE, transport_switch_control, [Args]),
+ Node = proplists:get_value(node, Args),
+ Result = spawn_link(Node, ?MODULE, transport_switch_control, [Args]),
receive
{listen, up} ->
Result
@@ -215,35 +210,31 @@ start_server_transport_control(Args) ->
transport_accept_abuse(Opts) ->
- Node = proplists:get_value(node, Opts),
Port = proplists:get_value(port, Opts),
Options = proplists:get_value(options, Opts),
Pid = proplists:get_value(from, Opts),
Transport = proplists:get_value(transport, Opts, ssl),
ct:log("~p:~p~nssl:listen(~p, ~p)~n", [?MODULE,?LINE, Port, Options]),
- {ok, ListenSocket} = rpc:call(Node, Transport, listen, [Port, Options]),
+ {ok, ListenSocket} = Transport:listen(Port, Options),
Pid ! {listen, up},
send_selected_port(Pid, Port, ListenSocket),
- {ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept,
- [ListenSocket]),
- {error, _} = rpc:call(Node, ssl, connection_information, [AcceptSocket]),
- _ = rpc:call(Node, ssl, handshake, [AcceptSocket, infinity]),
+ {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
+ {error, _} = ssl:connection_information(AcceptSocket),
+ _ = ssl:handshake(AcceptSocket, infinity),
Pid ! {self(), ok}.
transport_switch_control(Opts) ->
- Node = proplists:get_value(node, Opts),
Port = proplists:get_value(port, Opts),
Options = proplists:get_value(options, Opts),
Pid = proplists:get_value(from, Opts),
Transport = proplists:get_value(transport, Opts, ssl),
ct:log("~p:~p~nssl:listen(~p, ~p)~n", [?MODULE,?LINE, Port, Options]),
- {ok, ListenSocket} = rpc:call(Node, Transport, listen, [Port, Options]),
+ {ok, ListenSocket} = Transport:listen(Port, Options),
Pid ! {listen, up},
send_selected_port(Pid, Port, ListenSocket),
- {ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept,
- [ListenSocket]),
- ok = rpc:call(Node, ssl, controlling_process, [AcceptSocket, self()]),
+ {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
+ ok = ssl:controlling_process(AcceptSocket, self()),
Pid ! {self(), ok}.
@@ -256,7 +247,8 @@ remove_close_msg(ReconnectTimes) ->
end.
start_client(Args) ->
- Result = spawn_link(?MODULE, run_client_init, [lists:delete(return_socket, Args)]),
+ Node = proplists:get_value(node, Args),
+ Result = spawn_link(Node, ?MODULE, run_client_init, [lists:delete(return_socket, Args)]),
receive
{connected, Socket} ->
case lists:member(return_socket, Args) of
@@ -288,8 +280,8 @@ run_client(Opts) ->
client_cont_loop(Node, Host, Port, Pid, Transport, Options, ContOpts, Opts)
end.
-client_loop(Node, Host, Port, Pid, Transport, Options, Opts) ->
- case rpc:call(Node, Transport, connect, [Host, Port, Options]) of
+client_loop(_Node, Host, Port, Pid, Transport, Options, Opts) ->
+ case Transport:connect(Host, Port, Options) of
{ok, Socket} ->
Pid ! {connected, Socket},
ct:log("~p:~p~nClient: connected~n", [?MODULE,?LINE]),
@@ -299,7 +291,7 @@ client_loop(Node, Host, Port, Pid, Transport, Options, Opts) ->
{Module, Function, Args} = proplists:get_value(mfa, Opts),
ct:log("~p:~p~nClient: apply(~p,~p,~p)~n",
[?MODULE,?LINE, Module, Function, [Socket | Args]]),
- case rpc:call(Node, Module, Function, [Socket | Args]) of
+ case apply(Module, Function, [Socket | Args]) of
no_result_msg ->
ok;
Msg ->
@@ -309,7 +301,7 @@ client_loop(Node, Host, Port, Pid, Transport, Options, Opts) ->
receive
close ->
ct:log("~p:~p~nClient closing~n", [?MODULE,?LINE]),
- rpc:call(Node, Transport, close, [Socket]);
+ Transport:close(Socket);
{ssl_closed, Socket} ->
ok;
{gen_tcp, closed} ->
@@ -339,16 +331,13 @@ client_loop(Node, Host, Port, Pid, Transport, Options, Opts) ->
end;
{error, Reason} ->
ct:log("~p:~p~nClient: connection failed: ~p ~n", [?MODULE,?LINE, Reason]),
- Pid ! {connect_failed, Reason};
- {badrpc,BadRPC} ->
- ct:log("~p:~p~nBad rpc: ~p",[?MODULE,?LINE, BadRPC]),
- Pid ! {connect_failed, {badrpc,BadRPC}}
+ Pid ! {connect_failed, Reason}
end.
-client_cont_loop(Node, Host, Port, Pid, Transport, Options, cancel, _Opts) ->
- case rpc:call(Node, Transport, connect, [Host, Port, Options]) of
+client_cont_loop(_Node, Host, Port, Pid, Transport, Options, cancel, _Opts) ->
+ case Transport:connect(Host, Port, Options) of
{ok, Socket, _} ->
- Result = rpc:call(Node, Transport, handshake_cancel, [Socket]),
+ Result = Transport:handshake_cancel(Socket),
ct:log("~p:~p~nClient: Cancel: ~p ~n", [?MODULE,?LINE, Result]),
Pid ! {connect_failed, Result};
{error, Reason} ->
@@ -356,17 +345,17 @@ client_cont_loop(Node, Host, Port, Pid, Transport, Options, cancel, _Opts) ->
Pid ! {connect_failed, Reason}
end;
-client_cont_loop(Node, Host, Port, Pid, Transport, Options, ContOpts, Opts) ->
- case rpc:call(Node, Transport, connect, [Host, Port, Options]) of
+client_cont_loop(_Node, Host, Port, Pid, Transport, Options, ContOpts, Opts) ->
+ case Transport:connect(Host, Port, Options) of
{ok, Socket0, _} ->
ct:log("~p:~p~nClient: handshake_continue(~p, ~p, infinity) ~n", [?MODULE, ?LINE, Socket0, ContOpts]),
- case rpc:call(Node, Transport, handshake_continue, [Socket0, ContOpts]) of
+ case Transport:handshake_continue(Socket0, ContOpts) of
{ok, Socket} ->
Pid ! {connected, Socket},
{Module, Function, Args} = proplists:get_value(mfa, Opts),
ct:log("~p:~p~nClient: apply(~p,~p,~p)~n",
[?MODULE,?LINE, Module, Function, [Socket | Args]]),
- case rpc:call(Node, Module, Function, [Socket | Args]) of
+ case apply(Module, Function, [Socket | Args]) of
no_result_msg ->
ok;
Msg ->
@@ -896,14 +885,14 @@ make_ecdh_rsa_cert(Config) ->
end.
start_upgrade_server(Args) ->
- Result = spawn_link(?MODULE, run_upgrade_server, [Args]),
+ Node = proplists:get_value(node, Args),
+ Result = spawn_link(Node, ?MODULE, run_upgrade_server, [Args]),
receive
{listen, up} ->
Result
end.
run_upgrade_server(Opts) ->
- Node = proplists:get_value(node, Opts),
Port = proplists:get_value(port, Opts),
TimeOut = proplists:get_value(timeout, Opts, infinity),
TcpOptions = proplists:get_value(tcp_options, Opts),
@@ -911,43 +900,41 @@ run_upgrade_server(Opts) ->
Pid = proplists:get_value(from, Opts),
ct:log("~p:~p~ngen_tcp:listen(~p, ~p)~n", [?MODULE,?LINE, Port, TcpOptions]),
- {ok, ListenSocket} = rpc:call(Node, gen_tcp, listen, [Port, TcpOptions]),
+ {ok, ListenSocket} = gen_tcp:listen(Port, TcpOptions),
Pid ! {listen, up},
send_selected_port(Pid, Port, ListenSocket),
ct:log("~p:~p~ngen_tcp:accept(~p)~n", [?MODULE,?LINE, ListenSocket]),
- {ok, AcceptSocket} = rpc:call(Node, gen_tcp, accept, [ListenSocket]),
+ {ok, AcceptSocket} = gen_tcp:accept(ListenSocket),
try
{ok, SslAcceptSocket} = case TimeOut of
infinity ->
- ct:log("~p:~p~nssl:ssl_accept(~p, ~p)~n",
+ ct:log("~p:~p~nssl:handshake(~p, ~p)~n",
[?MODULE,?LINE, AcceptSocket, SslOptions]),
- rpc:call(Node, ssl, ssl_accept,
- [AcceptSocket, SslOptions]);
+ ssl:handshake(AcceptSocket, SslOptions);
_ ->
- ct:log("~p:~p~nssl:ssl_accept(~p, ~p, ~p)~n",
+ ct:log("~p:~p~nssl:handshake(~p, ~p, ~p)~n",
[?MODULE,?LINE, AcceptSocket, SslOptions, TimeOut]),
- rpc:call(Node, ssl, ssl_accept,
- [AcceptSocket, SslOptions, TimeOut])
+ ssl:handshake(AcceptSocket, SslOptions, TimeOut)
end,
{Module, Function, Args} = proplists:get_value(mfa, Opts),
- Msg = rpc:call(Node, Module, Function, [SslAcceptSocket | Args]),
+ Msg = apply(Module, Function, [SslAcceptSocket | Args]),
ct:log("~p:~p~nUpgrade Server Msg: ~p ~n", [?MODULE,?LINE, Msg]),
Pid ! {self(), Msg},
receive
close ->
ct:log("~p:~p~nUpgrade Server closing~n", [?MODULE,?LINE]),
- rpc:call(Node, ssl, close, [SslAcceptSocket])
+ ssl:close(SslAcceptSocket)
end
catch error:{badmatch, Error} ->
Pid ! {self(), Error}
end.
start_upgrade_client(Args) ->
- spawn_link(?MODULE, run_upgrade_client, [Args]).
+ Node = proplists:get_value(node, Args),
+ spawn_link(Node, ?MODULE, run_upgrade_client, [Args]).
run_upgrade_client(Opts) ->
- Node = proplists:get_value(node, Opts),
Host = proplists:get_value(host, Opts),
Port = proplists:get_value(port, Opts),
Pid = proplists:get_value(from, Opts),
@@ -956,34 +943,34 @@ run_upgrade_client(Opts) ->
ct:log("~p:~p~ngen_tcp:connect(~p, ~p, ~p)~n",
[?MODULE,?LINE, Host, Port, TcpOptions]),
- {ok, Socket} = rpc:call(Node, gen_tcp, connect, [Host, Port, TcpOptions]),
+ {ok, Socket} = gen_tcp:connect(Host, Port, TcpOptions),
send_selected_port(Pid, Port, Socket),
ct:log("~p:~p~nssl:connect(~p, ~p)~n", [?MODULE,?LINE, Socket, SslOptions]),
- {ok, SslSocket} = rpc:call(Node, ssl, connect, [Socket, SslOptions]),
+ {ok, SslSocket} = ssl:connect(Socket, SslOptions),
{Module, Function, Args} = proplists:get_value(mfa, Opts),
ct:log("~p:~p~napply(~p, ~p, ~p)~n",
[?MODULE,?LINE, Module, Function, [SslSocket | Args]]),
- Msg = rpc:call(Node, Module, Function, [SslSocket | Args]),
+ Msg = apply(Module, Function, [SslSocket | Args]),
ct:log("~p:~p~nUpgrade Client Msg: ~p ~n", [?MODULE,?LINE, Msg]),
Pid ! {self(), Msg},
receive
close ->
ct:log("~p:~p~nUpgrade Client closing~n", [?MODULE,?LINE]),
- rpc:call(Node, ssl, close, [SslSocket])
+ ssl:close(SslSocket)
end.
start_upgrade_server_error(Args) ->
- Result = spawn_link(?MODULE, run_upgrade_server_error, [Args]),
+ Node = proplists:get_value(node, Args),
+ Result = spawn_link(Node,?MODULE, run_upgrade_server_error, [Args]),
receive
{listen, up} ->
Result
end.
run_upgrade_server_error(Opts) ->
- Node = proplists:get_value(node, Opts),
Port = proplists:get_value(port, Opts),
TimeOut = proplists:get_value(timeout, Opts, infinity),
TcpOptions = proplists:get_value(tcp_options, Opts),
@@ -991,22 +978,20 @@ run_upgrade_server_error(Opts) ->
Pid = proplists:get_value(from, Opts),
ct:log("~p:~p~ngen_tcp:listen(~p, ~p)~n", [?MODULE,?LINE, Port, TcpOptions]),
- {ok, ListenSocket} = rpc:call(Node, gen_tcp, listen, [Port, TcpOptions]),
+ {ok, ListenSocket} = gen_tcp:listen(Port, TcpOptions),
Pid ! {listen, up},
send_selected_port(Pid, Port, ListenSocket),
ct:log("~p:~p~ngen_tcp:accept(~p)~n", [?MODULE,?LINE, ListenSocket]),
- {ok, AcceptSocket} = rpc:call(Node, gen_tcp, accept, [ListenSocket]),
+ {ok, AcceptSocket} = gen_tcp:accept(ListenSocket),
Error = case TimeOut of
infinity ->
- ct:log("~p:~p~nssl:ssl_accept(~p, ~p)~n",
+ ct:log("~p:~p~nssl:handshake(~p, ~p)~n",
[?MODULE,?LINE, AcceptSocket, SslOptions]),
- rpc:call(Node, ssl, ssl_accept,
- [AcceptSocket, SslOptions]);
+ ssl:handshake(AcceptSocket, SslOptions);
_ ->
- ct:log("~p:~p~nssl:ssl_accept(~p, ~p, ~p)~n",
+ ct:log("~p:~p~nssl:ssl_handshake(~p, ~p, ~p)~n",
[?MODULE,?LINE, AcceptSocket, SslOptions, TimeOut]),
- rpc:call(Node, ssl, ssl_accept,
- [AcceptSocket, SslOptions, TimeOut])
+ ssl:handshake(AcceptSocket, SslOptions, TimeOut)
end,
Pid ! {self(), Error}.
@@ -1018,32 +1003,31 @@ start_server_error(Args) ->
end.
run_server_error(Opts) ->
- Node = proplists:get_value(node, Opts),
Port = proplists:get_value(port, Opts),
Options = proplists:get_value(options, Opts),
Pid = proplists:get_value(from, Opts),
Transport = proplists:get_value(transport, Opts, ssl),
ct:log("~p:~p~nssl:listen(~p, ~p)~n", [?MODULE,?LINE, Port, Options]),
- case rpc:call(Node, Transport, listen, [Port, Options]) of
+ case Transport:listen(Port, Options) of
{ok, #sslsocket{} = ListenSocket} ->
%% To make sure error_client will
%% get {error, closed} and not {error, connection_refused}
Pid ! {listen, up},
send_selected_port(Pid, Port, ListenSocket),
ct:log("~p:~p~nssl:transport_accept(~p)~n", [?MODULE,?LINE, ListenSocket]),
- case rpc:call(Node, Transport, transport_accept, [ListenSocket]) of
+ case Transport:transport_accept(ListenSocket) of
{error, _} = Error ->
Pid ! {self(), Error};
{ok, AcceptSocket} ->
ct:log("~p:~p~nssl:ssl_accept(~p)~n", [?MODULE,?LINE, AcceptSocket]),
- Error = rpc:call(Node, ssl, ssl_accept, [AcceptSocket]),
+ Error = ssl:handshake(AcceptSocket),
Pid ! {self(), Error}
end;
{ok, ListenSocket} ->
Pid ! {listen, up},
send_selected_port(Pid, Port, ListenSocket),
ct:log("~p:~p~n~p:accept(~p)~n", [?MODULE,?LINE, Transport, ListenSocket]),
- case rpc:call(Node, Transport, accept, [ListenSocket]) of
+ case Transport:accept(ListenSocket) of
{error, _} = Error ->
Pid ! {self(), Error}
end;
@@ -1055,17 +1039,17 @@ run_server_error(Opts) ->
end.
start_client_error(Args) ->
- spawn_link(?MODULE, run_client_error, [Args]).
+ Node = proplists:get_value(node, Args),
+ spawn_link(Node, ?MODULE, run_client_error, [Args]).
run_client_error(Opts) ->
- Node = proplists:get_value(node, Opts),
Host = proplists:get_value(host, Opts),
Port = proplists:get_value(port, Opts),
Pid = proplists:get_value(from, Opts),
Transport = proplists:get_value(transport, Opts, ssl),
Options = proplists:get_value(options, Opts),
ct:log("~p:~p~nssl:connect(~p, ~p, ~p)~n", [?MODULE,?LINE, Host, Port, Options]),
- Error = rpc:call(Node, Transport, connect, [Host, Port, Options]),
+ Error = Transport:connect(Host, Port, Options),
Pid ! {self(), Error}.
accepters(N) ->
@@ -1357,13 +1341,13 @@ common_ciphers(crypto) ->
common_ciphers(openssl) ->
OpenSslSuites =
string:tokens(string:strip(os:cmd("openssl ciphers"), right, $\n), ":"),
- [ssl_cipher_format:suite_definition(S)
+ [ssl_cipher_format:suite_bin_to_map(S)
|| S <- ssl_cipher:suites(tls_record:highest_protocol_version([])),
- lists:member(ssl_cipher_format:openssl_suite_name(S), OpenSslSuites)
+ lists:member(ssl_cipher_format:suite_map_to_openssl_str(ssl_cipher_format:suite_bin_to_map(S)), OpenSslSuites)
].
available_suites(Version) ->
- [ssl_cipher_format:suite_definition(Suite) ||
+ [ssl_cipher_format:suite_bin_to_map(Suite) ||
Suite <- ssl_cipher:filter_suites(ssl_cipher:suites(Version))].
@@ -1436,7 +1420,7 @@ string_regex_filter(_Str, _Search) ->
false.
ecdh_dh_anonymous_suites(Version) ->
- ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:anonymous_suites(Version)],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_bin_to_map(S) || S <- ssl_cipher:anonymous_suites(Version)],
[{key_exchange,
fun(dh_anon) ->
true;
@@ -1446,7 +1430,7 @@ ecdh_dh_anonymous_suites(Version) ->
false
end}]).
psk_suites({3,_} = Version) ->
- ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:psk_suites(Version)], []);
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_bin_to_map(S) || S <- ssl_cipher:psk_suites(Version)], []);
psk_suites(Version) ->
ssl:filter_cipher_suites(psk_suites(dtls_v1:corresponding_tls_version(Version)),
[{cipher,
@@ -1457,7 +1441,7 @@ psk_suites(Version) ->
end}]).
psk_anon_suites({3,_} = Version) ->
- ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:psk_suites_anon(Version)],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_bin_to_map(S) || S <- ssl_cipher:psk_suites_anon(Version)],
[{key_exchange,
fun(psk) ->
true;
@@ -1480,7 +1464,7 @@ psk_anon_suites(Version) ->
srp_suites() ->
- ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:srp_suites()],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_bin_to_map(S) || S <- ssl_cipher:srp_suites()],
[{key_exchange,
fun(srp_rsa) ->
true;
@@ -1488,10 +1472,10 @@ srp_suites() ->
false
end}]).
srp_anon_suites() ->
- ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:srp_suites_anon()],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_bin_to_map(S) || S <- ssl_cipher:srp_suites_anon()],
[]).
srp_dss_suites() ->
- ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:srp_suites()],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_bin_to_map(S) || S <- ssl_cipher:srp_suites()],
[{key_exchange,
fun(srp_dss) ->
true;
@@ -1499,14 +1483,14 @@ srp_dss_suites() ->
false
end}]).
chacha_suites(Version) ->
- [ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:filter_suites(ssl_cipher:chacha_suites(Version))].
+ [ssl_cipher_format:suite_bin_to_map(S) || S <- ssl_cipher:filter_suites(ssl_cipher:chacha_suites(Version))].
rc4_suites(Version) ->
- ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <-ssl_cipher:rc4_suites(Version)], []).
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_bin_to_map(S) || S <-ssl_cipher:rc4_suites(Version)], []).
des_suites(Version) ->
- ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <-ssl_cipher:des_suites(Version)], []).
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_bin_to_map(S) || S <-ssl_cipher:des_suites(Version)], []).
tuple_to_map({Kex, Cipher, Mac}) ->
#{key_exchange => Kex,
@@ -1772,6 +1756,15 @@ is_sane_ecc(crypto) ->
is_sane_ecc(_) ->
sufficient_crypto_support(cipher_ec).
+is_sane_oppenssl_client() ->
+ [{_,_, Bin}] = crypto:info_lib(),
+ case binary_to_list(Bin) of
+ "OpenSSL 0.9" ++ _ ->
+ false;
+ _ ->
+ true
+ end.
+
is_fips(openssl) ->
VersionStr = os:cmd("openssl version"),
case re:split(VersionStr, "fips") of
@@ -1948,10 +1941,10 @@ version_flag('dtlsv1') ->
"-dtls1".
filter_suites([Cipher | _] = Ciphers, AtomVersion) when is_list(Cipher)->
- filter_suites([ssl_cipher_format:openssl_suite(S) || S <- Ciphers],
+ filter_suites([ssl_cipher_format:suite_openssl_str_to_map(S) || S <- Ciphers],
AtomVersion);
filter_suites([Cipher | _] = Ciphers, AtomVersion) when is_binary(Cipher)->
- filter_suites([ssl_cipher_format:suite_definition(S) || S <- Ciphers],
+ filter_suites([ssl_cipher_format:suite_bin_to_map(S) || S <- Ciphers],
AtomVersion);
filter_suites(Ciphers0, AtomVersion) ->
Version = tls_version(AtomVersion),
@@ -1963,7 +1956,7 @@ filter_suites(Ciphers0, AtomVersion) ->
++ ssl_cipher:srp_suites_anon()
++ ssl_cipher:rc4_suites(Version),
Supported1 = ssl_cipher:filter_suites(Supported0),
- Supported2 = [ssl_cipher_format:suite_definition(S) || S <- Supported1],
+ Supported2 = [ssl_cipher_format:suite_bin_to_map(S) || S <- Supported1],
[Cipher || Cipher <- Ciphers0, lists:member(Cipher, Supported2)].
-define(OPENSSL_QUIT, "Q\n").
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index f22eb4ecdf..07abddbcf7 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -181,16 +181,6 @@ end_per_suite(_Config) ->
ssl:stop(),
application:stop(crypto).
-init_per_group(basic, Config0) ->
- case ssl_test_lib:supports_ssl_tls_version('tlsv1.2')
- orelse ssl_test_lib:supports_ssl_tls_version('tlsv1.1')
- orelse ssl_test_lib:supports_ssl_tls_version('tlsv1')
- of
- true ->
- ssl_test_lib:clean_tls_version(Config0);
- false ->
- {skip, "only sslv3 supported by OpenSSL"}
- end;
init_per_group(GroupName, Config) ->
case ssl_test_lib:is_tls_version(GroupName) of
@@ -233,7 +223,7 @@ init_per_testcase(TestCase, Config) when
TestCase == erlang_server_openssl_client_dsa_cert;
TestCase == erlang_client_openssl_server_dsa_cert;
TestCase == erlang_server_openssl_client_dsa_cert ->
- case ssl_test_lib:openssl_dsa_support() of
+ case ssl_test_lib:openssl_dsa_support() andalso ssl_test_lib:is_sane_oppenssl_client() of
true ->
special_init(TestCase, Config);
false ->
@@ -334,7 +324,16 @@ special_init(TestCase, Config0)
]}
]}]} | Config0],
check_openssl_sni_support(Config);
-
+special_init(TestCase, Config)
+ when TestCase == erlang_server_openssl_client;
+ TestCase == erlang_server_openssl_client_client_cert;
+ TestCase == erlang_server_openssl_client_reuse_session ->
+ case ssl_test_lib:is_sane_oppenssl_client() of
+ true ->
+ Config;
+ false ->
+ {skip, "Broken OpenSSL client"}
+ end;
special_init(_, Config) ->
Config.
@@ -1073,7 +1072,7 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) ->
Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {ssl_test_lib, no_result_msg, []}},
+ {mfa, {ssl_test_lib, no_result, []}},
{options,
[{versions, [Version]} | ClientOpts]}]),
@@ -1161,7 +1160,7 @@ ssl2_erlang_server_openssl_client(Config) when is_list(Config) ->
ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
ssl_test_lib:consume_port_exit(OpenSslPort),
- ssl_test_lib:check_server_alert(Server, bad_record_mac),
+ ssl_test_lib:check_server_alert(Server, unexpected_message),
process_flag(trap_exit, false).
%%--------------------------------------------------------------------
@@ -1462,6 +1461,7 @@ send_and_hostname(SSLSocket) ->
end.
erlang_server_openssl_client_sni_test(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
+ Version = ssl_test_lib:protocol_version(Config),
ct:log("Start running handshake, Config: ~p, SNIHostname: ~p, ExpectedSNIHostname: ~p, ExpectedCN: ~p", [Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]),
ServerOptions = proplists:get_value(sni_server_opts, Config) ++ proplists:get_value(server_rsa_opts, Config),
{_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -1472,9 +1472,9 @@ erlang_server_openssl_client_sni_test(Config, SNIHostname, ExpectedSNIHostname,
Exe = "openssl",
ClientArgs = case SNIHostname of
undefined ->
- openssl_client_args(ssl_test_lib:supports_ssl_tls_version(sslv2), Hostname,Port);
+ openssl_client_args(Version, Hostname,Port);
_ ->
- openssl_client_args(ssl_test_lib:supports_ssl_tls_version(sslv2), Hostname, Port, SNIHostname)
+ openssl_client_args(Version, Hostname, Port, SNIHostname)
end,
ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs),
@@ -1485,6 +1485,7 @@ erlang_server_openssl_client_sni_test(Config, SNIHostname, ExpectedSNIHostname,
erlang_server_openssl_client_sni_test_sni_fun(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
+ Version = ssl_test_lib:protocol_version(Config),
ct:log("Start running handshake for sni_fun, Config: ~p, SNIHostname: ~p, ExpectedSNIHostname: ~p, ExpectedCN: ~p", [Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]),
[{sni_hosts, ServerSNIConf}] = proplists:get_value(sni_server_opts, Config),
SNIFun = fun(Domain) -> proplists:get_value(Domain, ServerSNIConf, undefined) end,
@@ -1497,9 +1498,9 @@ erlang_server_openssl_client_sni_test_sni_fun(Config, SNIHostname, ExpectedSNIHo
Exe = "openssl",
ClientArgs = case SNIHostname of
undefined ->
- openssl_client_args(ssl_test_lib:supports_ssl_tls_version(sslv2), Hostname,Port);
+ openssl_client_args(Version, Hostname,Port);
_ ->
- openssl_client_args(ssl_test_lib:supports_ssl_tls_version(sslv2), Hostname, Port, SNIHostname)
+ openssl_client_args(Version, Hostname, Port, SNIHostname)
end,
ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs),
@@ -1910,13 +1911,19 @@ send_wait_send(Socket, [ErlData, OpenSslData]) ->
check_openssl_sni_support(Config) ->
HelpText = os:cmd("openssl s_client --help"),
- case string:str(HelpText, "-servername") of
- 0 ->
- {skip, "Current openssl doesn't support SNI"};
- _ ->
- Config
+ case ssl_test_lib:is_sane_oppenssl_client() of
+ true ->
+ case string:str(HelpText, "-servername") of
+ 0 ->
+ {skip, "Current openssl doesn't support SNI"};
+ _ ->
+ Config
+ end;
+ false ->
+ {skip, "Current openssl doesn't support SNI or extension handling is flawed"}
end.
+
check_openssl_npn_support(Config) ->
HelpText = os:cmd("openssl s_client --help"),
case string:str(HelpText, "nextprotoneg") of
@@ -1982,17 +1989,13 @@ workaround_openssl_s_clinent() ->
[]
end.
-openssl_client_args(false, Hostname, Port) ->
- ["s_client", "-connect", Hostname ++ ":" ++ integer_to_list(Port)];
-openssl_client_args(true, Hostname, Port) ->
- ["s_client", "-no_ssl2", "-connect", Hostname ++ ":" ++ integer_to_list(Port)].
+openssl_client_args(Version, Hostname, Port) ->
+ ["s_client", "-connect", Hostname ++ ":" ++ integer_to_list(Port), ssl_test_lib:version_flag(Version)].
-openssl_client_args(false, Hostname, Port, ServerName) ->
+openssl_client_args(Version, Hostname, Port, ServerName) ->
["s_client", "-connect", Hostname ++ ":" ++
- integer_to_list(Port), "-servername", ServerName];
-openssl_client_args(true, Hostname, Port, ServerName) ->
- ["s_client", "-no_ssl2", "-connect", Hostname ++ ":" ++
- integer_to_list(Port), "-servername", ServerName].
+ integer_to_list(Port), ssl_test_lib:version_flag(Version), "-servername", ServerName].
+
hostname_format(Hostname) ->
case lists:member($., Hostname) of
@@ -2002,22 +2005,12 @@ hostname_format(Hostname) ->
"localhost"
end.
-no_low_flag("-no_ssl2" = Flag) ->
- case ssl_test_lib:supports_ssl_tls_version(sslv2) of
- true ->
- Flag;
- false ->
- ""
- end;
-no_low_flag(Flag) ->
- Flag.
-
openssl_has_common_ciphers(Ciphers) ->
OCiphers = ssl_test_lib:common_ciphers(openssl),
has_common_ciphers(Ciphers, OCiphers).
-has_common_ciphers([], OCiphers) ->
+has_common_ciphers([], _) ->
false;
has_common_ciphers([Cipher | Rest], OCiphers) ->
case lists:member(Cipher, OCiphers) of
diff --git a/lib/ssl/test/ssl_upgrade_SUITE.erl b/lib/ssl/test/ssl_upgrade_SUITE.erl
index 875399db76..ead18aeb73 100644
--- a/lib/ssl/test/ssl_upgrade_SUITE.erl
+++ b/lib/ssl/test/ssl_upgrade_SUITE.erl
@@ -47,10 +47,7 @@ init_per_suite(Config0) ->
{skip, Reason} ->
{skip, Reason};
Config ->
- Result =
- {ok, _} = make_certs:all(proplists:get_value(data_dir, Config),
- proplists:get_value(priv_dir, Config)),
- ssl_test_lib:cert_options(Config)
+ ssl_test_lib:make_rsa_cert(Config)
end
catch _:_ ->
{skip, "Crypto did not start"}
@@ -149,8 +146,8 @@ use_connection(Socket) ->
end.
soft_start_connection(Config, ResulProxy) ->
- ClientOpts = proplists:get_value(client_verification_opts, Config),
- ServerOpts = proplists:get_value(server_verification_opts, Config),
+ ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
+ ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = start_server([{node, ServerNode}, {port, 0},
{from, ResulProxy},
@@ -166,8 +163,8 @@ soft_start_connection(Config, ResulProxy) ->
{Server, Client}.
restart_start_connection(Config, ResulProxy) ->
- ClientOpts = proplists:get_value(client_verification_opts, Config),
- ServerOpts = proplists:get_value(server_verification_opts, Config),
+ ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
+ ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = start_server([{node, ServerNode}, {port, 0},
{from, ResulProxy},
diff --git a/lib/ssl/test/x509_test.erl b/lib/ssl/test/x509_test.erl
index fea01efdaf..faf223ae35 100644
--- a/lib/ssl/test/x509_test.erl
+++ b/lib/ssl/test/x509_test.erl
@@ -22,7 +22,7 @@
-module(x509_test).
- -include_lib("public_key/include/public_key.hrl").
+-include_lib("public_key/include/public_key.hrl").
-export([extensions/1, gen_pem_config_files/3]).
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index c4bcc1560c..98070f794c 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 9.2.1
+SSL_VSN = 9.2.2