diff options
author | Péter Dimitrov <[email protected]> | 2018-10-26 11:06:18 +0200 |
---|---|---|
committer | Péter Dimitrov <[email protected]> | 2018-11-01 15:52:57 +0100 |
commit | 29b555abdebc7ce2097679286ca94b176aa493b9 (patch) | |
tree | 8e6a4a76686d9a4da1b584fe0025a6aa551c1040 | |
parent | f3dfe10d8ee4a65362ef75803016b7b2e4368719 (diff) | |
download | otp-29b555abdebc7ce2097679286ca94b176aa493b9.tar.gz otp-29b555abdebc7ce2097679286ca94b176aa493b9.tar.bz2 otp-29b555abdebc7ce2097679286ca94b176aa493b9.zip |
ssl: Fix failing property tests
- Updated message generators:
ClientHello, ServerHello and EncryptedExtensions
- Fixed encoding of the extensions 'signature_algorithms' and
'signature_algorithms_cert'
- Updated empty extension definitions
Change-Id: I9415e2d022744b9ed4667d20aee2553637ed49f8
-rw-r--r-- | lib/ssl/src/ssl_handshake.erl | 105 | ||||
-rw-r--r-- | lib/ssl/src/ssl_handshake.hrl | 8 | ||||
-rw-r--r-- | lib/ssl/test/property_test/ssl_eqc_handshake.erl | 443 | ||||
-rw-r--r-- | lib/ssl/test/ssl_handshake_SUITE.erl | 6 |
4 files changed, 386 insertions, 176 deletions
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 1e812c92a8..da2e92a76b 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -75,7 +75,7 @@ handle_client_hello_extensions/9, %% Returns server hello extensions handle_server_hello_extensions/9, select_curve/2, select_curve/3, select_hashsign/4, select_hashsign/5, - select_hashsign_algs/3 + select_hashsign_algs/3, empty_extensions/2 ]). %%==================================================================== @@ -646,7 +646,15 @@ encode_extensions([#hash_sign_algos{hash_sign_algos = HashSignAlgos} | Rest], Ac Len = ListLen + 2, encode_extensions(Rest, <<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len), ?UINT16(ListLen), SignAlgoList/binary, Acc/binary>>); -encode_extensions([#signature_scheme_list{ +encode_extensions([#signature_algorithms{ + signature_scheme_list = SignatureSchemes} | Rest], Acc) -> + SignSchemeList = << <<(ssl_cipher:signature_scheme(SignatureScheme)):16 >> || + SignatureScheme <- SignatureSchemes >>, + ListLen = byte_size(SignSchemeList), + Len = ListLen + 2, + encode_extensions(Rest, <<?UINT16(?SIGNATURE_ALGORITHMS_EXT), + ?UINT16(Len), ?UINT16(ListLen), SignSchemeList/binary, Acc/binary>>); +encode_extensions([#signature_algorithms_cert{ signature_scheme_list = SignatureSchemes} | Rest], Acc) -> SignSchemeList = << <<(ssl_cipher:signature_scheme(SignatureScheme)):16 >> || SignatureScheme <- SignatureSchemes >>, @@ -711,7 +719,7 @@ decode_handshake(Version, ?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32 session_id = Session_ID, cipher_suite = Cipher_suite, compression_method = Comp_method, - extensions = empty_hello_extensions(Version, server)}; + extensions = empty_extensions(Version, server_hello)}; decode_handshake(Version, ?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary, ?BYTE(SID_length), Session_ID:SID_length/binary, @@ -780,7 +788,12 @@ decode_vector(<<?UINT16(Len), Vector:Len/binary>>) -> %% Description: Decodes TLS hello extensions %%-------------------------------------------------------------------- decode_hello_extensions(Extensions, Version, Role) -> - decode_extensions(Extensions, Version, empty_hello_extensions(Version, Role)). + MessageType = + case Role of + client -> client_hello; + server -> server_hello + end, + decode_extensions(Extensions, Version, empty_extensions(Version, MessageType)). %%-------------------------------------------------------------------- -spec decode_extensions(binary(),tuple()) -> map(). @@ -1049,14 +1062,14 @@ maybe_add_tls13_extensions({3,4}, HelloExtensions#{client_hello_versions => #client_hello_versions{versions = SupportedVersions}, signature_algs_cert => - signature_scheme_list(SignatureSchemes)}; + signature_algs_cert(SignatureSchemes)}; maybe_add_tls13_extensions(_, HelloExtensions, _) -> HelloExtensions. -signature_scheme_list(undefined) -> +signature_algs_cert(undefined) -> undefined; -signature_scheme_list(SignatureSchemes) -> - #signature_scheme_list{signature_scheme_list = SignatureSchemes}. +signature_algs_cert(SignatureSchemes) -> + #signature_algorithms_cert{signature_scheme_list = SignatureSchemes}. handle_client_hello_extensions(RecordCB, Random, ClientCipherSuites, Exts, Version, @@ -1071,7 +1084,7 @@ handle_client_hello_extensions(RecordCB, Random, ClientCipherSuites, ClientCipherSuites, Compression, ConnectionStates0, Renegotiation, SecureRenegotation), - Empty = empty_hello_extensions(Version, client), + Empty = empty_extensions(Version, server_hello), ServerHelloExtensions = Empty#{renegotiation_info => renegotiation_info(RecordCB, server, ConnectionStates, Renegotiation), ec_point_formats => server_ecc_extension(Version, maps:get(ec_point_formats, Exts, undefined)) @@ -1279,7 +1292,7 @@ get_cert_params(Cert) -> get_signature_scheme(undefined) -> undefined; -get_signature_scheme(#signature_scheme_list{ +get_signature_scheme(#signature_algorithms_cert{ signature_scheme_list = ClientSignatureSchemes}) -> ClientSignatureSchemes. @@ -2101,7 +2114,8 @@ decode_extensions(<<?UINT16(?SRP_EXT), ?UINT16(Len), ?BYTE(SRPLen), decode_extensions(Rest, Version, Acc#{srp => #srp{username = SRP}}); decode_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len), - ExtData:Len/binary, Rest/binary>>, Version, Acc) -> + ExtData:Len/binary, Rest/binary>>, Version, Acc) + when Version < {3,4} -> SignAlgoListLen = Len - 2, <<?UINT16(SignAlgoListLen), SignAlgoList/binary>> = ExtData, HashSignAlgos = [{ssl_cipher:hash_algorithm(Hash), ssl_cipher:sign_algorithm(Sign)} || @@ -2110,6 +2124,17 @@ decode_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len), #hash_sign_algos{hash_sign_algos = HashSignAlgos}}); +decode_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len), + ExtData:Len/binary, Rest/binary>>, Version, Acc) + when Version =:= {3,4} -> + SignSchemeListLen = Len - 2, + <<?UINT16(SignSchemeListLen), SignSchemeList/binary>> = ExtData, + SignSchemes = [ssl_cipher:signature_scheme(SignScheme) || + <<?UINT16(SignScheme)>> <= SignSchemeList], + decode_extensions(Rest, Version, Acc#{signature_algs => + #signature_algorithms{ + signature_scheme_list = SignSchemes}}); + decode_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_CERT_EXT), ?UINT16(Len), ExtData:Len/binary, Rest/binary>>, Version, Acc) -> SignSchemeListLen = Len - 2, @@ -2117,7 +2142,7 @@ decode_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_CERT_EXT), ?UINT16(Len), SignSchemes = [ssl_cipher:signature_scheme(SignScheme) || <<?UINT16(SignScheme)>> <= SignSchemeList], decode_extensions(Rest, Version, Acc#{signature_algs_cert => - #signature_scheme_list{ + #signature_algorithms_cert{ signature_scheme_list = SignSchemes}}); decode_extensions(<<?UINT16(?ELLIPTIC_CURVES_EXT), ?UINT16(Len), @@ -2756,27 +2781,37 @@ cert_curve(Cert, ECCCurve0, CipherSuite) -> {ECCCurve0, CipherSuite} end. -empty_hello_extensions({3, 4}, server) -> - #{server_hello_selected_version => undefined, - key_share => undefined, - pre_shared_key => undefined, - sni => undefined - }; -empty_hello_extensions({3, 4}, client) -> - #{client_hello_versions => undefined, - signature_algs => undefined, - signature_algs_cert => undefined, +empty_extensions() -> + #{}. + +empty_extensions({3,4}, client_hello) -> + #{ sni => undefined, + %% max_fragment_length => undefined, + %% status_request => undefined, + elliptic_curves => undefined, + signature_algs => undefined, + %% use_srtp => undefined, + %% heartbeat => undefined, alpn => undefined, + %% signed_cert_timestamp => undefined, + %% client_cert_type => undefined, + %% server_cert_type => undefined, + %% padding => undefined, key_share => undefined, - pre_shared_key => undefined + pre_shared_key => undefined, + %% psk_key_exhange_modes => undefined, + %% early_data => undefined, + %% cookie => undefined, + client_hello_versions => undefined, + %% cert_authorities => undefined, + %% post_handshake_auth => undefined, + signature_algs_cert => undefined }; -empty_hello_extensions({3, 3}, client) -> - Ext = empty_hello_extensions({3,2}, client), - Ext#{client_hello_versions => undefined, - signature_algs => undefined, - signature_algs_cert => undefined}; -empty_hello_extensions(_, client) -> +empty_extensions({3, 3}, client_hello) -> + Ext = empty_extensions({3,2}, client_hello), + Ext#{signature_algs => undefined}; +empty_extensions(_, client_hello) -> #{renegotiation_info => undefined, alpn => undefined, next_protocol_negotiation => undefined, @@ -2784,11 +2819,13 @@ empty_hello_extensions(_, client) -> ec_point_formats => undefined, elliptic_curves => undefined, sni => undefined}; -empty_hello_extensions(_, server) -> +empty_extensions({3,4}, server_hello) -> + #{server_hello_selected_version => undefined, + key_share => undefined, + pre_shared_key => undefined + }; +empty_extensions(_, server_hello) -> #{renegotiation_info => undefined, alpn => undefined, next_protocol_negotiation => undefined, - ec_point_formats => undefined, - sni => undefined}. -empty_extensions() -> - #{}. + ec_point_formats => undefined}. diff --git a/lib/ssl/src/ssl_handshake.hrl b/lib/ssl/src/ssl_handshake.hrl index 4336742e76..1fd143a641 100644 --- a/lib/ssl/src/ssl_handshake.hrl +++ b/lib/ssl/src/ssl_handshake.hrl @@ -315,9 +315,9 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -define(SIGNATURE_ALGORITHMS_EXT, 13). --record(hash_sign_algos, { - hash_sign_algos - }). +-record(hash_sign_algos, {hash_sign_algos}). +%% RFC 8446 (TLS 1.3) +-record(signature_algorithms, {signature_scheme_list}). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% RFC 7301 Application-Layer Protocol Negotiation @@ -436,6 +436,6 @@ -define(SIGNATURE_ALGORITHMS_CERT_EXT, 50). --record(signature_scheme_list, {signature_scheme_list}). +-record(signature_algorithms_cert, {signature_scheme_list}). -endif. % -ifdef(ssl_handshake). diff --git a/lib/ssl/test/property_test/ssl_eqc_handshake.erl b/lib/ssl/test/property_test/ssl_eqc_handshake.erl index 99c6554f15..8b3b81aaf1 100644 --- a/lib/ssl/test/property_test/ssl_eqc_handshake.erl +++ b/lib/ssl/test/property_test/ssl_eqc_handshake.erl @@ -85,17 +85,14 @@ prop_tls_hs_encode_decode() -> ). %%-------------------------------------------------------------------- -%% Message Generators -------------------------------------------------- +%% Message Generators ----------------------------------------------- %%-------------------------------------------------------------------- -tls_version() -> - oneof([?'TLS_v1.3', ?'TLS_v1.2', ?'TLS_v1.1', ?'TLS_v1', ?'SSL_v3']). - tls_msg(?'TLS_v1.3'= Version) -> oneof([client_hello(Version), server_hello(Version), %%new_session_ticket() - #end_of_early_data{}, + #end_of_early_data{}, encrypted_extensions(), certificate_1_3(), %%certificate_request_1_3, @@ -104,7 +101,8 @@ tls_msg(?'TLS_v1.3'= Version) -> key_update() ]); tls_msg(Version) -> - oneof([#hello_request{}, + oneof([ + #hello_request{}, client_hello(Version), server_hello(Version), certificate(), @@ -116,6 +114,9 @@ tls_msg(Version) -> finished() ]). +%% +%% Shared messages +%% client_hello(?'TLS_v1.3' = Version) -> #client_hello{session_id = session_id(), client_version = ?'TLS_v1.2', @@ -150,10 +151,6 @@ server_hello(Version) -> extensions = server_hello_extensions(Version) }. -encrypted_extensions() -> - ?LET(Exts, extensions(?'TLS_v1.3'), - #encrypted_extensions{extensions = Exts}). - certificate() -> #certificate{ asn1_certificates = certificate_chain() @@ -166,17 +163,35 @@ certificate_1_3() -> entries = certificate_entries(Certs, []) }). -key_update() -> - #key_update{request_update = request_update()}. - finished() -> ?LET(Size, digest_size(), #finished{verify_data = crypto:strong_rand_bytes(Size)}). +%% +%% TLS 1.0-1.2 messages +%% + + + +%% +%% TLS 1.3 messages +%% + +encrypted_extensions() -> + ?LET(Exts, extensions(?'TLS_v1.3', encrypted_extensions), + #encrypted_extensions{extensions = Exts}). + + +key_update() -> + #key_update{request_update = request_update()}. + + %%-------------------------------------------------------------------- %% Messge Data Generators ------------------------------------------- %%-------------------------------------------------------------------- +tls_version() -> + oneof([?'TLS_v1.3', ?'TLS_v1.2', ?'TLS_v1.1', ?'TLS_v1', ?'SSL_v3']). cipher_suite(Version) -> oneof(cipher_suites(Version)). @@ -200,52 +215,14 @@ server_random(_) -> crypto:strong_rand_bytes(32). -client_hello_extensions(?'TLS_v1.3' = Version) -> - ?LET({Versions, Ext}, {supported_versions(Version), c_hello_extensions(Version)}, - maps:merge(Ext, #{client_hello_versions => client_hello_versions(Versions)}) - ); -client_hello_extensions(?'TLS_v1.2' = Version) -> - ?LET({Versions, Exts}, {supported_versions(Version), c_hello_extensions(Version)}, - maps:merge(Exts, #{client_hello_versions => client_hello_versions(Versions)}) - ); client_hello_extensions(Version) -> - ?LET(Exts, - c_hello_extensions(Version), - maps:merge(empty_hello_extensions(Version, client), Exts)). - -server_hello_extensions(?'TLS_v1.3' = Version) -> - ?LET(Exts, - s_hello_extensions(Version), - maps:merge(Exts, #{server_hello_selected_version => server_hello_selected_version(Version)})); -server_hello_extensions(Version) -> - ?LET(Exts, - s_hello_extensions(Version), - Exts). - -c_hello_extensions(?'TLS_v1.3'= Version) -> - ?LET({KeyShare, PreShare}, {key_share_client_hello(), - pre_shared_keyextension()}, - maps:merge(empty_hello_extensions(Version, client), - #{key_share => KeyShare, - pre_shared_key => PreShare - }) - ); -c_hello_extensions(Version) -> - ?LET(Exts, extensions(Version), - maps:merge(empty_hello_extensions(Version, client), + ?LET(Exts, extensions(Version, client_hello), + maps:merge(ssl_handshake:empty_extensions(Version, client_hello), Exts)). -s_hello_extensions(?'TLS_v1.3'= Version) -> - ?LET({KeyShare, PreShare}, {key_share_server_hello(), - pre_shared_keyextension()}, - maps:merge(empty_hello_extensions(Version, server), - #{key_share => KeyShare, - pre_shared_key => PreShare - }) - ); -s_hello_extensions(Version) -> - ?LET(Exts, extensions(Version), - maps:merge(empty_hello_extensions(Version, server), +server_hello_extensions(Version) -> + ?LET(Exts, extensions(Version, server_hello), + maps:merge(ssl_handshake:empty_extensions(Version, server_hello), Exts)). key_share_client_hello() -> @@ -260,83 +237,260 @@ pre_shared_keyextension() -> oneof([undefined]). %%oneof([#pre_shared_keyextension{},undefined]). -extensions(?'TLS_v1.3') -> - ?LET({Ext_1_3, Exts}, {extensions_1_3(), extensions(?'TLS_v1.2')}, maps:merge(Ext_1_3, Exts)); -extensions(?'SSL_v3') -> +%% +--------------------------------------------------+-------------+ +%% | Extension | TLS 1.3 | +%% +--------------------------------------------------+-------------+ +%% | server_name [RFC6066] | CH, EE | +%% | | | +%% | max_fragment_length [RFC6066] | CH, EE | +%% | | | +%% | status_request [RFC6066] | CH, CR, CT | +%% | | | +%% | supported_groups [RFC7919] | CH, EE | +%% | | | +%% | signature_algorithms (RFC 8446) | CH, CR | +%% | | | +%% | use_srtp [RFC5764] | CH, EE | +%% | | | +%% | heartbeat [RFC6520] | CH, EE | +%% | | | +%% | application_layer_protocol_negotiation [RFC7301] | CH, EE | +%% | | | +%% | signed_certificate_timestamp [RFC6962] | CH, CR, CT | +%% | | | +%% | client_certificate_type [RFC7250] | CH, EE | +%% | | | +%% | server_certificate_type [RFC7250] | CH, EE | +%% | | | +%% | padding [RFC7685] | CH | +%% | | | +%% | key_share (RFC 8446) | CH, SH, HRR | +%% | | | +%% | pre_shared_key (RFC 8446) | CH, SH | +%% | | | +%% | psk_key_exchange_modes (RFC 8446) | CH | +%% | | | +%% | early_data (RFC 8446) | CH, EE, NST | +%% | | | +%% | cookie (RFC 8446) | CH, HRR | +%% | | | +%% | supported_versions (RFC 8446) | CH, SH, HRR | +%% | | | +%% | certificate_authorities (RFC 8446) | CH, CR | +%% | | | +%% | oid_filters (RFC 8446) | CR | +%% | | | +%% | post_handshake_auth (RFC 8446) | CH | +%% | | | +%% | signature_algorithms_cert (RFC 8446) | CH, CR | +%% +--------------------------------------------------+-------------+ +extensions(?'TLS_v1.3' = Version, client_hello) -> + ?LET({ + ServerName, + %% MaxFragmentLength, + %% StatusRequest, + SupportedGroups, + SignatureAlgorithms, + %% UseSrtp, + %% Heartbeat, + ALPN, + %% SignedCertTimestamp, + %% ClientCertiticateType, + %% ServerCertificateType, + %% Padding, + %% KeyShare, + %% PreSharedKey, + %% PSKKeyExchangeModes, + %% EarlyData, + %% Cookie, + SupportedVersions, + %% CertAuthorities, + %% PostHandshakeAuth, + SignatureAlgorithmsCert + }, + { + oneof([server_name(), undefined]), + %% oneof([max_fragment_length(), undefined]), + %% oneof([status_request(), undefined]), + oneof([supported_groups(Version), undefined]), + oneof([signature_algs(Version), undefined]), + %% oneof([use_srtp(), undefined]), + %% oneof([heartbeat(), undefined]), + oneof([alpn(), undefined]), + %% oneof([signed_cert_timestamp(), undefined]), + %% oneof([client_cert_type(), undefined]), + %% oneof([server_cert_type(), undefined]), + %% oneof([padding(), undefined]), + %% oneof([key_share(), undefined]), + %% oneof([pre_shared_key(), undefined]), + %% oneof([psk_key_exchange_modes(), undefined]), + %% oneof([early_data(), undefined]), + %% oneof([cookie(), undefined]), + oneof([client_hello_versions(Version), undefined]), + %% oneof([cert_authorities(), undefined]), + %% oneof([post_handshake_auth(), undefined]), + oneof([signature_algs_cert(), undefined]) + }, + maps:filter(fun(_, undefined) -> + false; + (_,_) -> + true + end, + #{ + sni => ServerName, + %% max_fragment_length => MaxFragmentLength, + %% status_request => StatusRequest, + elliptic_curves => SupportedGroups, + signature_algs => SignatureAlgorithms, + %% use_srtp => UseSrtp, + %% heartbeat => Heartbeat, + alpn => ALPN, + %% signed_cert_timestamp => SignedCertTimestamp, + %% client_cert_type => ClientCertificateType, + %% server_cert_type => ServerCertificateType, + %% padding => Padding, + %% key_share => KeyShare, + %% pre_shared_key => PreSharedKey, + %% psk_key_exhange_modes => PSKKeyExchangeModes, + %% early_data => EarlyData, + %% cookie => Cookie, + client_hello_versions => SupportedVersions, + %% cert_authorities => CertAuthorities, + %% post_handshake_auth => PostHandshakeAuth, + signature_algs_cert => SignatureAlgorithmsCert + })); +extensions(?'SSL_v3', client_hello) -> #{}; -extensions(Version) -> - ?LET({SNI, ECPoitF, ECCurves, ALPN, NextP, SRP}, - {oneof([sni(), undefined]), - oneof([ec_poit_formats(), undefined]), +extensions(Version, client_hello) -> + ?LET({ + SNI, + ECPoitF, + ECCurves, + ALPN, + NextP, + SRP + %% RenegotiationInfo + }, + { + oneof([sni(), undefined]), + oneof([ec_point_formats(), undefined]), oneof([elliptic_curves(Version), undefined]), oneof([alpn(), undefined]), oneof([next_protocol_negotiation(), undefined]), - oneof([srp(), undefined])}, + oneof([srp(), undefined]) + %% oneof([renegotiation_info(), undefined]) + }, maps:filter(fun(_, undefined) -> false; (_,_) -> true end, - #{sni => SNI, + #{ + sni => SNI, ec_point_formats => ECPoitF, elliptic_curves => ECCurves, alpn => ALPN, next_protocol_negotiation => NextP, - srp => SRP})). - -extensions_1_3() -> - %% ?LET(Entry, key_share_entry(), - %% maps:filter(fun(_, undefined) -> - %% false; - %% (_,_) -> - %% true - %% end, #{key_share_entry => Entry})). - ?LET({HashSign, SigAlgCert}, {oneof([hash_sign_algos(?'TLS_v1.2')]), oneof([signature_scheme_list()])}, - #{signature_algs => HashSign, - signature_algs_cert => SigAlgCert}). - -empty_hello_extensions({3, 4}, server) -> - #{server_hello_selected_version => undefined, - key_share => undefined, - pre_shared_key => undefined, - sni => undefined - }; -empty_hello_extensions({3, 4}, client) -> - #{client_hello_versions => undefined, - signature_algs => undefined, - signature_algs_cert => undefined, - sni => undefined, - alpn => undefined, - key_share => undefined, - pre_shared_key => undefined - }; -empty_hello_extensions({3, 3}, client) -> - Ext = empty_hello_extensions({3,2}, client), - Ext#{client_hello_versions => undefined, - signature_algs => undefined, - signature_algs_cert => undefined}; -empty_hello_extensions(_, client) -> - #{renegotiation_info => undefined, - alpn => undefined, - next_protocol_negotiation => undefined, - srp => undefined, - ec_point_formats => undefined, - elliptic_curves => undefined, - sni => undefined}; -empty_hello_extensions(_, server) -> - #{renegotiation_info => undefined, - alpn => undefined, - next_protocol_negotiation => undefined, - ec_point_formats => undefined, - sni => undefined}. + srp => SRP + %% renegotiation_info => RenegotiationInfo + })); +extensions(?'TLS_v1.3' = Version, server_hello) -> + ?LET({ + %% KeyShare, + %% PreSharedKeys, + SupportedVersions + }, + { + %% oneof([key_share(), undefined]), + %% oneof([pre_shared_keys(), undefined]), + oneof([server_hello_selected_version(), undefined]) + }, + maps:filter(fun(_, undefined) -> + false; + (_,_) -> + true + end, + #{ + %% key_share => KeyShare, + %% pre_shared_keys => PreSharedKeys, + server_hello_selected_version => SupportedVersions + })); +extensions(Version, server_hello) -> + ?LET({ + ECPoitF, + ALPN, + NextP + %% RenegotiationInfo, + }, + { + oneof([ec_point_formats(), undefined]), + oneof([alpn(), undefined]), + oneof([next_protocol_negotiation(), undefined]) + %% oneof([renegotiation_info(), undefined]), + }, + maps:filter(fun(_, undefined) -> + false; + (_,_) -> + true + end, + #{ + ec_point_formats => ECPoitF, + alpn => ALPN, + next_protocol_negotiation => NextP + %% renegotiation_info => RenegotiationInfo + })); +extensions(?'TLS_v1.3' = Version, encrypted_extensions) -> + ?LET({ + ServerName, + %% MaxFragmentLength, + SupportedGroups, + %% UseSrtp, + %% Heartbeat, + ALPN + %% ClientCertiticateType, + %% ServerCertificateType, + %% EarlyData + }, + { + oneof([server_name(), undefined]), + %% oneof([max_fragment_length(), undefined]), + oneof([supported_groups(Version), undefined]), + %% oneof([use_srtp(), undefined]), + %% oneof([heartbeat(), undefined]), + oneof([alpn(), undefined]) + %% oneof([client_cert_type(), undefined]), + %% oneof([server_cert_type(), undefined]), + %% oneof([early_data(), undefined]) + }, + maps:filter(fun(_, undefined) -> + false; + (_,_) -> + true + end, + #{ + sni => ServerName, + %% max_fragment_length => MaxFragmentLength, + elliptic_curves => SupportedGroups, + %% use_srtp => UseSrtp, + %% heartbeat => Heartbeat, + alpn => ALPN + %% client_cert_type => ClientCertificateType, + %% server_cert_type => ServerCertificateType, + %% early_data => EarlyData + })). + +server_name() -> + ?LET(ServerName, sni(), + ServerName). + %% sni(). signature_algs_cert() -> - ?LET(Algs, signature_scheme_list(), - Algs). + ?LET(List, sig_scheme_list(), + #signature_algorithms_cert{signature_scheme_list = List}). -signature_scheme_list() -> +signature_algorithms() -> ?LET(List, sig_scheme_list(), - #signature_scheme_list{signature_scheme_list = List}). + #signature_algorithms{signature_scheme_list = List}). sig_scheme_list() -> oneof([[rsa_pkcs1_sha256], @@ -357,16 +511,23 @@ sig_scheme_list() -> ecdsa_sha1] ]). -supported_versions(?'TLS_v1.3') -> - oneof([[{3,4}], - [{3,3},{3,4}], - [{3,4},{3,3},{3,2},{3,1},{3,0}] - ]); -supported_versions(_) -> - oneof([[{3,3}], - [{3,3},{3,2}], - [{3,3},{3,2},{3,1},{3,0}] - ]). +client_hello_versions(?'TLS_v1.3') -> + ?LET(SupportedVersions, + oneof([[{3,4}], + [{3,3},{3,4}], + [{3,4},{3,3},{3,2},{3,1},{3,0}] + ]), + #client_hello_versions{versions = SupportedVersions}); +client_hello_versions(_) -> + ?LET(SupportedVersions, + oneof([[{3,3}], + [{3,3},{3,2}], + [{3,3},{3,2},{3,1},{3,0}] + ]), + #client_hello_versions{versions = SupportedVersions}). + +server_hello_selected_version() -> + #server_hello_selected_version{selected_version = {3,4}}. request_update() -> oneof([?UPDATE_NOT_REQUESTED, ?UPDATE_REQUESTED]). @@ -431,13 +592,25 @@ certificate_types(?'TLS_v1.2') -> certificate_types(_) -> iolist_to_binary([<<?BYTE(?ECDSA_SIGN)>>, <<?BYTE(?RSA_SIGN)>>, <<?BYTE(?DSS_SIGN)>>]). + + +signature_algs({3,4}) -> + ?LET(Algs, signature_algorithms(), + Algs); +signature_algs({3,3} = Version) -> + #hash_sign_algos{hash_sign_algos = hash_alg_list(Version)}; +signature_algs(Version) when Version < {3,3} -> + undefined. + + + hashsign_algorithms({_, N} = Version) when N >= 3 -> #hash_sign_algos{hash_sign_algos = hash_alg_list(Version)}; hashsign_algorithms(_) -> undefined. hash_alg_list(Version) -> - ?LET(NumOf, choose(0,15), + ?LET(NumOf, choose(1,15), ?LET(List, [hash_alg(Version) || _ <- lists:seq(1,NumOf)], lists:usort(List) )). @@ -481,27 +654,27 @@ key_share_entry() -> undefined. %%#key_share_entry{}. -client_hello_versions(Versions) -> - #client_hello_versions{versions = Versions}. - server_hello_selected_version(Version) -> #server_hello_selected_version{selected_version = Version}. sni() -> #sni{hostname = net_adm:localhost()}. -ec_poit_formats() -> +ec_point_formats() -> #ec_point_formats{ec_point_format_list = ec_point_format_list()}. ec_point_format_list() -> [?ECPOINT_UNCOMPRESSED]. -elliptic_curves({_, Minor}) -> +elliptic_curves({_, Minor}) when Minor < 4 -> Curves = tls_v1:ecc_curves(Minor), #elliptic_curves{elliptic_curve_list = Curves}. -hash_sign_algos(Version) -> - #hash_sign_algos{hash_sign_algos = hash_alg_list(Version)}. +%% RFC 8446 (TLS 1.3) renamed the "elliptic_curve" extension. +supported_groups({_, Minor}) when Minor >= 4 -> + SupportedGroups = tls_v1:groups(Minor), + #supported_groups{supported_groups = SupportedGroups}. + alpn() -> ?LET(ExtD, alpn_protocols(), #alpn{extension_data = ExtD}). @@ -520,7 +693,7 @@ renegotiation_info() -> #renegotiation_info{renegotiated_connection = 0}. gen_name() -> - ?LET(Size, choose(0,10), gen_string(Size)). + ?LET(Size, choose(1,10), gen_string(Size)). gen_char() -> choose($a,$z). diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl index 861fecc554..c35ee6cb57 100644 --- a/lib/ssl/test/ssl_handshake_SUITE.erl +++ b/lib/ssl/test/ssl_handshake_SUITE.erl @@ -112,7 +112,7 @@ decode_hello_handshake(_Config) -> decode_single_hello_extension_correctly(_Config) -> Renegotiation = <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(1), 0>>, - Extensions = ssl_handshake:decode_extensions(Renegotiation), + Extensions = ssl_handshake:decode_extensions(Renegotiation, {3,3}), #{renegotiation_info := #renegotiation_info{renegotiated_connection = <<0>>}} = Extensions. decode_supported_elliptic_curves_hello_extension_correctly(_Config) -> @@ -200,7 +200,7 @@ signature_algorithms(Config) -> hash_sign_algos = [{sha512, rsa}, {sha, dsa}, {sha, rsa}]}, - Schemes0 = #signature_scheme_list{ + Schemes0 = #signature_algorithms_cert{ signature_scheme_list = [rsa_pkcs1_sha1, ecdsa_sha1]}, {sha512, rsa} = ssl_handshake:select_hashsign( @@ -216,7 +216,7 @@ signature_algorithms(Config) -> Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,3}), {3,3}), - Schemes1 = #signature_scheme_list{ + Schemes1 = #signature_algorithms_cert{ signature_scheme_list = [rsa_pkcs1_sha256, ecdsa_sha1]}, %% Signature not supported |