diff options
author | Ingela Anderton Andin <[email protected]> | 2013-08-14 15:31:21 +0200 |
---|---|---|
committer | Ingela Anderton Andin <[email protected]> | 2013-09-02 09:39:11 +0200 |
commit | c2045419346ea46f3f8ad89dfedd5169adb7c9c4 (patch) | |
tree | 3416061249fc7237d7de68ae73cf2978f7bddbe8 /lib/ssl/src | |
parent | 63a3de06cfc02762ff933bf34ec2a4307f51749b (diff) | |
download | otp-c2045419346ea46f3f8ad89dfedd5169adb7c9c4.tar.gz otp-c2045419346ea46f3f8ad89dfedd5169adb7c9c4.tar.bz2 otp-c2045419346ea46f3f8ad89dfedd5169adb7c9c4.zip |
ssl: Handle signature_algorithm field in digitally_signed properly
with proper defaults
Added ssl_ECC_SUITE
Diffstat (limited to 'lib/ssl/src')
-rw-r--r-- | lib/ssl/src/ssl_cipher.erl | 21 | ||||
-rw-r--r-- | lib/ssl/src/tls_connection.erl | 121 | ||||
-rw-r--r-- | lib/ssl/src/tls_handshake.erl | 86 |
3 files changed, 154 insertions, 74 deletions
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl index ec5d793d65..09aad8e414 100644 --- a/lib/ssl/src/ssl_cipher.erl +++ b/lib/ssl/src/ssl_cipher.erl @@ -36,7 +36,7 @@ decipher/5, cipher/5, suite/1, suites/1, anonymous_suites/0, psk_suites/1, srp_suites/0, openssl_suite/1, openssl_suite_name/1, filter/2, filter_suites/1, - hash_algorithm/1, sign_algorithm/1]). + hash_algorithm/1, sign_algorithm/1, is_acceptable_hash/2]). -compile(inline). @@ -1009,6 +1009,7 @@ filter(DerCert, Ciphers) -> filter_keyuse(OtpCert, (Ciphers -- rsa_keyed_suites()) -- dsa_signed_suites(), [], ecdhe_ecdsa_suites()) end, + case public_key:pkix_sign_types(SigAlg#'SignatureAlgorithm'.algorithm) of {_, rsa} -> Ciphers1 -- ecdsa_signed_suites(); @@ -1191,15 +1192,15 @@ hash_size(md5) -> hash_size(sha) -> 20; %% Uncomment when adding cipher suite that needs it -%% hash_size(sha224) -> -%% 28; +hash_size(sha224) -> + 28; hash_size(sha256) -> 32; hash_size(sha384) -> - 48. + 48; %% Uncomment when adding cipher suite that needs it -%% hash_size(sha512) -> -%% 64. +hash_size(sha512) -> + 64. %% RFC 5246: 6.2.3.2. CBC Block Cipher %% @@ -1259,15 +1260,15 @@ generic_stream_cipher_from_bin(T, HashSz) -> %% SSL 3.0 and TLS 1.0 as it is not strictly required and breaks %% interopability with for instance Google. is_correct_padding(#generic_block_cipher{padding_length = Len, - padding = Padding}, {3, N}) + padding = Padding}, {3, N}) when N == 0; N == 1 -> Len == byte_size(Padding); %% Padding must be check in TLS 1.1 and after is_correct_padding(#generic_block_cipher{padding_length = Len, - padding = Padding}, _) -> + padding = Padding}, _) -> Len == byte_size(Padding) andalso list_to_binary(lists:duplicate(Len, Len)) == Padding. - + get_padding(Length, BlockSize) -> get_padding_aux(BlockSize, Length rem BlockSize). @@ -1291,7 +1292,7 @@ next_iv(Bin, IV) -> rsa_signed_suites() -> dhe_rsa_suites() ++ rsa_suites() ++ psk_rsa_suites() ++ srp_rsa_suites() ++ - ecdh_rsa_suites(). + ecdh_rsa_suites() ++ ecdhe_rsa_suites(). rsa_keyed_suites() -> dhe_rsa_suites() ++ rsa_suites() ++ diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 77f49c5d2a..0415ea6ecc 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -76,7 +76,8 @@ negotiated_version, % tls_version() client_certificate_requested = false, key_algorithm, % atom as defined by cipher_suite - hashsign_algorithm, % atom as defined by cipher_suite + hashsign_algorithm = {undefined, undefined}, + cert_hashsign_algorithm, public_key_info, % PKIX: {Algorithm, PublicKey, PublicKeyParams} private_key, % PKIX: #'RSAPrivateKey'{} diffie_hellman_params, % PKIX: #'DHParameter'{} relevant for server side @@ -366,6 +367,7 @@ hello(#hello_request{}, #state{role = client} = State0) -> next_state(hello, hello, Record, State); hello(#server_hello{cipher_suite = CipherSuite, + hash_signs = HashSign, compression_method = Compression} = Hello, #state{session = #session{session_id = OldId}, connection_states = ConnectionStates0, @@ -388,9 +390,10 @@ hello(#server_hello{cipher_suite = CipherSuite, _ -> NextProtocol end, - + State = State0#state{key_algorithm = KeyAlgorithm, - hashsign_algorithm = default_hashsign(Version, KeyAlgorithm), + hashsign_algorithm = + negotiated_hashsign(HashSign, KeyAlgorithm, Version), negotiated_version = Version, connection_states = ConnectionStates, premaster_secret = PremasterSecret, @@ -406,22 +409,28 @@ hello(#server_hello{cipher_suite = CipherSuite, end end; -hello(Hello = #client_hello{client_version = ClientVersion}, +hello(Hello = #client_hello{client_version = ClientVersion, + hash_signs = HashSigns}, State = #state{connection_states = ConnectionStates0, port = Port, session = #session{own_certificate = Cert} = Session0, renegotiation = {Renegotiation, _}, session_cache = Cache, session_cache_cb = CacheCb, ssl_options = SslOpts}) -> + + HashSign = tls_handshake:select_hashsign(HashSigns, Cert), case tls_handshake:hello(Hello, SslOpts, {Port, Session0, Cache, CacheCb, ConnectionStates0, Cert}, Renegotiation) of - {Version, {Type, Session}, ConnectionStates, ProtocolsToAdvertise, + {Version, {Type, #session{cipher_suite = CipherSuite} = Session}, ConnectionStates, ProtocolsToAdvertise, EcPointFormats, EllipticCurves} -> + {KeyAlgorithm, _, _, _} = ssl_cipher:suite_definition(CipherSuite), + NH = negotiated_hashsign(HashSign, KeyAlgorithm, Version), do_server_hello(Type, ProtocolsToAdvertise, EcPointFormats, EllipticCurves, State#state{connection_states = ConnectionStates, negotiated_version = Version, session = Session, + hashsign_algorithm = NH, client_ecc = {EllipticCurves, EcPointFormats}}); #alert{} = Alert -> handle_own_alert(Alert, ClientVersion, hello, State) @@ -526,7 +535,7 @@ certify(#certificate{} = Cert, Opts#ssl_options.verify, Opts#ssl_options.verify_fun, Role) of {PeerCert, PublicKeyInfo} -> - handle_peer_cert(PeerCert, PublicKeyInfo, + handle_peer_cert(Role, PeerCert, PublicKeyInfo, State#state{client_certificate_requested = false}); #alert{} = Alert -> handle_own_alert(Alert, Version, certify, State) @@ -552,9 +561,11 @@ certify(#server_key_exchange{} = Msg, #state{role = client, key_algorithm = rsa} = State) -> handle_unexpected_message(Msg, certify_server_keyexchange, State); -certify(#certificate_request{}, State0) -> +certify(#certificate_request{hashsign_algorithms = HashSigns}, + #state{session = #session{own_certificate = Cert}} = State0) -> + HashSign = tls_handshake:select_hashsign(HashSigns, Cert), {Record, State} = next_record(State0#state{client_certificate_requested = true}), - next_state(certify, certify, Record, State); + next_state(certify, certify, Record, State#state{cert_hashsign_algorithm = HashSign}); %% PSK and RSA_PSK might bypass the Server-Key-Exchange certify(#server_hello_done{}, @@ -757,21 +768,18 @@ cipher(#hello_request{}, State0) -> cipher(#certificate_verify{signature = Signature, hashsign_algorithm = CertHashSign}, #state{role = server, - public_key_info = PublicKeyInfo, + public_key_info = {Algo, _, _} =PublicKeyInfo, negotiated_version = Version, session = #session{master_secret = MasterSecret}, - hashsign_algorithm = ConnectionHashSign, tls_handshake_history = Handshake } = State0) -> - HashSign = case CertHashSign of - {_, _} -> CertHashSign; - _ -> ConnectionHashSign - end, + + HashSign = tls_handshake:select_cert_hashsign(CertHashSign, Algo, Version), case tls_handshake:certificate_verify(Signature, PublicKeyInfo, Version, HashSign, MasterSecret, Handshake) of valid -> {Record, State} = next_record(State0), - next_state(cipher, cipher, Record, State); + next_state(cipher, cipher, Record, State#state{cert_hashsign_algorithm = HashSign}); #alert{} = Alert -> handle_own_alert(Alert, Version, cipher, State0) end; @@ -1369,25 +1377,34 @@ sync_send_all_state_event(FsmPid, Event) -> {error, closed} end. -%% We do currently not support cipher suites that use fixed DH. -%% If we want to implement that we should add a code -%% here to extract DH parameters form cert. -handle_peer_cert(PeerCert, PublicKeyInfo, - #state{session = Session} = State0) -> +handle_peer_cert(Role, PeerCert, PublicKeyInfo, + #state{session = #session{cipher_suite = CipherSuite} = Session} = State0) -> State1 = State0#state{session = Session#session{peer_certificate = PeerCert}, public_key_info = PublicKeyInfo}, - State2 = case PublicKeyInfo of - {?'id-ecPublicKey', #'ECPoint'{point = _ECPoint} = PublicKey, PublicKeyParams} -> - ECDHKey = public_key:generate_key(PublicKeyParams), - State3 = State1#state{diffie_hellman_keys = ECDHKey}, - ec_dh_master_secret(ECDHKey, PublicKey, State3); - - _ -> State1 - end, + {KeyAlg,_,_,_} = ssl_cipher:suite_definition(CipherSuite), + State2 = handle_peer_cert_key(Role, PeerCert, PublicKeyInfo, KeyAlg, State1), + {Record, State} = next_record(State2), next_state(certify, certify, Record, State). +handle_peer_cert_key(client, _, + {?'id-ecPublicKey', #'ECPoint'{point = _ECPoint} = PublicKey, PublicKeyParams}, + KeyAlg, State) when KeyAlg == ecdh_rsa; + KeyAlg == ecdh_ecdsa -> + ECDHKey = public_key:generate_key(PublicKeyParams), + ec_dh_master_secret(ECDHKey, PublicKey, State#state{diffie_hellman_keys = ECDHKey}); + +%% We do currently not support cipher suites that use fixed DH. +%% If we want to implement that the following clause can be used +%% to extract DH parameters form cert. +%% handle_peer_cert_key(client, _PeerCert, {?dhpublicnumber, PublicKey, PublicKeyParams}, {_,SignAlg}, +%% #state{diffie_hellman_keys = {_, MyPrivatKey}} = State) when SignAlg == dh_rsa; +%% SignAlg == dh_dss -> +%% dh_master_secret(PublicKeyParams, PublicKey, MyPrivatKey, State); +handle_peer_cert_key(_, _, _, _, State) -> + State. + certify_client(#state{client_certificate_requested = true, role = client, connection_states = ConnectionStates0, transport_cb = Transport, @@ -1414,10 +1431,9 @@ verify_client_cert(#state{client_certificate_requested = true, role = client, private_key = PrivateKey, session = #session{master_secret = MasterSecret, own_certificate = OwnCert}, - hashsign_algorithm = HashSign, + cert_hashsign_algorithm = HashSign, tls_handshake_history = Handshake0} = State) -> - %%TODO: for TLS 1.2 we can choose a different/stronger HashSign combination for this. case tls_handshake:client_certificate_verify(OwnCert, MasterSecret, Version, HashSign, PrivateKey, Handshake0) of #certificate_verify{} = Verified -> @@ -1560,8 +1576,7 @@ server_hello(ServerHello, #state{transport_cb = Transport, Transport:send(Socket, BinMsg), State#state{connection_states = ConnectionStates1, tls_handshake_history = Handshake1, - key_algorithm = KeyAlgorithm, - hashsign_algorithm = default_hashsign(Version, KeyAlgorithm)}. + key_algorithm = KeyAlgorithm}. server_hello_done(#state{transport_cb = Transport, socket = Socket, @@ -1937,7 +1952,7 @@ request_client_cert(#state{ssl_options = #ssl_options{verify = verify_peer}, negotiated_version = Version, socket = Socket, transport_cb = Transport} = State) -> - Msg = tls_handshake:certificate_request(ConnectionStates0, CertDbHandle, CertDbRef), + Msg = tls_handshake:certificate_request(ConnectionStates0, CertDbHandle, CertDbRef, Version), {BinMsg, ConnectionStates, Handshake} = encode_handshake(Msg, Version, ConnectionStates0, Handshake0), Transport:send(Socket, BinMsg), @@ -2014,12 +2029,13 @@ handle_server_key(#server_key_exchange{exchange_keys = Keys}, #state{key_algorithm = KeyAlg, negotiated_version = Version} = State) -> Params = tls_handshake:decode_server_key(Keys, KeyAlg, Version), - HashSign = connection_hashsign(Params#server_key_params.hashsign, State), - case HashSign of - {_, SignAlgo} when SignAlgo == anon; SignAlgo == ecdh_anon -> - server_master_secret(Params#server_key_params.params, State); - _ -> - verify_server_key(Params, HashSign, State) + HashSign = negotiated_hashsign(Params#server_key_params.hashsign, KeyAlg, Version), + case is_anonymous(KeyAlg) of + true -> + server_master_secret(Params#server_key_params.params, + State#state{hashsign_algorithm = HashSign}); + false -> + verify_server_key(Params, HashSign, State#state{hashsign_algorithm = HashSign}) end. verify_server_key(#server_key_params{params = Params, @@ -2995,11 +3011,6 @@ get_pending_connection_state_prf(CStates, Direction) -> CS = tls_record:pending_connection_state(CStates, Direction), CS#connection_state.security_parameters#security_parameters.prf_algorithm. -connection_hashsign(HashSign = {_, _}, _State) -> - HashSign; -connection_hashsign(_, #state{hashsign_algorithm = HashSign}) -> - HashSign. - %% RFC 5246, Sect. 7.4.1.4.1. Signature Algorithms %% If the client does not send the signature_algorithms extension, the %% server MUST do the following: @@ -3014,12 +3025,18 @@ connection_hashsign(_, #state{hashsign_algorithm = HashSign}) -> %% - If the negotiated key exchange algorithm is one of (ECDH_ECDSA, %% ECDHE_ECDSA), behave as if the client had sent value {sha1,ecdsa}. +negotiated_hashsign(undefined, Algo, Version) -> + default_hashsign(Version, Algo); +negotiated_hashsign(HashSign = {_, _}, _, _) -> + HashSign. + default_hashsign(_Version = {Major, Minor}, KeyExchange) - when Major == 3 andalso Minor >= 3 andalso + when Major >= 3 andalso Minor >= 3 andalso (KeyExchange == rsa orelse KeyExchange == dhe_rsa orelse KeyExchange == dh_rsa orelse KeyExchange == ecdhe_rsa orelse + KeyExchange == ecdh_rsa orelse KeyExchange == srp_rsa) -> {sha, rsa}; default_hashsign(_Version, KeyExchange) @@ -3027,12 +3044,12 @@ default_hashsign(_Version, KeyExchange) KeyExchange == dhe_rsa; KeyExchange == dh_rsa; KeyExchange == ecdhe_rsa; + KeyExchange == ecdh_rsa; KeyExchange == srp_rsa -> {md5sha, rsa}; default_hashsign(_Version, KeyExchange) when KeyExchange == ecdhe_ecdsa; - KeyExchange == ecdh_ecdsa; - KeyExchange == ecdh_rsa -> + KeyExchange == ecdh_ecdsa -> {sha, ecdsa}; default_hashsign(_Version, KeyExchange) when KeyExchange == dhe_dss; @@ -3081,3 +3098,13 @@ select_curve(#state{client_ecc = {[Curve|_], _}}) -> {namedCurve, Curve}; select_curve(_) -> {namedCurve, ?secp256k1}. + +is_anonymous(Algo) when Algo == dh_anon; + Algo == ecdh_anon; + Algo == psk; + Algo == dhe_psk; + Algo == rsa_psk; + Algo == srp_anon -> + true; +is_anonymous(_) -> + false. diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl index 51fd2e1dc9..fdd696c0b1 100644 --- a/lib/ssl/src/tls_handshake.erl +++ b/lib/ssl/src/tls_handshake.erl @@ -34,11 +34,12 @@ -export([master_secret/4, client_hello/8, server_hello/7, hello/4, hello_request/0, certify/7, certificate/4, client_certificate_verify/6, certificate_verify/6, verify_signature/5, - certificate_request/3, key_exchange/3, server_key_exchange_hash/2, + certificate_request/4, key_exchange/3, server_key_exchange_hash/2, finished/5, verify_connection/6, get_tls_handshake/3, decode_client_key/3, decode_server_key/3, server_hello_done/0, encode_handshake/2, init_handshake_history/0, update_handshake_history/2, - decrypt_premaster_secret/2, prf/5, next_protocol/1]). + decrypt_premaster_secret/2, prf/5, next_protocol/1, select_hashsign/2, + select_cert_hashsign/3, default_hash_signs/0]). -export([dec_hello_extensions/2]). @@ -82,7 +83,7 @@ client_hello(Host, Port, ConnectionStates, renegotiation_info = renegotiation_info(client, ConnectionStates, Renegotiation), srp = SRP, - hash_signs = default_hash_signs(), + hash_signs = advertised_hash_signs(Version), ec_point_formats = EcPointFormats, elliptic_curves = EllipticCurves, next_protocol_negotiation = @@ -152,7 +153,6 @@ hello(#server_hello{cipher_suite = CipherSuite, server_version = Version, #ssl_options{secure_renegotiate = SecureRenegotation, next_protocol_selector = NextProtocolSelector, versions = SupportedVersions}, ConnectionStates0, Renegotiation) -> - %%TODO: select hash and signature algorigthm case tls_record:is_acceptable_version(Version, SupportedVersions) of true -> case handle_renegotiation_info(client, Info, ConnectionStates0, @@ -177,7 +177,6 @@ hello(#server_hello{cipher_suite = CipherSuite, server_version = Version, hello(#client_hello{client_version = ClientVersion} = Hello, #ssl_options{versions = Versions} = SslOpts, {Port, Session0, Cache, CacheCb, ConnectionStates0, Cert}, Renegotiation) -> - %% TODO: select hash and signature algorithm Version = select_version(ClientVersion, Versions), case tls_record:is_acceptable_version(Version, Versions) of true -> @@ -298,7 +297,7 @@ client_certificate_verify(undefined, _, _, _, _, _) -> client_certificate_verify(_, _, _, _, undefined, _) -> ignore; client_certificate_verify(OwnCert, MasterSecret, Version, - {HashAlgo, SignAlgo}, + {HashAlgo, _} = HashSign, PrivateKey, {Handshake, _}) -> case public_key:pkix_is_fixed_dh_cert(OwnCert) of true -> @@ -307,7 +306,7 @@ client_certificate_verify(OwnCert, MasterSecret, Version, Hashes = calc_certificate_verify(Version, HashAlgo, MasterSecret, Handshake), Signed = digitally_signed(Version, Hashes, HashAlgo, PrivateKey), - #certificate_verify{signature = Signed, hashsign_algorithm = {HashAlgo, SignAlgo}} + #certificate_verify{signature = Signed, hashsign_algorithm = HashSign} end. %%-------------------------------------------------------------------- @@ -349,17 +348,17 @@ verify_signature(_Version, Hash, {HashAlgo, ecdsa}, Signature, {?'id-ecPublicKey public_key:verify({digest, Hash}, HashAlgo, Signature, {PublicKey, PublicKeyParams}). %%-------------------------------------------------------------------- --spec certificate_request(#connection_states{}, db_handle(), certdb_ref()) -> +-spec certificate_request(#connection_states{}, db_handle(), certdb_ref(), tls_version()) -> #certificate_request{}. %% %% Description: Creates a certificate_request message, called by the server. %%-------------------------------------------------------------------- -certificate_request(ConnectionStates, CertDbHandle, CertDbRef) -> +certificate_request(ConnectionStates, CertDbHandle, CertDbRef, Version) -> #connection_state{security_parameters = #security_parameters{cipher_suite = CipherSuite}} = tls_record:pending_connection_state(ConnectionStates, read), Types = certificate_types(CipherSuite), - HashSigns = default_hash_signs(), + HashSigns = advertised_hash_signs(Version), Authorities = certificate_authorities(CertDbHandle, CertDbRef), #certificate_request{ certificate_types = Types, @@ -687,6 +686,54 @@ prf({3,1}, Secret, Label, Seed, WantedLength) -> prf({3,_N}, Secret, Label, Seed, WantedLength) -> {ok, ssl_tls1:prf(?SHA256, Secret, Label, Seed, WantedLength)}. + +%%-------------------------------------------------------------------- +-spec select_hashsign(#hash_sign_algos{}| undefined, undefined | term()) -> + [{atom(), atom()}] | undefined. + +%% +%% Description: +%%-------------------------------------------------------------------- +select_hashsign(_, undefined) -> + {null, anon}; +select_hashsign(undefined, Cert) -> + #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp), + #'OTPSubjectPublicKeyInfo'{algorithm = {_,Algo, _}} = TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo, + select_cert_hashsign(undefined, Algo, {undefined, undefined}); +select_hashsign(#hash_sign_algos{hash_sign_algos = HashSigns}, Cert) -> + #'OTPCertificate'{tbsCertificate = TBSCert} =public_key:pkix_decode_cert(Cert, otp), + #'OTPSubjectPublicKeyInfo'{algorithm = {_,Algo, _}} = TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo, + DefaultHashSign = {_, Sign} = select_cert_hashsign(undefined, Algo, {undefined, undefined}), + case lists:filter(fun({sha, dsa}) -> + true; + ({_, dsa}) -> + false; + ({Hash, S}) when S == Sign -> + ssl_cipher:is_acceptable_hash(Hash, proplists:get_value(hashs, crypto:supports())); + (_) -> + false + end, HashSigns) of + [] -> + DefaultHashSign; + [HashSign| _] -> + HashSign + end. +%%-------------------------------------------------------------------- +-spec select_cert_hashsign(#hash_sign_algos{}| undefined, oid(), tls_version()) -> + [{atom(), atom()}]. + +%% +%% Description: +%%-------------------------------------------------------------------- +select_cert_hashsign(HashSign, _, {Major, Minor}) when HashSign =/= undefined andalso Major >= 3 andalso Minor >= 3 -> + HashSign; +select_cert_hashsign(undefined,?'id-ecPublicKey', _) -> + {sha, ecdsa}; +select_cert_hashsign(undefined, ?rsaEncryption, _) -> + {md5sha, rsa}; +select_cert_hashsign(undefined, ?'id-dsa', _) -> + {sha, dsa}. + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- @@ -1066,7 +1113,7 @@ dec_hs(_Version, ?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary, cipher_suites = from_2bytes(CipherSuites), compression_methods = Comp_methods, renegotiation_info = RenegotiationInfo, - srp = SRP, + srp = SRP, hash_signs = HashSigns, elliptic_curves = EllipticCurves, next_protocol_negotiation = NextProtocolNegotiation @@ -1179,12 +1226,12 @@ dec_ske_params(Len, Keys, Version) -> dec_ske_signature(Params, <<?BYTE(HashAlgo), ?BYTE(SignAlgo), ?UINT16(0)>>, {Major, Minor}) - when Major == 3, Minor >= 3 -> + when Major >= 3, Minor >= 3 -> HashSign = {ssl_cipher:hash_algorithm(HashAlgo), ssl_cipher:sign_algorithm(SignAlgo)}, {Params, HashSign, <<>>}; dec_ske_signature(Params, <<?BYTE(HashAlgo), ?BYTE(SignAlgo), ?UINT16(Len), Signature:Len/binary>>, {Major, Minor}) - when Major == 3, Minor >= 3 -> + when Major >= 3, Minor >= 3 -> HashSign = {ssl_cipher:hash_algorithm(HashAlgo), ssl_cipher:sign_algorithm(SignAlgo)}, {Params, HashSign, Signature}; dec_ske_signature(Params, <<>>, _) -> @@ -1219,11 +1266,11 @@ dec_server_key(<<?BYTE(?NAMED_CURVE), ?UINT16(CurveID), params_bin = BinMsg, hashsign = HashSign, signature = Signature}; -dec_server_key(<<?UINT16(Len), PskIdentityHint:Len/binary>> = KeyStruct, +dec_server_key(<<?UINT16(Len), PskIdentityHint:Len/binary, _/binary>> = KeyStruct, KeyExchange, Version) when KeyExchange == ?KEY_EXCHANGE_PSK; KeyExchange == ?KEY_EXCHANGE_RSA_PSK -> Params = #server_psk_params{ - hint = PskIdentityHint}, + hint = PskIdentityHint}, {BinMsg, HashSign, Signature} = dec_ske_params(Len + 2, KeyStruct, Version), #server_key_params{params = Params, params_bin = BinMsg, @@ -1236,8 +1283,8 @@ dec_server_key(<<?UINT16(Len), IdentityHint:Len/binary, ?KEY_EXCHANGE_DHE_PSK, Version) -> DHParams = #server_dh_params{dh_p = P, dh_g = G, dh_y = Y}, Params = #server_dhe_psk_params{ - hint = IdentityHint, - dh_params = DHParams}, + hint = IdentityHint, + dh_params = DHParams}, {BinMsg, HashSign, Signature} = dec_ske_params(Len + PLen + GLen + YLen + 8, KeyStruct, Version), #server_key_params{params = Params, params_bin = BinMsg, @@ -1825,3 +1872,8 @@ handle_srp_extension(#srp{username = Username}, Session) -> int_to_bin(I) -> L = (length(integer_to_list(I, 16)) + 1) div 2, <<I:(L*8)>>. + +advertised_hash_signs({Major, Minor}) when Major >= 3 andalso Minor >= 3 -> + default_hash_signs(); +advertised_hash_signs(_) -> + undefined. |