Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion lib/ssl/src/ssl_handshake.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2885,10 +2885,12 @@ decode_extensions(<<?UINT16(?ALPN_EXT), ?UINT16(ExtLen), ?UINT16(Len),
ExtensionData:Len/binary, Rest/binary>>, Version, MessageType, Acc)
when Len + 2 =:= ExtLen ->
ALPN = #alpn{extension_data = ExtensionData},
assert_unique_extension(alpn, Acc),
decode_extensions(Rest, Version, MessageType, Acc#{alpn => ALPN});
decode_extensions(<<?UINT16(?NEXTPROTONEG_EXT), ?UINT16(Len),
ExtensionData:Len/binary, Rest/binary>>, Version, MessageType, Acc) ->
NextP = #next_protocol_negotiation{extension_data = ExtensionData},
assert_unique_extension(next_protocol_negotiation, Acc),
decode_extensions(Rest, Version, MessageType, Acc#{next_protocol_negotiation => NextP});
decode_extensions(<<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len),
Info:Len/binary, Rest/binary>>, Version, MessageType, Acc) ->
Expand All @@ -2900,6 +2902,7 @@ decode_extensions(<<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len),
<<?BYTE(VerifyLen), VerifyInfo/binary>> = Info,
VerifyInfo
end,
assert_unique_extension(renegotiation_info, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{renegotiation_info =>
#renegotiation_info{renegotiated_connection =
Expand All @@ -2908,6 +2911,7 @@ decode_extensions(<<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len),
decode_extensions(<<?UINT16(?SRP_EXT), ?UINT16(Len), ?BYTE(SRPLen),
SRP:SRPLen/binary, Rest/binary>>, Version, MessageType, Acc)
when Len == SRPLen + 1 ->
assert_unique_extension(srp, Acc),
decode_extensions(Rest, Version, MessageType, Acc#{srp => #srp{username = SRP}});

decode_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len),
Expand All @@ -2917,6 +2921,7 @@ decode_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len),
<<?UINT16(SignAlgoListLen), SignAlgoList/binary>> = ExtData,
HashSignAlgos = [{ssl_cipher:hash_algorithm(Hash), ssl_cipher:sign_algorithm(Sign)} ||
<<?BYTE(Hash), ?BYTE(Sign)>> <= SignAlgoList],
assert_unique_extension(signature_algs, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{signature_algs =>
#hash_sign_algos{hash_sign_algos =
Expand All @@ -2926,6 +2931,7 @@ decode_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len),
SignSchemeListLen = Len - 2,
<<?UINT16(SignSchemeListLen), SignSchemeList/binary>> = ExtData,
HashSigns = decode_sign_alg(Version, SignSchemeList),
assert_unique_extension(signature_algs, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{signature_algs =>
#hash_sign_algos{
Expand All @@ -2935,6 +2941,7 @@ decode_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len),
SignSchemeListLen = Len - 2,
<<?UINT16(SignSchemeListLen), SignSchemeList/binary>> = ExtData,
SignSchemes = decode_sign_alg(Version, SignSchemeList),
assert_unique_extension(signature_algs, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{signature_algs =>
#signature_algorithms{
Expand All @@ -2954,6 +2961,7 @@ decode_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_CERT_EXT), ?UINT16(Len),
end,
SignSchemes= lists:filtermap(Fun, [SignScheme ||
<<?UINT16(SignScheme)>> <= SignSchemeList]),
assert_unique_extension(signature_algs_cert, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{signature_algs_cert =>
#signature_algorithms_cert{
Expand All @@ -2963,6 +2971,7 @@ decode_extensions(<<?UINT16(?USE_SRTP_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>, Version, MessageType, Acc) ->
<<?UINT16(ProfilesLen), ProfilesBin:ProfilesLen/binary, ?BYTE(MKILen), MKI:MKILen/binary>> = ExtData,
Profiles = [P || <<P:2/binary>> <= ProfilesBin],
assert_unique_extension(use_srtp, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{use_srtp =>
#use_srtp{
Expand All @@ -2983,6 +2992,7 @@ decode_extensions(<<?UINT16(?ELLIPTIC_CURVES_EXT), ?UINT16(Len),
end
end,
EllipticCurves = lists:filtermap(Pick, [ECC || <<ECC:16>> <= EllipticCurveList]),
assert_unique_extension(elliptic_curves, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{elliptic_curves =>
#elliptic_curves{elliptic_curve_list =
Expand All @@ -3001,6 +3011,7 @@ decode_extensions(<<?UINT16(?ELLIPTIC_CURVES_EXT), ?UINT16(Len),
end
end,
SupportedGroups = lists:filtermap(Pick, [Group || <<Group:16>> <= GroupList]),
assert_unique_extension(elliptic_curves, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{elliptic_curves =>
#supported_groups{supported_groups =
Expand All @@ -3010,29 +3021,34 @@ decode_extensions(<<?UINT16(?EC_POINT_FORMATS_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>, Version, MessageType, Acc) ->
<<?BYTE(_), ECPointFormatList/binary>> = ExtData,
ECPointFormats = binary_to_list(ECPointFormatList),
assert_unique_extension(ec_point_formats, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{ec_point_formats =>
#ec_point_formats{ec_point_format_list =
ECPointFormats}});

decode_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len),
Rest/binary>>, Version, MessageType, Acc) when Len == 0 ->
assert_unique_extension(sni, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{sni => #sni{hostname = ""}}); %% Server may send an empty SNI

decode_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>, Version, MessageType, Acc) ->
<<?UINT16(_), NameList/binary>> = ExtData,
assert_unique_extension(sni, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{sni => dec_sni(NameList)});

decode_extensions(<<?UINT16(?MAX_FRAGMENT_LENGTH_EXT), ?UINT16(1), ?BYTE(MaxFragEnum), Rest/binary>>,
Version, MessageType, Acc) ->
%% RFC 6066 Section 4
assert_unique_extension(max_frag_enum, Acc),
decode_extensions(Rest, Version, MessageType, Acc#{max_frag_enum => #max_frag_enum{enum = MaxFragEnum}});
decode_extensions(<<?UINT16(?SUPPORTED_VERSIONS_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>, Version, MessageType, Acc) when Len > 2 ->
<<?BYTE(_),Versions/binary>> = ExtData,
assert_unique_extension(client_hello_versions, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{client_hello_versions =>
#client_hello_versions{
Expand All @@ -3041,6 +3057,7 @@ decode_extensions(<<?UINT16(?SUPPORTED_VERSIONS_EXT), ?UINT16(Len),
decode_extensions(<<?UINT16(?SUPPORTED_VERSIONS_EXT), ?UINT16(Len),
?UINT16(SelectedVersion), Rest/binary>>, Version, MessageType, Acc)
when Len =:= 2, SelectedVersion =:= 16#0304 ->
assert_unique_extension(server_hello_selected_version, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{server_hello_selected_version =>
#server_hello_selected_version{selected_version = ?TLS_1_3}});
Expand All @@ -3049,6 +3066,7 @@ decode_extensions(<<?UINT16(?KEY_SHARE_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>,
Version, MessageType = client_hello, Acc) ->
<<?UINT16(_),ClientShares/binary>> = ExtData,
assert_unique_extension(key_share, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{key_share =>
#key_share_client_hello{
Expand All @@ -3058,6 +3076,7 @@ decode_extensions(<<?UINT16(?KEY_SHARE_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>,
Version, MessageType = server_hello, Acc) ->
<<?UINT16(Group),?UINT16(KeyLen),KeyExchange:KeyLen/binary>> = ExtData,
assert_unique_extension(key_share, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{key_share =>
#key_share_server_hello{
Expand All @@ -3078,6 +3097,7 @@ decode_extensions(<<?UINT16(?KEY_SHARE_EXT), ?UINT16(Len),
decode_extensions(<<?UINT16(?PSK_KEY_EXCHANGE_MODES_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>, Version, MessageType, Acc) ->
<<?BYTE(PLen),KEModes:PLen/binary>> = ExtData,
assert_unique_extension(psk_key_exchange_modes, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{psk_key_exchange_modes =>
#psk_key_exchange_modes{
Expand All @@ -3087,17 +3107,18 @@ decode_extensions(<<?UINT16(?PRE_SHARED_KEY_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>,
Version, MessageType = client_hello, Acc) ->
<<?UINT16(IdLen),Identities:IdLen/binary,?UINT16(BLen),Binders:BLen/binary>> = ExtData,
assert_unique_extension(pre_shared_key, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{pre_shared_key =>
#pre_shared_key_client_hello{
offered_psks = #offered_psks{
identities = decode_psk_identities(Identities),
binders = decode_psk_binders(Binders)}}});

decode_extensions(<<?UINT16(?PRE_SHARED_KEY_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>,
Version, MessageType = server_hello, Acc) ->
<<?UINT16(Identity)>> = ExtData,
assert_unique_extension(pre_shared_key, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{pre_shared_key =>
#pre_shared_key_server_hello{
Expand All @@ -3107,6 +3128,7 @@ decode_extensions(<<?UINT16(?COOKIE_EXT), ?UINT16(Len), ?UINT16(CookieLen),
Cookie:CookieLen/binary, Rest/binary>>,
Version, MessageType, Acc)
when Len == CookieLen + 2 ->
assert_unique_extension(cookie, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{cookie => #cookie{cookie = Cookie}});

Expand All @@ -3117,6 +3139,7 @@ decode_extensions(<<?UINT16(?STATUS_REQUEST), ?UINT16(Len),
_ExtensionData:Len/binary, Rest/binary>>, Version,
MessageType = server_hello, Acc)
when Len =:= 0 ->
assert_unique_extension(status_request, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{status_request => undefined});
%% RFC8446 4.4.2.1, In TLS1.3, the body of the "status_request" extension
Expand All @@ -3129,6 +3152,7 @@ decode_extensions(<<?UINT16(?STATUS_REQUEST), ?UINT16(Len),
<<?BYTE(?CERTIFICATE_STATUS_TYPE_OCSP),
?UINT24(OCSPLen),
ASN1OCSPResponse:OCSPLen/binary>> ->
assert_unique_extension(status_request, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{status_request => #certificate_status{response = ASN1OCSPResponse}});
_Other ->
Expand All @@ -3137,12 +3161,14 @@ decode_extensions(<<?UINT16(?STATUS_REQUEST), ?UINT16(Len),

decode_extensions(<<?UINT16(?EARLY_DATA_EXT), ?UINT16(0), Rest/binary>>,
Version, MessageType, Acc) ->
assert_unique_extension(early_data, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{early_data => #early_data_indication{}});

decode_extensions(<<?UINT16(?EARLY_DATA_EXT), ?UINT16(4), ?UINT32(MaxSize),
Rest/binary>>,
Version, MessageType, Acc) ->
assert_unique_extension(early_data, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{early_data =>
#early_data_indication_nst{indication = MaxSize}});
Expand All @@ -3151,6 +3177,7 @@ decode_extensions(<<?UINT16(?CERTIFICATE_AUTHORITIES_EXT), ?UINT16(Len),
Version, MessageType, Acc) ->
CertAutsLen = Len - 2,
<<?UINT16(CertAutsLen), EncCertAuts/binary>> = CertAutsExt,
assert_unique_extension(certificate_authorities, Acc),
decode_extensions(Rest, Version, MessageType,
Acc#{certificate_authorities =>
#certificate_authorities{authorities = decode_cert_auths(EncCertAuts, [])}});
Expand All @@ -3162,6 +3189,14 @@ decode_extensions(<<?UINT16(_), ?UINT16(Len), _Unknown:Len/binary, Rest/binary>>
decode_extensions(_, _, _, Acc) ->
Acc.

assert_unique_extension(Ext, Map) ->
case maps:get(Ext, Map, undefined) of
undefined ->
ok;
_ ->
throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER, {duplicate_extension, Ext}))
end.

decode_sign_alg(?TLS_1_2, SignSchemeList) ->
%% Ignore unknown signature algorithms
Fun = fun(Elem) ->
Expand Down
Loading