From 88733e3e2e9b7e15fac74a42e813da4f19f86482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Fri, 30 Nov 2018 13:35:20 +0100 Subject: ssl: Process "supported_versions" before decoding Change-Id: I465760b7001692367c68839219745e40abafdfa8 --- lib/ssl/src/ssl_handshake.erl | 57 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) (limited to 'lib/ssl/src/ssl_handshake.erl') diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 9ed2654668..1b555f0277 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -61,7 +61,7 @@ -export([encode_handshake/2, encode_hello_extensions/1, encode_extensions/1, encode_extensions/2, encode_client_protocol_negotiation/2, encode_protocols_advertised_on_server/1]). %% Decode --export([decode_handshake/3, decode_vector/1, decode_hello_extensions/3, decode_extensions/3, +-export([decode_handshake/3, decode_vector/1, decode_hello_extensions/4, decode_extensions/3, decode_server_key/3, decode_client_key/3, decode_suites/2 ]). @@ -746,7 +746,7 @@ decode_handshake(Version, ?SERVER_HELLO, <>) -> - HelloExtensions = decode_hello_extensions(Extensions, Version, server_hello), + HelloExtensions = decode_hello_extensions(Extensions, Version, {Major, Minor}, server_hello), #server_hello{ server_version = {Major,Minor}, @@ -803,11 +803,12 @@ decode_vector(<>) -> Vector. %%-------------------------------------------------------------------- --spec decode_hello_extensions(binary(), ssl_record:ssl_version(), atom()) -> map(). +-spec decode_hello_extensions(binary(), ssl_record:ssl_version(), + ssl_record:ssl_version(), atom()) -> map(). %% %% Description: Decodes TLS hello extensions %%-------------------------------------------------------------------- -decode_hello_extensions(Extensions, Version, MessageType0) -> +decode_hello_extensions(Extensions, LocalVersion, LegacyVersion, MessageType0) -> %% Convert legacy atoms MessageType = case MessageType0 of @@ -815,6 +816,13 @@ decode_hello_extensions(Extensions, Version, MessageType0) -> server -> server_hello; T -> T end, + %% RFC 8446 - 4.2.1 + %% Servers MUST be prepared to receive ClientHellos that include this extension but + %% do not include 0x0304 in the list of versions. + %% Clients MUST check for this extension prior to processing the rest of the + %% ServerHello (although they will have to parse the ServerHello in order to read + %% the extension). + Version = process_supported_versions_extension(Extensions, LocalVersion, LegacyVersion), decode_extensions(Extensions, Version, MessageType, empty_extensions(Version, MessageType)). %%-------------------------------------------------------------------- @@ -2195,6 +2203,47 @@ dec_server_key_signature(Params, <>, _) -> dec_server_key_signature(_, _, _) -> throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, failed_to_decrypt_server_key_sign)). +%% Processes a ClientHello/ServerHello message and returns the version to be used +%% in the decoding functions. The following rules apply: +%% - IF supported_versions extension is absent: +%% RETURN the lowest of (LocalVersion and LegacyVersion) +%% - IF supported_versions estension is present: +%% RETURN the lowest of (LocalVersion and first element of supported versions) +process_supported_versions_extension(<<>>, LocalVersion, LegacyVersion) + when LegacyVersion =< LocalVersion -> + LegacyVersion; +process_supported_versions_extension(<<>>, LocalVersion, _LegacyVersion) -> + LocalVersion; +process_supported_versions_extension(<>, + LocalVersion, _LegacyVersion) when Len > 2 -> + <> = ExtData, + [Highest|_] = decode_versions(Versions0), + if Highest =< LocalVersion -> + Highest; + true -> + LocalVersion + end; +process_supported_versions_extension(<>, + LocalVersion, _LegacyVersion) when Len =:= 2 -> + SelectedVersion = {Major, Minor}, + if SelectedVersion =< LocalVersion -> + SelectedVersion; + true -> + LocalVersion + end; +process_supported_versions_extension(<>, + LocalVersion, LegacyVersion) -> + process_supported_versions_extension(Rest, LocalVersion, LegacyVersion); +%% Tolerate protocol encoding errors and skip parsing the rest of the extension. +process_supported_versions_extension(_, LocalVersion, LegacyVersion) + when LegacyVersion =< LocalVersion -> + LegacyVersion; +process_supported_versions_extension(_, LocalVersion, _) -> + LocalVersion. + decode_extensions(<<>>, _Version, _MessageType, Acc) -> Acc; decode_extensions(< Date: Fri, 30 Nov 2018 13:39:10 +0100 Subject: ssl: Fix handling of signature algorithms Change-Id: I5cc6b470ea19e32dd5516a86fe6750c5b51d5368 --- lib/ssl/src/ssl_handshake.erl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib/ssl/src/ssl_handshake.erl') diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 1b555f0277..d45fea84be 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -1175,7 +1175,12 @@ kse_remove_private_key(#key_share_entry{ signature_algs_ext(undefined) -> undefined; -signature_algs_ext(SignatureSchemes) -> +signature_algs_ext(SignatureSchemes0) -> + %% The SSL option signature_algs contains both hash-sign algorithms (tuples) and + %% signature schemes (atoms) if TLS 1.3 is configured. + %% Filter out all hash-sign tuples when creating the signature_algs extension. + %% (TLS 1.3 specific record type) + SignatureSchemes = lists:filter(fun is_atom/1, SignatureSchemes0), #signature_algorithms{signature_scheme_list = SignatureSchemes}. signature_algs_cert(undefined) -> -- cgit v1.2.3 From 8724ebf1e13fe4ebec73aaa9285011d9aa99e9cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Thu, 13 Dec 2018 15:41:07 +0100 Subject: ssl: Fix encoding/decoding of supported_versions Encode length of supported_versions in one octet instead of two. Change-Id: If24b38f3d2a40f0aa7152bb05bc0392efca6454c --- lib/ssl/src/ssl_handshake.erl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'lib/ssl/src/ssl_handshake.erl') diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index d45fea84be..5e3c767c2c 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -680,9 +680,9 @@ encode_extensions([#sni{hostname = Hostname} | Rest], Acc) -> encode_extensions([#client_hello_versions{versions = Versions0} | Rest], Acc) -> Versions = encode_versions(Versions0), VerLen = byte_size(Versions), - Len = VerLen + 2, + Len = VerLen + 1, encode_extensions(Rest, <>); + ?UINT16(Len), ?BYTE(VerLen), Versions/binary, Acc/binary>>); encode_extensions([#server_hello_selected_version{selected_version = Version0} | Rest], Acc) -> Version = encode_versions([Version0]), Len = byte_size(Version), %% 2 @@ -745,7 +745,6 @@ decode_handshake(Version, ?SERVER_HELLO, <>) -> - HelloExtensions = decode_hello_extensions(Extensions, Version, {Major, Minor}, server_hello), #server_hello{ @@ -2222,7 +2221,7 @@ process_supported_versions_extension(<<>>, LocalVersion, _LegacyVersion) -> process_supported_versions_extension(<>, LocalVersion, _LegacyVersion) when Len > 2 -> - <> = ExtData, + <> = ExtData, [Highest|_] = decode_versions(Versions0), if Highest =< LocalVersion -> Highest; @@ -2375,7 +2374,7 @@ decode_extensions(<>, Version, MessageType, Acc) when Len > 2 -> - <> = ExtData, + <> = ExtData, decode_extensions(Rest, Version, MessageType, Acc#{client_hello_versions => #client_hello_versions{ -- cgit v1.2.3