diff options
Diffstat (limited to 'lib/ssl/src/ssl_connection.erl')
-rw-r--r-- | lib/ssl/src/ssl_connection.erl | 180 |
1 files changed, 102 insertions, 78 deletions
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index e4715ba329..179ad67940 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -588,7 +588,7 @@ handle_session(#server_hello{cipher_suite = CipherSuite, {ProtoExt =:= npn, Protocol0} end, - State = State0#state{key_algorithm = KeyAlgorithm, + State = State0#state{kex_algorithm = KeyAlgorithm, connection_states = ConnectionStates, handshake_env = HsEnv#handshake_env{premaster_secret = PremasterSecret, expecting_next_protocol_negotiation = ExpectNPN, @@ -836,21 +836,29 @@ certify(internal, #server_key_exchange{exchange_keys = Keys}, #state{static_env = #static_env{role = client}, handshake_env = #handshake_env{public_key_info = PubKeyInfo} = HsEnv, connection_env = #connection_env{negotiated_version = Version}, - key_algorithm = Alg, + kex_algorithm = KexAlg, session = Session, connection_states = ConnectionStates} = State, Connection) - when Alg == dhe_dss; Alg == dhe_rsa; - Alg == ecdhe_rsa; Alg == ecdhe_ecdsa; - Alg == dh_anon; Alg == ecdh_anon; - Alg == psk; Alg == dhe_psk; Alg == ecdhe_psk; Alg == rsa_psk; - Alg == srp_dss; Alg == srp_rsa; Alg == srp_anon -> - - Params = ssl_handshake:decode_server_key(Keys, Alg, ssl:tls_version(Version)), + when KexAlg == dhe_dss; + KexAlg == dhe_rsa; + KexAlg == ecdhe_rsa; + KexAlg == ecdhe_ecdsa; + KexAlg == dh_anon; + KexAlg == ecdh_anon; + KexAlg == psk; + KexAlg == dhe_psk; + KexAlg == ecdhe_psk; + KexAlg == rsa_psk; + KexAlg == srp_dss; + KexAlg == srp_rsa; + KexAlg == srp_anon -> + + Params = ssl_handshake:decode_server_key(Keys, KexAlg, ssl:tls_version(Version)), %% Use negotiated value if TLS-1.2 otherwhise return default - HashSign = negotiated_hashsign(Params#server_key_params.hashsign, Alg, PubKeyInfo, ssl:tls_version(Version)), + HashSign = negotiated_hashsign(Params#server_key_params.hashsign, KexAlg, PubKeyInfo, ssl:tls_version(Version)), - case is_anonymous(Alg) of + case is_anonymous(KexAlg) of true -> calculate_secret(Params#server_key_params.params, State#state{handshake_env = HsEnv#handshake_env{hashsign_algorithm = HashSign}}, Connection); @@ -870,10 +878,16 @@ certify(internal, #server_key_exchange{exchange_keys = Keys}, certify(internal, #certificate_request{}, #state{static_env = #static_env{role = client}, connection_env = #connection_env{negotiated_version = Version}, - key_algorithm = Alg} = State, _) - when Alg == dh_anon; Alg == ecdh_anon; - Alg == psk; Alg == dhe_psk; Alg == ecdhe_psk; Alg == rsa_psk; - Alg == srp_dss; Alg == srp_rsa; Alg == srp_anon -> + kex_algorithm = KexAlg} = State, _) + when KexAlg == dh_anon; + KexAlg == ecdh_anon; + KexAlg == psk; + KexAlg == dhe_psk; + KexAlg == ecdhe_psk; + KexAlg == rsa_psk; + KexAlg == srp_dss; + KexAlg == srp_rsa; + KexAlg == srp_anon -> handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE), Version, ?FUNCTION_NAME, State); certify(internal, #certificate_request{}, @@ -905,9 +919,9 @@ certify(internal, #server_hello_done{}, handshake_env = #handshake_env{premaster_secret = undefined, server_psk_identity = PSKIdentity} = HsEnv, ssl_options = #ssl_options{user_lookup_fun = PSKLookup}, - key_algorithm = Alg} = State0, Connection) - when Alg == psk -> - case ssl_handshake:premaster_secret({Alg, PSKIdentity}, PSKLookup) of + kex_algorithm = KexAlg} = State0, Connection) + when KexAlg == psk -> + case ssl_handshake:premaster_secret({KexAlg, PSKIdentity}, PSKLookup) of #alert{} = Alert -> handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0); PremasterSecret -> @@ -923,11 +937,11 @@ certify(internal, #server_hello_done{}, server_psk_identity = PSKIdentity} = HsEnv, session = #session{master_secret = undefined}, ssl_options = #ssl_options{user_lookup_fun = PSKLookup}, - key_algorithm = Alg} = State0, Connection) - when Alg == rsa_psk -> + kex_algorithm = KexAlg} = State0, Connection) + when KexAlg == rsa_psk -> Rand = ssl_cipher:random_bytes(?NUM_OF_PREMASTERSECRET_BYTES-2), RSAPremasterSecret = <<?BYTE(Major), ?BYTE(Minor), Rand/binary>>, - case ssl_handshake:premaster_secret({Alg, PSKIdentity}, PSKLookup, + case ssl_handshake:premaster_secret({KexAlg, PSKIdentity}, PSKLookup, RSAPremasterSecret) of #alert{} = Alert -> handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0); @@ -977,7 +991,7 @@ certify(internal = Type, #client_key_exchange{} = Msg, %% We expect a certificate here handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection); certify(internal, #client_key_exchange{exchange_keys = Keys}, - State = #state{key_algorithm = KeyAlg, + State = #state{kex_algorithm = KeyAlg, connection_env = #connection_env{negotiated_version = Version}}, Connection) -> try certify_client_key_exchange(ssl_handshake:decode_client_key(Keys, KeyAlg, ssl:tls_version(Version)), @@ -1005,7 +1019,7 @@ cipher(internal, #certificate_verify{signature = Signature, handshake_env = #handshake_env{tls_handshake_history = Hist, public_key_info = PubKeyInfo} = HsEnv, connection_env = #connection_env{negotiated_version = Version}, - key_algorithm = KexAlg, + kex_algorithm = KexAlg, session = #session{master_secret = MasterSecret} } = State, Connection) -> @@ -1522,7 +1536,7 @@ server_hello(ServerHello, State0, Connection) -> CipherSuite = ServerHello#server_hello.cipher_suite, #{key_exchange := KeyAlgorithm} = ssl_cipher_format:suite_definition(CipherSuite), State = Connection:queue_handshake(ServerHello, State0), - State#state{key_algorithm = KeyAlgorithm}. + State#state{kex_algorithm = KeyAlgorithm}. server_hello_done(State, Connection) -> HelloDone = ssl_handshake:server_hello_done(), @@ -1687,12 +1701,12 @@ certify_client_key_exchange(#client_srp_public{} = ClientKey, PremasterSecret = ssl_handshake:premaster_secret(ClientKey, Key, Params), calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher). -certify_server(#state{key_algorithm = Algo} = State, _) when Algo == dh_anon; - Algo == ecdh_anon; - Algo == psk; - Algo == dhe_psk; - Algo == ecdhe_psk; - Algo == srp_anon -> +certify_server(#state{kex_algorithm = KexAlg} = State, _) when KexAlg == dh_anon; + KexAlg == ecdh_anon; + KexAlg == psk; + KexAlg == dhe_psk; + KexAlg == ecdhe_psk; + KexAlg == srp_anon -> State; certify_server(#state{static_env = #static_env{cert_db = CertDbHandle, cert_db_ref = CertDbRef}, @@ -1704,17 +1718,17 @@ certify_server(#state{static_env = #static_env{cert_db = CertDbHandle, throw(Alert) end. -key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = rsa} = State,_) -> +key_exchange(#state{static_env = #static_env{role = server}, kex_algorithm = rsa} = State,_) -> State; -key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = Algo, +key_exchange(#state{static_env = #static_env{role = server}, kex_algorithm = KexAlg, handshake_env = #handshake_env{diffie_hellman_params = #'DHParameter'{} = Params, hashsign_algorithm = HashSignAlgo}, connection_env = #connection_env{negotiated_version = Version, private_key = PrivateKey}, connection_states = ConnectionStates0} = State0, Connection) - when Algo == dhe_dss; - Algo == dhe_rsa; - Algo == dh_anon -> + when KexAlg == dhe_dss; + KexAlg == dhe_rsa; + KexAlg == dh_anon -> DHKeys = public_key:generate_key(Params), #{security_parameters := SecParams} = ssl_record:pending_connection_state(ConnectionStates0, read), @@ -1728,19 +1742,21 @@ key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = Alg State#state{diffie_hellman_keys = DHKeys}; key_exchange(#state{static_env = #static_env{role = server}, connection_env = #connection_env{private_key = #'ECPrivateKey'{parameters = ECCurve} = Key}, - key_algorithm = Algo, + kex_algorithm = KexAlg, session = Session} = State, _) - when Algo == ecdh_ecdsa; Algo == ecdh_rsa -> + when KexAlg == ecdh_ecdsa; + KexAlg == ecdh_rsa -> State#state{diffie_hellman_keys = Key, session = Session#session{ecc = ECCurve}}; -key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = Algo, +key_exchange(#state{static_env = #static_env{role = server}, kex_algorithm = KexAlg, handshake_env = #handshake_env{hashsign_algorithm = HashSignAlgo}, connection_env = #connection_env{negotiated_version = Version, private_key = PrivateKey}, session = #session{ecc = ECCCurve}, connection_states = ConnectionStates0} = State0, Connection) - when Algo == ecdhe_ecdsa; Algo == ecdhe_rsa; - Algo == ecdh_anon -> + when KexAlg == ecdhe_ecdsa; + KexAlg == ecdhe_rsa; + KexAlg == ecdh_anon -> ECDHKeys = public_key:generate_key(ECCCurve), #{security_parameters := SecParams} = @@ -1754,10 +1770,10 @@ key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = Alg PrivateKey}), State = Connection:queue_handshake(Msg, State0), State#state{diffie_hellman_keys = ECDHKeys}; -key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = psk, +key_exchange(#state{static_env = #static_env{role = server}, kex_algorithm = psk, ssl_options = #ssl_options{psk_identity = undefined}} = State, _) -> State; -key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = psk, +key_exchange(#state{static_env = #static_env{role = server}, kex_algorithm = psk, ssl_options = #ssl_options{psk_identity = PskIdentityHint}, handshake_env = #handshake_env{hashsign_algorithm = HashSignAlgo}, connection_env = #connection_env{negotiated_version = Version, @@ -1773,7 +1789,7 @@ key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = psk ServerRandom, PrivateKey}), Connection:queue_handshake(Msg, State0); -key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = dhe_psk, +key_exchange(#state{static_env = #static_env{role = server}, kex_algorithm = dhe_psk, ssl_options = #ssl_options{psk_identity = PskIdentityHint}, handshake_env = #handshake_env{diffie_hellman_params = #'DHParameter'{} = Params, hashsign_algorithm = HashSignAlgo}, @@ -1794,7 +1810,7 @@ key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = dhe PrivateKey}), State = Connection:queue_handshake(Msg, State0), State#state{diffie_hellman_keys = DHKeys}; -key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = ecdhe_psk, +key_exchange(#state{static_env = #static_env{role = server}, kex_algorithm = ecdhe_psk, ssl_options = #ssl_options{psk_identity = PskIdentityHint}, handshake_env = #handshake_env{hashsign_algorithm = HashSignAlgo}, connection_env = #connection_env{negotiated_version = Version, @@ -1815,10 +1831,10 @@ key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = ecd PrivateKey}), State = Connection:queue_handshake(Msg, State0), State#state{diffie_hellman_keys = ECDHKeys}; -key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = rsa_psk, +key_exchange(#state{static_env = #static_env{role = server}, kex_algorithm = rsa_psk, ssl_options = #ssl_options{psk_identity = undefined}} = State, _) -> State; -key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = rsa_psk, +key_exchange(#state{static_env = #static_env{role = server}, kex_algorithm = rsa_psk, ssl_options = #ssl_options{psk_identity = PskIdentityHint}, handshake_env = #handshake_env{hashsign_algorithm = HashSignAlgo}, connection_env = #connection_env{negotiated_version = Version, @@ -1835,7 +1851,7 @@ key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = rsa ServerRandom, PrivateKey}), Connection:queue_handshake(Msg, State0); -key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = Algo, +key_exchange(#state{static_env = #static_env{role = server}, kex_algorithm = KexAlg, ssl_options = #ssl_options{user_lookup_fun = LookupFun}, handshake_env = #handshake_env{hashsign_algorithm = HashSignAlgo}, connection_env = #connection_env{negotiated_version = Version, @@ -1843,9 +1859,9 @@ key_exchange(#state{static_env = #static_env{role = server}, key_algorithm = Alg session = #session{srp_username = Username}, connection_states = ConnectionStates0 } = State0, Connection) - when Algo == srp_dss; - Algo == srp_rsa; - Algo == srp_anon -> + when KexAlg == srp_dss; + KexAlg == srp_rsa; + KexAlg == srp_anon -> SrpParams = handle_srp_identity(Username, LookupFun), Keys = case generate_srp_server_keys(SrpParams, 0) of Alert = #alert{} -> @@ -1869,41 +1885,43 @@ key_exchange(#state{static_env = #static_env{role = client}, handshake_env = #handshake_env{public_key_info = PublicKeyInfo, premaster_secret = PremasterSecret}, connection_env = #connection_env{negotiated_version = Version}, - key_algorithm = rsa} = State0, Connection) -> + kex_algorithm = rsa} = State0, Connection) -> Msg = rsa_key_exchange(ssl:tls_version(Version), PremasterSecret, PublicKeyInfo), Connection:queue_handshake(Msg, State0); key_exchange(#state{static_env = #static_env{role = client}, connection_env = #connection_env{negotiated_version = Version}, - key_algorithm = Algorithm, + kex_algorithm = KexAlg, diffie_hellman_keys = {DhPubKey, _} } = State0, Connection) - when Algorithm == dhe_dss; - Algorithm == dhe_rsa; - Algorithm == dh_anon -> + when KexAlg == dhe_dss; + KexAlg == dhe_rsa; + KexAlg == dh_anon -> Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {dh, DhPubKey}), Connection:queue_handshake(Msg, State0); key_exchange(#state{static_env = #static_env{role = client}, connection_env = #connection_env{negotiated_version = Version}, - key_algorithm = Algorithm, + kex_algorithm = KexAlg, session = Session, diffie_hellman_keys = #'ECPrivateKey'{parameters = ECCurve} = Key} = State0, Connection) - when Algorithm == ecdhe_ecdsa; Algorithm == ecdhe_rsa; - Algorithm == ecdh_ecdsa; Algorithm == ecdh_rsa; - Algorithm == ecdh_anon -> + when KexAlg == ecdhe_ecdsa; + KexAlg == ecdhe_rsa; + KexAlg == ecdh_ecdsa; + KexAlg == ecdh_rsa; + KexAlg == ecdh_anon -> Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {ecdh, Key}), Connection:queue_handshake(Msg, State0#state{session = Session#session{ecc = ECCurve}}); key_exchange(#state{static_env = #static_env{role = client}, connection_env = #connection_env{negotiated_version = Version}, ssl_options = SslOpts, - key_algorithm = psk} = State0, Connection) -> + kex_algorithm = psk} = State0, Connection) -> Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {psk, SslOpts#ssl_options.psk_identity}), Connection:queue_handshake(Msg, State0); key_exchange(#state{static_env = #static_env{role = client}, connection_env = #connection_env{negotiated_version = Version}, ssl_options = SslOpts, - key_algorithm = dhe_psk, + kex_algorithm = dhe_psk, diffie_hellman_keys = {DhPubKey, _}} = State0, Connection) -> Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {dhe_psk, @@ -1913,7 +1931,7 @@ key_exchange(#state{static_env = #static_env{role = client}, key_exchange(#state{static_env = #static_env{role = client}, connection_env = #connection_env{negotiated_version = Version}, ssl_options = SslOpts, - key_algorithm = ecdhe_psk, + kex_algorithm = ecdhe_psk, diffie_hellman_keys = ECDHKeys} = State0, Connection) -> Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {ecdhe_psk, @@ -1925,19 +1943,19 @@ key_exchange(#state{static_env = #static_env{role = client}, premaster_secret = PremasterSecret}, connection_env = #connection_env{negotiated_version = Version}, ssl_options = SslOpts, - key_algorithm = rsa_psk} + kex_algorithm = rsa_psk} = State0, Connection) -> Msg = rsa_psk_key_exchange(ssl:tls_version(Version), SslOpts#ssl_options.psk_identity, PremasterSecret, PublicKeyInfo), Connection:queue_handshake(Msg, State0); key_exchange(#state{static_env = #static_env{role = client}, connection_env = #connection_env{negotiated_version = Version}, - key_algorithm = Algorithm, + kex_algorithm = KexAlg, srp_keys = {ClientPubKey, _}} = State0, Connection) - when Algorithm == srp_dss; - Algorithm == srp_rsa; - Algorithm == srp_anon -> + when KexAlg == srp_dss; + KexAlg == srp_rsa; + KexAlg == srp_anon -> Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {srp, ClientPubKey}), Connection:queue_handshake(Msg, State0). @@ -1974,10 +1992,16 @@ rsa_psk_key_exchange(Version, PskIdentity, PremasterSecret, rsa_psk_key_exchange(_, _, _, _) -> throw (?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE, pub_key_is_not_rsa)). -request_client_cert(#state{key_algorithm = Alg} = State, _) - when Alg == dh_anon; Alg == ecdh_anon; - Alg == psk; Alg == dhe_psk; Alg == ecdhe_psk; Alg == rsa_psk; - Alg == srp_dss; Alg == srp_rsa; Alg == srp_anon -> +request_client_cert(#state{kex_algorithm = Alg} = State, _) + when Alg == dh_anon; + Alg == ecdh_anon; + Alg == psk; + Alg == dhe_psk; + Alg == ecdhe_psk; + Alg == rsa_psk; + Alg == srp_dss; + Alg == srp_rsa; + Alg == srp_anon -> State; request_client_cert(#state{static_env = #static_env{cert_db = CertDbHandle, @@ -2198,13 +2222,13 @@ cipher_role(server, Data, Session, #state{connection_states = ConnectionStates0 {Record, State} = prepare_connection(State1, Connection), Connection:next_event(connection, Record, State, Actions). -is_anonymous(Algo) when Algo == dh_anon; - Algo == ecdh_anon; - Algo == psk; - Algo == dhe_psk; - Algo == ecdhe_psk; - Algo == rsa_psk; - Algo == srp_anon -> +is_anonymous(KexAlg) when KexAlg == dh_anon; + KexAlg == ecdh_anon; + KexAlg == psk; + KexAlg == dhe_psk; + KexAlg == ecdhe_psk; + KexAlg == rsa_psk; + KexAlg == srp_anon -> true; is_anonymous(_) -> false. |