aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/src/tls_connection.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/src/tls_connection.erl')
-rw-r--r--lib/ssl/src/tls_connection.erl73
1 files changed, 54 insertions, 19 deletions
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index a3002830d1..8320d3f7f3 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -38,7 +38,8 @@
-include("ssl_api.hrl").
-include("ssl_internal.hrl").
-include("ssl_srp.hrl").
--include_lib("public_key/include/public_key.hrl").
+-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/logger.hrl").
%% Internal application API
@@ -111,12 +112,13 @@ start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
init([Role, Host, Port, Socket, Options, User, CbInfo]) ->
process_flag(trap_exit, true),
- State0 = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
+ State0 = #state{protocol_specific = Map} = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
try
State = ssl_connection:ssl_config(State0#state.ssl_options, Role, State0),
gen_statem:enter_loop(?MODULE, [], init, State)
catch throw:Error ->
- gen_statem:enter_loop(?MODULE, [], error, {Error, State0})
+ EState = State0#state{protocol_specific = Map#{error => Error}},
+ gen_statem:enter_loop(?MODULE, [], error, EState)
end.
%%====================================================================
%% State transition handling
@@ -129,6 +131,7 @@ next_record(#state{protocol_buffers =
= Buffers,
connection_states = ConnStates0,
ssl_options = #ssl_options{padding_check = Check}} = State) ->
+
case tls_record:decode_cipher_text(CT, ConnStates0, Check) of
{Plain, ConnStates} ->
{Plain, State#state{protocol_buffers =
@@ -264,9 +267,19 @@ send_handshake(Handshake, State) ->
queue_handshake(Handshake, #state{negotiated_version = Version,
tls_handshake_history = Hist0,
flight_buffer = Flight0,
- connection_states = ConnectionStates0} = State0) ->
+ connection_states = ConnectionStates0,
+ ssl_options = SslOpts} = State0) ->
{BinHandshake, ConnectionStates, Hist} =
encode_handshake(Handshake, Version, ConnectionStates0, Hist0),
+ Report = #{direction => outbound,
+ protocol => 'tls_record',
+ message => BinHandshake},
+ HandshakeMsg = #{direction => outbound,
+ protocol => 'handshake',
+ message => Handshake},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, HandshakeMsg, #{domain => [otp,ssl,handshake]}),
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
+
State0#state{connection_states = ConnectionStates,
tls_handshake_history = Hist,
flight_buffer = Flight0 ++ [BinHandshake]}.
@@ -278,10 +291,15 @@ send_handshake_flight(#state{socket = Socket,
{State0#state{flight_buffer = []}, []}.
queue_change_cipher(Msg, #state{negotiated_version = Version,
- flight_buffer = Flight0,
- connection_states = ConnectionStates0} = State0) ->
+ flight_buffer = Flight0,
+ connection_states = ConnectionStates0,
+ ssl_options = SslOpts} = State0) ->
{BinChangeCipher, ConnectionStates} =
encode_change_cipher(Msg, Version, ConnectionStates0),
+ Report = #{direction => outbound,
+ protocol => 'tls_record',
+ message => BinChangeCipher},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
State0#state{connection_states = ConnectionStates,
flight_buffer = Flight0 ++ [BinChangeCipher]}.
@@ -309,10 +327,16 @@ empty_connection_state(ConnectionEnd, BeastMitigation) ->
send_alert(Alert, #state{negotiated_version = Version,
socket = Socket,
transport_cb = Transport,
- connection_states = ConnectionStates0} = State0) ->
+ connection_states = ConnectionStates0,
+ ssl_options = SslOpts} = State0) ->
{BinMsg, ConnectionStates} =
encode_alert(Alert, Version, ConnectionStates0),
+
send(Transport, Socket, BinMsg),
+ Report = #{direction => outbound,
+ protocol => 'tls_record',
+ message => BinMsg},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
State0#state{connection_states = ConnectionStates}.
%%--------------------------------------------------------------------
@@ -415,6 +439,14 @@ init({call, From}, {start, Timeout},
{BinMsg, ConnectionStates, Handshake} =
encode_handshake(Hello, HelloVersion, ConnectionStates0, Handshake0),
send(Transport, Socket, BinMsg),
+ Report = #{direction => outbound,
+ protocol => 'tls_record',
+ message => BinMsg},
+ HelloMsg = #{direction => outbound,
+ protocol => 'handshake',
+ message => Hello},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, HelloMsg, #{domain => [otp,ssl,handshake]}),
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
State1 = State0#state{connection_states = ConnectionStates,
negotiated_version = Version, %% Requested version
session =
@@ -432,17 +464,12 @@ init(Type, Event, State) ->
{start, timeout()} | term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-
-error({call, From}, {start, _Timeout}, {Error, State}) ->
- ssl_connection:stop_and_reply(
- normal, {reply, From, {error, Error}}, 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({call, _} = Call, Msg, State) ->
+ gen_handshake(?FUNCTION_NAME, Call, Msg, State);
error(_, _, _) ->
{keep_state_and_data, [postpone]}.
@@ -651,11 +678,11 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, Us
next_tls_record(Data, StateName, #state{protocol_buffers =
#protocol_buffers{tls_record_buffer = Buf0,
- tls_cipher_texts = CT0} = Buffers}
- = State0) ->
- case tls_record:get_tls_records(Data,
+ tls_cipher_texts = CT0} = Buffers,
+ ssl_options = SslOpts} = State0) ->
+ case tls_record:get_tls_records(Data,
acceptable_record_versions(StateName, State0),
- Buf0) of
+ Buf0, SslOpts) of
{Records, Buf1} ->
CT1 = CT0 ++ Records,
next_record(State0#state{protocol_buffers =
@@ -666,10 +693,18 @@ next_tls_record(Data, StateName, #state{protocol_buffers =
end.
+%% TLS 1.3 Client/Server
+%% - Ignore TLSPlaintext.legacy_record_version
+%% - Verify that TLSCiphertext.legacy_record_version is set to 0x0303 for all records
+%% other than an initial ClientHello, where it MAY also be 0x0301.
acceptable_record_versions(hello, _) ->
- [tls_record:protocol_version(Vsn) || Vsn <- ?ALL_AVAILABLE_VERSIONS];
+ [tls_record:protocol_version(Vsn) || Vsn <- ?ALL_TLS_RECORD_VERSIONS];
+acceptable_record_versions(_, #state{negotiated_version = {Major, Minor}})
+ when Major > 3; Major =:= 3, Minor >= 4 ->
+ [{3, 3}];
acceptable_record_versions(_, #state{negotiated_version = Version}) ->
[Version].
+
handle_record_alert(Alert, _) ->
Alert.