summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngela Anderton Andin <ingela@erlang.org>2022-04-21 13:06:15 +0200
committerIngela Anderton Andin <ingela@erlang.org>2022-04-25 08:52:23 +0200
commit5e48b34f684c837bb93980c96740c16663813fdb (patch)
treec368a3b4e162606ec84d62e05317e75fca8b6e8b
parentf00827e60ff1f43aae30ac596f342d45d4d3860e (diff)
downloaderlang-5e48b34f684c837bb93980c96740c16663813fdb.tar.gz
ssl: Fix version mismatch
The special case handled by the tls_gen_connection:effective_version function is only valid in the hello and wait_sh state. Closes #5835
-rw-r--r--lib/ssl/src/ssl_handshake.erl11
-rw-r--r--lib/ssl/src/tls_gen_connection.erl29
2 files changed, 22 insertions, 18 deletions
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 837f7c0249..ee102077af 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -863,14 +863,13 @@ decode_handshake(_Version, ?CERTIFICATE_STATUS, <<?BYTE(?CERTIFICATE_STATUS_TYPE
response = ASN1OcspResponse};
decode_handshake(_Version, ?SERVER_KEY_EXCHANGE, Keys) ->
#server_key_exchange{exchange_keys = Keys};
-decode_handshake({Major, Minor} = Version, ?CERTIFICATE_REQUEST,
- <<?BYTE(CertTypesLen), CertTypes:CertTypesLen/binary,
- ?UINT16(HashSignsLen), HashSigns:HashSignsLen/binary,
- ?UINT16(CertAuthsLen), CertAuths:CertAuthsLen/binary>>)
- when Major >= 3, Minor >= 3 ->
+decode_handshake({3, 3} = Version, ?CERTIFICATE_REQUEST,
+ <<?BYTE(CertTypesLen), CertTypes:CertTypesLen/binary,
+ ?UINT16(HashSignsLen), HashSigns:HashSignsLen/binary,
+ ?UINT16(CertAuthsLen), CertAuths:CertAuthsLen/binary>>) ->
HashSignAlgos = decode_sign_alg(Version, HashSigns),
#certificate_request{certificate_types = CertTypes,
- hashsign_algorithms = #hash_sign_algos{hash_sign_algos = HashSignAlgos},
+ hashsign_algorithms = #hash_sign_algos{hash_sign_algos = HashSignAlgos},
certificate_authorities = CertAuths};
decode_handshake(_Version, ?CERTIFICATE_REQUEST,
<<?BYTE(CertTypesLen), CertTypes:CertTypesLen/binary,
diff --git a/lib/ssl/src/tls_gen_connection.erl b/lib/ssl/src/tls_gen_connection.erl
index 89cc945e21..f5ec0832ad 100644
--- a/lib/ssl/src/tls_gen_connection.erl
+++ b/lib/ssl/src/tls_gen_connection.erl
@@ -398,7 +398,7 @@ handle_protocol_record(#ssl_tls{type = ?HANDSHAKE, fragment = Data},
try
%% Calculate the effective version that should be used when decoding an incoming handshake
%% message.
- EffectiveVersion = effective_version(Version, Options, Role),
+ EffectiveVersion = effective_version(Version, Options, Role, StateName),
{Packets, Buf} = tls_handshake:get_tls_handshake(EffectiveVersion,Data,Buf0, Options),
State =
State0#state{protocol_buffers =
@@ -751,19 +751,24 @@ next_record_done(#state{protocol_buffers = Buffers} = State, CipherTexts, Connec
State#state{protocol_buffers = Buffers#protocol_buffers{tls_cipher_texts = CipherTexts},
connection_states = ConnectionStates}}.
-%% Special version handling for TLS 1.3 clients:
-%% In the shared state 'init' negotiated_version is set to requested version and
-%% that is expected by the legacy part of the state machine. However, in order to
-%% be able to process new TLS 1.3 extensions, the effective version shall be set
-%% {3,4}.
-%% When highest supported version is {3,4} the negotiated version is set to {3,3}.
-effective_version({3,3} , #{versions := [Version|_]}, client) when Version >= {3,4} ->
+
+%% Pre TLS-1.3, on the client side, the connection state variable negotiated_version will initialy be
+%% the requested version. On the server side the the variable is intially undefined.
+%% When the client can support TLS-1.3 and one or more prior versions and we are waiting
+%% for the server hello (with or without a RetryRequest, that is in state hello or in state wait_sh),
+%% the "initial requested version" keeped in the connection state variable negotiated_version
+%% (before the versions is actually negotiated) will always be the value of TLS-1.2 (which is a legacy
+%% filed in TLS-1.3 client hello and versions are negotiated with an hello extension), but when
+%% decoding the server_hello messages we want to go through TLS-1.3 decode functions to be able
+%% to handle TLS-1.3 extensions if TLS-1.3 will be the negotiated version.
+effective_version({3,3} , #{versions := [{3,4} = Version |_]}, client, StateName) when StateName == hello;
+ StateName == wait_sh ->
Version;
-%% Use highest supported version during startup (TLS server, all versions).
-effective_version(undefined, #{versions := [Version|_]}, _) ->
+%% When the negotiated_version variable is not yet set use the highest supported version.
+effective_version(undefined, #{versions := [Version|_]}, _, _) ->
Version;
-%% Use negotiated version in all other cases.
-effective_version(Version, _, _) ->
+%% In all other cases use version saved in the connection state variable negotiated_version
+effective_version(Version, _, _, _) ->
Version.
assert_buffer_sanity(<<?BYTE(_Type), ?UINT24(Length), Rest/binary>>,