diff options
Diffstat (limited to 'lib/ssl/src')
| -rw-r--r-- | lib/ssl/src/dtls_connection.erl | 5 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_cipher.erl | 97 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_connection.erl | 8 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_connection.hrl | 2 | ||||
| -rw-r--r-- | lib/ssl/src/tls_connection.erl | 18 | 
5 files changed, 85 insertions, 45 deletions
| diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl index 479f68f4bb..4f1f050e4b 100644 --- a/lib/ssl/src/dtls_connection.erl +++ b/lib/ssl/src/dtls_connection.erl @@ -232,9 +232,7 @@ error(_, _, _) ->  	    #state{}) ->  		   gen_statem:state_function_result().  %%-------------------------------------------------------------------- -hello(internal, #client_hello{client_version = ClientVersion, -			      extensions = #hello_extensions{ec_point_formats = EcPointFormats, -							     elliptic_curves = EllipticCurves}} = Hello, +hello(internal, #client_hello{client_version = ClientVersion} = Hello,        State = #state{connection_states = ConnectionStates0,  		     port = Port, session = #session{own_certificate = Cert} = Session0,  		     renegotiation = {Renegotiation, _}, @@ -260,7 +258,6 @@ hello(internal, #client_hello{client_version = ClientVersion,  					     negotiated_version = Version,  					     hashsign_algorithm = HashSign,  					     session = Session, -					     client_ecc = {EllipticCurves, EcPointFormats},  					     negotiated_protocol = Protocol}, ?MODULE)      end;  hello(internal, #server_hello{} = Hello, diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl index e935c033c7..605bbd859a 100644 --- a/lib/ssl/src/ssl_cipher.erl +++ b/lib/ssl/src/ssl_cipher.erl @@ -46,9 +46,9 @@  	      erl_cipher_suite/0, openssl_cipher_suite/0,  	      hash/0, key_algo/0, sign_algo/0]). --type cipher()            :: null |rc4_128 | idea_cbc | des40_cbc | des_cbc | '3des_ede_cbc'  +-type cipher()            :: null |rc4_128 | des_cbc | '3des_ede_cbc'   			   | aes_128_cbc |  aes_256_cbc | aes_128_gcm | aes_256_gcm | chacha20_poly1305. --type hash()              :: null | sha | md5 | sha224 | sha256 | sha384 | sha512. +-type hash()              :: null | md5 | sha | sha224 | sha256 | sha384 | sha512.  -type sign_algo()         :: rsa | dsa | ecdsa.  -type key_algo()          :: null | rsa | dhe_rsa | dhe_dss | ecdhe_ecdsa| ecdh_ecdsa | ecdh_rsa| srp_rsa| srp_dss |   			     psk | dhe_psk | rsa_psk | dh_anon | ecdh_anon | srp_anon. @@ -333,21 +333,27 @@ anonymous_suites({3, N}) ->  anonymous_suites(N)    when N >= 3 ->      [?TLS_DH_anon_WITH_AES_128_GCM_SHA256, -     ?TLS_DH_anon_WITH_AES_256_GCM_SHA384 -    ] ++ anonymous_suites(0); - -anonymous_suites(_) -> -    [?TLS_DH_anon_WITH_RC4_128_MD5, -     ?TLS_DH_anon_WITH_DES_CBC_SHA, -     ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, -     ?TLS_DH_anon_WITH_AES_128_CBC_SHA, -     ?TLS_DH_anon_WITH_AES_256_CBC_SHA, +     ?TLS_DH_anon_WITH_AES_256_GCM_SHA384,       ?TLS_DH_anon_WITH_AES_128_CBC_SHA256,       ?TLS_DH_anon_WITH_AES_256_CBC_SHA256, -     ?TLS_ECDH_anon_WITH_RC4_128_SHA, -     ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,       ?TLS_ECDH_anon_WITH_AES_128_CBC_SHA, -     ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA]. +     ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA, +     ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, +     ?TLS_DH_anon_WITH_RC4_128_MD5]; + +anonymous_suites(2) -> +    [?TLS_ECDH_anon_WITH_AES_128_CBC_SHA, +     ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA, +     ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, +     ?TLS_DH_anon_WITH_DES_CBC_SHA, +     ?TLS_DH_anon_WITH_RC4_128_MD5]; + +anonymous_suites(N)  when N == 0; +			  N == 1 -> +    [?TLS_DH_anon_WITH_RC4_128_MD5, +     ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, +     ?TLS_DH_anon_WITH_DES_CBC_SHA +    ].  %%--------------------------------------------------------------------  -spec psk_suites(ssl_record:ssl_version() | integer()) -> [cipher_suite()]. @@ -1441,25 +1447,60 @@ filter_suites(Suites) ->  			     is_acceptable_prf(Prf, Hashs)  		 end, Suites). -is_acceptable_keyexchange(KeyExchange, Algos) -  when KeyExchange == ecdh_ecdsa; -       KeyExchange == ecdhe_ecdsa; -       KeyExchange == ecdh_rsa; -       KeyExchange == ecdhe_rsa; -       KeyExchange == ecdh_anon -> +is_acceptable_keyexchange(KeyExchange, _Algos) when KeyExchange == psk; +                                                    KeyExchange == null -> +    true; +is_acceptable_keyexchange(KeyExchange, Algos) when KeyExchange == dh_anon; +                                                   KeyExchange == dhe_psk -> +    proplists:get_bool(dh, Algos); +is_acceptable_keyexchange(dhe_dss, Algos) -> +    proplists:get_bool(dh, Algos) andalso +        proplists:get_bool(dss, Algos); +is_acceptable_keyexchange(dhe_rsa, Algos) -> +    proplists:get_bool(dh, Algos) andalso +        proplists:get_bool(rsa, Algos); +is_acceptable_keyexchange(ecdh_anon, Algos) ->      proplists:get_bool(ecdh, Algos); -is_acceptable_keyexchange(_, _) -> -    true. - +is_acceptable_keyexchange(KeyExchange, Algos) when KeyExchange == ecdh_ecdsa; +                                                   KeyExchange == ecdhe_ecdsa -> +    proplists:get_bool(ecdh, Algos) andalso +        proplists:get_bool(ecdsa, Algos); +is_acceptable_keyexchange(KeyExchange, Algos) when KeyExchange == ecdh_rsa; +                                                   KeyExchange == ecdhe_rsa -> +    proplists:get_bool(ecdh, Algos) andalso +        proplists:get_bool(rsa, Algos); +is_acceptable_keyexchange(KeyExchange, Algos) when KeyExchange == rsa; +                                                   KeyExchange == rsa_psk -> +    proplists:get_bool(rsa, Algos); +is_acceptable_keyexchange(srp_anon, Algos) -> +    proplists:get_bool(srp, Algos); +is_acceptable_keyexchange(srp_dss, Algos) -> +    proplists:get_bool(srp, Algos) andalso +        proplists:get_bool(dss, Algos); +is_acceptable_keyexchange(srp_rsa, Algos) -> +    proplists:get_bool(srp, Algos) andalso +        proplists:get_bool(rsa, Algos); +is_acceptable_keyexchange(_KeyExchange, _Algos) -> +    false. + +is_acceptable_cipher(null, _Algos) -> +    true; +is_acceptable_cipher(rc4_128, Algos) -> +    proplists:get_bool(rc4, Algos); +is_acceptable_cipher(des_cbc, Algos) -> +    proplists:get_bool(des_cbc, Algos); +is_acceptable_cipher('3des_ede_cbc', Algos) -> +    proplists:get_bool(des3_cbc, Algos); +is_acceptable_cipher(aes_128_cbc, Algos) -> +    proplists:get_bool(aes_cbc128, Algos); +is_acceptable_cipher(aes_256_cbc, Algos) -> +    proplists:get_bool(aes_cbc256, Algos);  is_acceptable_cipher(Cipher, Algos)    when Cipher == aes_128_gcm;         Cipher == aes_256_gcm ->      proplists:get_bool(aes_gcm, Algos); -is_acceptable_cipher(Cipher, Algos) -  when Cipher == chacha20_poly1305 -> -    proplists:get_bool(Cipher, Algos); -is_acceptable_cipher(_, _) -> -    true. +is_acceptable_cipher(Cipher, Algos) -> +    proplists:get_bool(Cipher, Algos).  is_acceptable_hash(null, _Algos) ->      true; diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 304d1706f5..08fca76123 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -1430,13 +1430,14 @@ key_exchange(#state{role = server, private_key = Key, key_algorithm = Algo} = St  key_exchange(#state{role = server, key_algorithm = Algo,  		    hashsign_algorithm = HashSignAlgo,  		    private_key = PrivateKey, +		    session = #session{ecc = ECCCurve},  		    connection_states = ConnectionStates0,  		    negotiated_version = Version  		   } = State0, Connection)    when Algo == ecdhe_ecdsa; Algo == ecdhe_rsa;         Algo == ecdh_anon -> -    ECDHKeys = public_key:generate_key(select_curve(State0)), +    ECDHKeys = public_key:generate_key(ECCCurve),      #{security_parameters := SecParams} =   	ssl_record:pending_connection_state(ConnectionStates0, read),      #security_parameters{client_random = ClientRandom, @@ -1845,11 +1846,6 @@ cipher_role(server, Data, Session,  #state{connection_states = ConnectionStates0      {Record, State} = prepare_connection(State1, Connection),      Connection:next_event(connection, Record, State). -select_curve(#state{client_ecc = {[Curve|_], _}}) -> -    {namedCurve, Curve}; -select_curve(_) -> -    {namedCurve, ?secp256r1}. -  is_anonymous(Algo) when Algo == dh_anon;  			Algo == ecdh_anon;  			Algo == psk; diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl index f1e612a41b..fca3e11894 100644 --- a/lib/ssl/src/ssl_connection.hrl +++ b/lib/ssl/src/ssl_connection.hrl @@ -48,6 +48,7 @@            socket_options        :: #socket_options{},            connection_states     :: ssl_record:connection_states() | secret_printout(),  	  protocol_buffers      :: term() | secret_printout() , %% #protocol_buffers{} from tls_record.hrl or dtls_recor.hrl +	  unprocessed_handshake_events = 0    :: integer(),            tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout()                                   | 'undefined',  	  cert_db               :: reference() | 'undefined', @@ -81,7 +82,6 @@            expecting_next_protocol_negotiation = false ::boolean(),  	  expecting_finished =                  false ::boolean(),            negotiated_protocol = undefined             :: undefined | binary(), -	  client_ecc,          % {Curves, PointFmt}  	  tracker              :: pid() | 'undefined', %% Tracker process for listen socket  	  sni_hostname = undefined,  	  downgrade, diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 9b9031473a..932bb139c1 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -237,9 +237,7 @@ error(_, _, _) ->  	    #state{}) ->  		   gen_statem:state_function_result().  %%-------------------------------------------------------------------- -hello(internal, #client_hello{client_version = ClientVersion, -			       extensions = #hello_extensions{ec_point_formats = EcPointFormats, -							      elliptic_curves = EllipticCurves}} = Hello, +hello(internal, #client_hello{client_version = ClientVersion} = Hello,        #state{connection_states = ConnectionStates0,  	     port = Port, session = #session{own_certificate = Cert} = Session0,  	     renegotiation = {Renegotiation, _}, @@ -265,7 +263,6 @@ hello(internal, #client_hello{client_version = ClientVersion,  					     negotiated_version = Version,  					     hashsign_algorithm = HashSign,  					     session = Session, -					     client_ecc = {EllipticCurves, EcPointFormats},  					     negotiated_protocol = Protocol})      end;  hello(internal, #server_hello{} = Hello, @@ -421,7 +418,7 @@ handle_common_event(internal,  #ssl_tls{type = ?HANDSHAKE, fragment = Data},  	    connection ->  		ssl_connection:hibernate_after(StateName, State, Events);  	    _ -> -		{next_state, StateName, State, Events} +		{next_state, StateName, State#state{unprocessed_handshake_events = unprocessed_events(Events)}, Events}  	end      catch throw:#alert{} = Alert ->  	    ssl_connection:handle_own_alert(Alert, Version, StateName, State0) @@ -537,7 +534,9 @@ next_tls_record(Data, #state{protocol_buffers = #protocol_buffers{tls_record_buf  	#alert{} = Alert ->  	    Alert      end. - +next_record(#state{unprocessed_handshake_events = N} = State) when N > 0 -> +    {no_record, State#state{unprocessed_handshake_events = N-1}}; +					   next_record(#state{protocol_buffers =  		       #protocol_buffers{tls_packets = [], tls_cipher_texts = [CT | Rest]}  		   = Buffers, @@ -712,3 +711,10 @@ gen_info(Event, StateName, #state{negotiated_version = Version} = State) ->  					    Version, StateName, State)        end. +unprocessed_events(Events) -> +    %% The first handshake event will be processed immediately +    %% as it is entered first in the event queue and +    %% when it is processed there will be length(Events)-1 +    %% handshake events left to process before we should +    %% process more TLS-records received on the socket.  +    erlang:length(Events)-1. | 
