aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/doc/src/notes.xml55
-rw-r--r--lib/ssl/doc/src/ssl_introduction.xml2
-rw-r--r--lib/ssl/doc/src/using_ssl.xml37
-rw-r--r--lib/ssl/src/dtls_connection.erl36
-rw-r--r--lib/ssl/src/dtls_handshake.erl7
-rw-r--r--lib/ssl/src/dtls_udp_listener.erl7
-rw-r--r--lib/ssl/src/ssl.app.src2
-rw-r--r--lib/ssl/src/ssl_handshake.erl8
-rw-r--r--lib/ssl/src/tls_connection.erl9
-rw-r--r--lib/ssl/src/tls_handshake.erl9
-rw-r--r--lib/ssl/test/ssl.spec6
-rw-r--r--lib/ssl/vsn.mk2
12 files changed, 145 insertions, 35 deletions
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 37c916e585..79176f5edf 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -27,6 +27,61 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
+<section><title>SSL 8.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Packet options cannot be supported for unreliable
+ transports, that is, packet option for DTLS over udp will
+ not be supported.</p>
+ <p>
+ Own Id: OTP-14664</p>
+ </item>
+ <item>
+ <p>
+ Ensure data delivery before close if possible. This fix
+ is related to fix in PR-1479.</p>
+ <p>
+ Own Id: OTP-14794</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The crypto API is extended to use private/public keys
+ stored in an Engine for sign/verify or encrypt/decrypt
+ operations.</p>
+ <p>
+ The ssl application provides an API to use this new
+ engine concept in TLS.</p>
+ <p>
+ Own Id: OTP-14448</p>
+ </item>
+ <item>
+ <p>
+ Implemented renegotiation for DTLS</p>
+ <p>
+ Own Id: OTP-14563</p>
+ </item>
+ <item>
+ <p>
+ A new command line option <c>-ssl_dist_optfile</c> has
+ been added to facilitate specifying the many options
+ needed when using SSL as the distribution protocol.</p>
+ <p>
+ Own Id: OTP-14657</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 8.2.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ssl/doc/src/ssl_introduction.xml b/lib/ssl/doc/src/ssl_introduction.xml
index d3e39dbb01..25b05a769d 100644
--- a/lib/ssl/doc/src/ssl_introduction.xml
+++ b/lib/ssl/doc/src/ssl_introduction.xml
@@ -36,7 +36,7 @@
<title>Purpose</title>
<p>Transport Layer Security (TLS) and its predecessor, the Secure
Sockets Layer (SSL), are cryptographic protocols designed to
- provide communications security over a computer network. The protocols use
+ provide communications security over a computer network. The protocols
use X.509 certificates and hence public key (asymmetric) cryptography to
authenticate the counterpart with whom they communicate,
and to exchange a symmetric key for payload encryption. The protocol provides
diff --git a/lib/ssl/doc/src/using_ssl.xml b/lib/ssl/doc/src/using_ssl.xml
index f84cd6e391..61918a346d 100644
--- a/lib/ssl/doc/src/using_ssl.xml
+++ b/lib/ssl/doc/src/using_ssl.xml
@@ -152,4 +152,41 @@ Shell got {ssl,{sslsocket,[...]},"foo"}
ok</code>
</section>
</section>
+
+ <section>
+ <title>Using an Engine Stored Key</title>
+
+ <p>Erlang ssl application is able to use private keys provided
+ by OpenSSL engines using the following mechanism:</p>
+
+ <code type="erl">1> ssl:start().
+ok</code>
+
+ <p>Load a crypto engine, should be done once per engine used. For example
+ dynamically load the engine called <c>MyEngine</c>:
+ </p>
+ <code type="erl">2> {ok, EngineRef} =
+crypto:engine_load(&lt;&lt;"dynamic">>,
+ [{&lt;&lt;"SO_PATH">>, "/tmp/user/engines/MyEngine"},&lt;&lt;"LOAD">>],[]).
+{ok,#Ref&lt;0.2399045421.3028942852.173962>}
+ </code>
+
+ <p>Create a map with the engine information and the algorithm used by the engine:</p>
+ <code type="erl">3> PrivKey =
+ #{algorithm => rsa,
+ engine => EngineRef,
+ key_id => "id of the private key in Engine"}.
+ </code>
+ <p>Use the map in the ssl key option:</p>
+ <code type="erl">4> {ok, SSLSocket} =
+ssl:connect("localhost", 9999,
+ [{cacertfile, "cacerts.pem"},
+ {certfile, "cert.pem"},
+ {key, PrivKey}], infinity).
+ </code>
+
+ <p>See also <seealso marker="crypto:engine_load#engine_load"> crypto documentation</seealso> </p>
+
+ </section>
+
</chapter>
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index e5760e7951..3b5a548f72 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -143,10 +143,16 @@ next_record(#state{role = server,
dtls_udp_listener:active_once(Listener, Client, self()),
{no_record, State};
next_record(#state{role = client,
- socket = {_Server, Socket},
+ socket = {_Server, Socket} = DTLSSocket,
+ close_tag = CloseTag,
transport_cb = Transport} = State) ->
- dtls_socket:setopts(Transport, Socket, [{active,once}]),
- {no_record, State};
+ case dtls_socket:setopts(Transport, Socket, [{active,once}]) of
+ ok ->
+ {no_record, State};
+ _ ->
+ self() ! {CloseTag, DTLSSocket},
+ {no_record, State}
+ end;
next_record(State) ->
{no_record, State}.
@@ -218,12 +224,12 @@ next_event(StateName, Record,
#state{connection_states = #{current_read := #{epoch := CurrentEpoch}}} = State0, Actions) ->
case Record of
no_record ->
- {next_state, StateName, State0, Actions};
+ {next_state, StateName, State0, Actions};
#ssl_tls{epoch = CurrentEpoch,
version = Version} = Record ->
State = dtls_version(StateName, Version, State0),
- {next_state, StateName, State,
- [{next_event, internal, {protocol_record, Record}} | Actions]};
+ {next_state, StateName, State,
+ [{next_event, internal, {protocol_record, Record}} | Actions]};
#ssl_tls{epoch = _Epoch,
version = _Version} = _Record ->
%% TODO maybe buffer later epoch
@@ -605,6 +611,12 @@ certify(info, Event, State) ->
gen_info(Event, ?FUNCTION_NAME, State);
certify(internal = Type, #server_hello_done{} = Event, State) ->
ssl_connection:certify(Type, Event, prepare_flight(State), ?MODULE);
+certify(internal, #change_cipher_spec{type = <<1>>}, State0) ->
+ {State1, Actions0} = send_handshake_flight(State0, retransmit_epoch(?FUNCTION_NAME, State0)),
+ {Record, State2} = next_record(State1),
+ {next_state, ?FUNCTION_NAME, State, Actions} = next_event(?FUNCTION_NAME, Record, State2, Actions0),
+ %% This will reset the retransmission timer by repeating the enter state event
+ {repeat_state, State, Actions};
certify(state_timeout, Event, State) ->
handle_state_timeout(Event, ?FUNCTION_NAME, State);
certify(Type, Event, State) ->
@@ -864,12 +876,14 @@ handle_info(new_cookie_secret, StateName,
handle_info(Msg, StateName, State) ->
ssl_connection:StateName(info, Msg, State, ?MODULE).
-handle_state_timeout(flight_retransmission_timeout, StateName,
- #state{flight_state = {retransmit, NextTimeout}} = State0) ->
- {State1, Actions} = send_handshake_flight(State0#state{flight_state = {retransmit, NextTimeout}},
+handle_state_timeout(flight_retransmission_timeout, StateName,
+ #state{flight_state = {retransmit, NextTimeout}} = State0) ->
+ {State1, Actions0} = send_handshake_flight(State0#state{flight_state = {retransmit, NextTimeout}},
retransmit_epoch(StateName, State0)),
- {Record, State} = next_record(State1),
- next_event(StateName, Record, State, Actions).
+ {Record, State2} = next_record(State1),
+ {next_state, StateName, State, Actions} = next_event(StateName, Record, State2, Actions0),
+ %% This will reset the retransmission timer by repeating the enter state event
+ {repeat_state, State, Actions}.
handle_alerts([], Result) ->
Result;
diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl
index 5e8f5c2ca0..6071eece13 100644
--- a/lib/ssl/src/dtls_handshake.erl
+++ b/lib/ssl/src/dtls_handshake.erl
@@ -67,7 +67,8 @@ client_hello(Host, Port, ConnectionStates, SslOpts,
%%--------------------------------------------------------------------
client_hello(Host, Port, Cookie, ConnectionStates,
#ssl_options{versions = Versions,
- ciphers = UserSuites
+ ciphers = UserSuites,
+ fallback = Fallback
} = SslOpts,
Cache, CacheCb, Renegotiation, OwnCert) ->
Version = dtls_record:highest_protocol_version(Versions),
@@ -83,7 +84,9 @@ client_hello(Host, Port, Cookie, ConnectionStates,
#client_hello{session_id = Id,
client_version = Version,
- cipher_suites = ssl_handshake:cipher_suites(CipherSuites, Renegotiation),
+ cipher_suites =
+ ssl_handshake:cipher_suites(CipherSuites,
+ Renegotiation, Fallback),
compression_methods = ssl_record:compressions(),
random = SecParams#security_parameters.client_random,
cookie = Cookie,
diff --git a/lib/ssl/src/dtls_udp_listener.erl b/lib/ssl/src/dtls_udp_listener.erl
index c9e04767aa..0608c6bd2b 100644
--- a/lib/ssl/src/dtls_udp_listener.erl
+++ b/lib/ssl/src/dtls_udp_listener.erl
@@ -84,7 +84,7 @@ init([Port, EmOpts, InetOptions, DTLSOptions]) ->
listener = Socket,
close = false}}
catch _:_ ->
- {error, closed}
+ {stop, {shutdown, {error, closed}}}
end.
handle_call({accept, _}, _, #state{close = true} = State) ->
{reply, {error, closed}, State};
@@ -153,15 +153,18 @@ handle_info({udp_error, Socket, Error}, #state{listener = Socket} = State) ->
handle_info({'DOWN', _, process, Pid, _}, #state{clients = Clients,
dtls_processes = Processes0,
+ dtls_msq_queues = MsgQueues0,
close = ListenClosed} = State) ->
Client = kv_get(Pid, Processes0),
Processes = kv_delete(Pid, Processes0),
+ MsgQueues = kv_delete(Client, MsgQueues0),
case ListenClosed andalso kv_empty(Processes) of
true ->
{stop, normal, State};
false ->
{noreply, State#state{clients = set_delete(Client, Clients),
- dtls_processes = Processes}}
+ dtls_processes = Processes,
+ dtls_msq_queues = MsgQueues}}
end.
terminate(_Reason, _State) ->
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index c5b55641a1..3c6cd254c1 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -63,4 +63,4 @@
{env, []},
{mod, {ssl_app, []}},
{runtime_dependencies, ["stdlib-3.2","public_key-1.5","kernel-6.0",
- "erts-10.0","crypto-3.3", "inets-5.10.7"]}]}.
+ "erts-10.0","crypto-4.2", "inets-5.10.7"]}]}.
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 61d61b53dd..0c55af9174 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -67,7 +67,7 @@
%% Cipher suites handling
-export([available_suites/2, available_signature_algs/2, available_signature_algs/4,
- cipher_suites/2, prf/6, select_session/11, supported_ecc/1,
+ cipher_suites/3, prf/6, select_session/11, supported_ecc/1,
premaster_secret/2, premaster_secret/3, premaster_secret/4]).
%% Extensions handling
@@ -801,6 +801,11 @@ available_signature_algs(#hash_sign_algos{hash_sign_algos = ClientHashSigns}, Su
available_signature_algs(_, _, _, _) ->
undefined.
+cipher_suites(Suites, Renegotiation, true) ->
+ %% TLS_FALLBACK_SCSV should be placed last -RFC7507
+ cipher_suites(Suites, Renegotiation) ++ [?TLS_FALLBACK_SCSV];
+cipher_suites(Suites, Renegotiation, false) ->
+ cipher_suites(Suites, Renegotiation).
cipher_suites(Suites, false) ->
[?TLS_EMPTY_RENEGOTIATION_INFO_SCSV | Suites];
cipher_suites(Suites, true) ->
@@ -1060,7 +1065,6 @@ select_hashsign(HashSigns, Cert, KeyExAlgo,
select_hashsign(HashSigns, Cert, KeyExAlgo, tls_v1:default_signature_algs(Version), Version);
select_hashsign(#hash_sign_algos{hash_sign_algos = HashSigns}, Cert, KeyExAlgo, SupportedHashSigns,
{Major, Minor}) when Major >= 3 andalso Minor >= 3 ->
- #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp),
#'OTPCertificate'{tbsCertificate = TBSCert,
signatureAlgorithm = {_,SignAlgo, _}} = public_key:pkix_decode_cert(Cert, otp),
#'OTPSubjectPublicKeyInfo'{algorithm = {_, SubjAlgo, _}} =
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 406a095d2e..cf2f3a2b62 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -439,8 +439,13 @@ init(Type, Event, State) ->
error({call, From}, {start, _Timeout}, {Error, State}) ->
ssl_connection:stop_and_reply(
normal, {reply, From, {error, Error}}, State);
-error({call, _} = Call, Msg, State) ->
- gen_handshake(?FUNCTION_NAME, Call, Msg, State);
+error({call, From}, {start, _Timeout},
+ #state{protocol_specific = #{error := Error}} = State) ->
+ ssl_connection:stop_and_reply(
+ normal, {reply, From, {error, Error}}, State);
+error({call, _} = Call, Msg, {Error, #state{protocol_specific = Map} = State}) ->
+ gen_handshake(?FUNCTION_NAME, Call, Msg,
+ State#state{protocol_specific = Map#{error => Error}});
error(_, _, _) ->
{keep_state_and_data, [postpone]}.
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index d59e817ffb..8817418fb0 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -67,14 +67,7 @@ client_hello(Host, Port, ConnectionStates,
AvailableCipherSuites,
SslOpts, ConnectionStates,
Renegotiation),
- CipherSuites =
- case Fallback of
- true ->
- [?TLS_FALLBACK_SCSV |
- ssl_handshake:cipher_suites(AvailableCipherSuites, Renegotiation)];
- false ->
- ssl_handshake:cipher_suites(AvailableCipherSuites, Renegotiation)
- end,
+ CipherSuites = ssl_handshake:cipher_suites(AvailableCipherSuites, Renegotiation, Fallback),
Id = ssl_session:client_id({Host, Port, SslOpts}, Cache, CacheCb, OwnCert),
#client_hello{session_id = Id,
client_version = Version,
diff --git a/lib/ssl/test/ssl.spec b/lib/ssl/test/ssl.spec
index 17b66aef40..cb54168d36 100644
--- a/lib/ssl/test/ssl.spec
+++ b/lib/ssl/test/ssl.spec
@@ -1,8 +1,4 @@
{suites,"../ssl_test",all}.
-{skip_cases, "../ssl_test",
- ssl_bench_SUITE, [setup_sequential, setup_concurrent, payload_simple,
- use_pem_cache, bypass_pem_cache],
- "Benchmarks run separately"}.
{skip_suites, "../ssl_test",
- [ssl_dist_bench_SUITE],
+ [ssl_bench_SUITE, ssl_dist_bench_SUITE],
"Benchmarks run separately"}.
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index cf6481d14c..2650399eea 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 8.2.2
+SSL_VSN = 8.2.3