diff options
-rw-r--r-- | src/tls/msg_cert_verify.cpp | 2 | ||||
-rw-r--r-- | src/tls/msg_client_kex.cpp | 24 | ||||
-rw-r--r-- | src/tls/msg_finished.cpp | 2 | ||||
-rw-r--r-- | src/tls/msg_server_kex.cpp | 16 | ||||
-rw-r--r-- | src/tls/tls_channel.cpp | 8 | ||||
-rw-r--r-- | src/tls/tls_channel.h | 8 | ||||
-rw-r--r-- | src/tls/tls_client.cpp | 161 | ||||
-rw-r--r-- | src/tls/tls_handshake_hash.cpp | 4 | ||||
-rw-r--r-- | src/tls/tls_handshake_hash.h | 4 | ||||
-rw-r--r-- | src/tls/tls_handshake_state.cpp | 114 | ||||
-rw-r--r-- | src/tls/tls_handshake_state.h | 117 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 12 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 246 | ||||
-rw-r--r-- | src/tls/tls_session_key.cpp | 10 | ||||
-rw-r--r-- | src/tls/tls_session_key.h | 2 |
15 files changed, 436 insertions, 294 deletions
diff --git a/src/tls/msg_cert_verify.cpp b/src/tls/msg_cert_verify.cpp index a6ec298c9..79e7bcaf6 100644 --- a/src/tls/msg_cert_verify.cpp +++ b/src/tls/msg_cert_verify.cpp @@ -92,7 +92,7 @@ std::vector<byte> Certificate_Verify::serialize() const * Verify a Certificate Verify message */ bool Certificate_Verify::verify(const X509_Certificate& cert, - Handshake_State* state) + const Handshake_State* state) const { std::unique_ptr<Public_Key> key(cert.subject_public_key()); diff --git a/src/tls/msg_client_kex.cpp b/src/tls/msg_client_kex.cpp index 176187d08..0fbd03b72 100644 --- a/src/tls/msg_client_kex.cpp +++ b/src/tls/msg_client_kex.cpp @@ -61,13 +61,13 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, { std::string identity_hint = ""; - if(state->server_kex) + if(state->server_kex()) { - TLS_Data_Reader reader(state->server_kex->params()); + TLS_Data_Reader reader(state->server_kex()->params()); identity_hint = reader.get_string(2, 0, 65535); } - const std::string hostname = state->client_hello->sni_hostname(); + const std::string hostname = state->client_hello()->sni_hostname(); const std::string psk_identity = creds.psk_identity("tls-client", hostname, @@ -82,9 +82,9 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, append_tls_length_value(m_pre_master, zeros, 2); append_tls_length_value(m_pre_master, psk.bits_of(), 2); } - else if(state->server_kex) + else if(state->server_kex()) { - TLS_Data_Reader reader(state->server_kex->params()); + TLS_Data_Reader reader(state->server_kex()->params()); SymmetricKey psk; @@ -92,7 +92,7 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, { std::string identity_hint = reader.get_string(2, 0, 65535); - const std::string hostname = state->client_hello->sni_hostname(); + const std::string hostname = state->client_hello()->sni_hostname(); const std::string psk_identity = creds.psk_identity("tls-client", hostname, @@ -238,7 +238,7 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, if(const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key.get())) { - const Protocol_Version offered_version = state->client_hello->version(); + const Protocol_Version offered_version = state->client_hello()->version(); m_pre_master = rng.random_vec(48); m_pre_master[0] = offered_version.major_version(); @@ -275,7 +275,7 @@ Client_Key_Exchange::Client_Key_Exchange(const std::vector<byte>& contents, if(kex_algo == "RSA") { - BOTAN_ASSERT(state->server_certs && !state->server_certs->cert_chain().empty(), + BOTAN_ASSERT(state->server_certs() && !state->server_certs()->cert_chain().empty(), "RSA key exchange negotiated so server sent a certificate"); const Private_Key* private_key = state->server_rsa_kex_key; @@ -288,7 +288,7 @@ Client_Key_Exchange::Client_Key_Exchange(const std::vector<byte>& contents, PK_Decryptor_EME decryptor(*private_key, "PKCS1v15"); - Protocol_Version client_version = state->client_hello->version(); + Protocol_Version client_version = state->client_hello()->version(); try { @@ -328,7 +328,7 @@ Client_Key_Exchange::Client_Key_Exchange(const std::vector<byte>& contents, const std::string psk_identity = reader.get_string(2, 0, 65535); psk = creds.psk("tls-server", - state->client_hello->sni_hostname(), + state->client_hello()->sni_hostname(), psk_identity); if(psk.length() == 0) @@ -349,14 +349,14 @@ Client_Key_Exchange::Client_Key_Exchange(const std::vector<byte>& contents, } else if(kex_algo == "SRP_SHA") { - SRP6_Server_Session& srp = state->server_kex->server_srp_params(); + SRP6_Server_Session& srp = state->server_kex()->server_srp_params(); m_pre_master = srp.step2(BigInt::decode(reader.get_range<byte>(2, 0, 65535))).bits_of(); } else if(kex_algo == "DH" || kex_algo == "DHE_PSK" || kex_algo == "ECDH" || kex_algo == "ECDHE_PSK") { - const Private_Key& private_key = state->server_kex->server_kex_key(); + const Private_Key& private_key = state->server_kex()->server_kex_key(); const PK_Key_Agreement_Key* ka_key = dynamic_cast<const PK_Key_Agreement_Key*>(&private_key); diff --git a/src/tls/msg_finished.cpp b/src/tls/msg_finished.cpp index 4f4f384c5..9a38b822b 100644 --- a/src/tls/msg_finished.cpp +++ b/src/tls/msg_finished.cpp @@ -94,7 +94,7 @@ Finished::Finished(const std::vector<byte>& buf) * Verify a Finished message */ bool Finished::verify(Handshake_State* state, - Connection_Side side) + Connection_Side side) const { return (m_verification_data == finished_compute_verify(state, side)); } diff --git a/src/tls/msg_server_kex.cpp b/src/tls/msg_server_kex.cpp index 2d27c6f0d..6e238c4fd 100644 --- a/src/tls/msg_server_kex.cpp +++ b/src/tls/msg_server_kex.cpp @@ -35,7 +35,7 @@ Server_Key_Exchange::Server_Key_Exchange(Handshake_IO& io, const Private_Key* signing_key) : m_kex_key(nullptr), m_srp_params(nullptr) { - const std::string hostname = state->client_hello->sni_hostname(); + const std::string hostname = state->client_hello()->sni_hostname(); const std::string kex_algo = state->suite.kex_algo(); if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK") @@ -58,7 +58,7 @@ Server_Key_Exchange::Server_Key_Exchange(Handshake_IO& io, else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK") { const std::vector<std::string>& curves = - state->client_hello->supported_ecc_curves(); + state->client_hello()->supported_ecc_curves(); if(curves.empty()) throw Internal_Error("Client sent no ECC extension but we negotiated ECDH"); @@ -91,7 +91,7 @@ Server_Key_Exchange::Server_Key_Exchange(Handshake_IO& io, } else if(kex_algo == "SRP_SHA") { - const std::string srp_identifier = state->client_hello->srp_identifier(); + const std::string srp_identifier = state->client_hello()->srp_identifier(); std::string group_id; BigInt v; @@ -130,8 +130,8 @@ Server_Key_Exchange::Server_Key_Exchange(Handshake_IO& io, PK_Signer signer(*signing_key, format.first, format.second); - signer.update(state->client_hello->random()); - signer.update(state->server_hello->random()); + signer.update(state->client_hello()->random()); + signer.update(state->server_hello()->random()); signer.update(params()); m_signature = signer.signature(rng); } @@ -270,8 +270,8 @@ bool Server_Key_Exchange::verify(const X509_Certificate& cert, PK_Verifier verifier(*key, format.first, format.second); - verifier.update(state->client_hello->random()); - verifier.update(state->server_hello->random()); + verifier.update(state->client_hello()->random()); + verifier.update(state->server_hello()->random()); verifier.update(params()); return verifier.check_signature(m_signature); @@ -284,7 +284,7 @@ const Private_Key& Server_Key_Exchange::server_kex_key() const } // Only valid for SRP negotiation -SRP6_Server_Session& Server_Key_Exchange::server_srp_params() +SRP6_Server_Session& Server_Key_Exchange::server_srp_params() const { BOTAN_ASSERT_NONNULL(m_srp_params); return *m_srp_params; diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp index 2951bbeb0..253110c81 100644 --- a/src/tls/tls_channel.cpp +++ b/src/tls/tls_channel.cpp @@ -228,7 +228,7 @@ void Channel::send_alert(const Alert& alert) } } -void Channel::Secure_Renegotiation_State::update(Client_Hello* client_hello) +void Channel::Secure_Renegotiation_State::update(const Client_Hello* client_hello) { if(initial_handshake()) { @@ -260,7 +260,7 @@ void Channel::Secure_Renegotiation_State::update(Client_Hello* client_hello) } } -void Channel::Secure_Renegotiation_State::update(Server_Hello* server_hello) +void Channel::Secure_Renegotiation_State::update(const Server_Hello* server_hello) { if(initial_handshake()) { @@ -298,8 +298,8 @@ void Channel::Secure_Renegotiation_State::update(Server_Hello* server_hello) m_initial_handshake = false; } -void Channel::Secure_Renegotiation_State::update(Finished* client_finished, - Finished* server_finished) +void Channel::Secure_Renegotiation_State::update(const Finished* client_finished, + const Finished* server_finished) { m_client_verify = client_finished->verify_data(); m_server_verify = server_finished->verify_data(); diff --git a/src/tls/tls_channel.h b/src/tls/tls_channel.h index 7a538fb9d..ae8791f6b 100644 --- a/src/tls/tls_channel.h +++ b/src/tls/tls_channel.h @@ -118,11 +118,11 @@ class BOTAN_DLL Channel m_secure_renegotiation(false) {} - void update(class Client_Hello* client_hello); - void update(class Server_Hello* server_hello); + void update(const class Client_Hello* client_hello); + void update(const class Server_Hello* server_hello); - void update(class Finished* client_finished, - class Finished* server_finished); + void update(const class Finished* client_finished, + const class Finished* server_finished); const std::vector<byte>& for_client_hello() const { return m_client_verify; } diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp index e72dcbc8f..e0f9b11d8 100644 --- a/src/tls/tls_client.cpp +++ b/src/tls/tls_client.cpp @@ -51,7 +51,7 @@ Handshake_State* Client::new_handshake_state() */ void Client::renegotiate(bool force_full_renegotiation) { - if(m_state && m_state->client_hello) + if(m_state && m_state->client_hello()) return; // currently in active handshake m_state.reset(); @@ -86,23 +86,23 @@ void Client::initiate_handshake(bool force_full_renegotiation, { if(srp_identifier == "" || session_info.srp_identifier() == srp_identifier) { - m_state->client_hello = new Client_Hello( + m_state->client_hello(new Client_Hello( m_state->handshake_io(), m_state->hash, m_policy, m_rng, m_secure_renegotiation.for_client_hello(), session_info, - send_npn_request); + send_npn_request)); m_state->resume_master_secret = session_info.master_secret(); } } } - if(!m_state->client_hello) // not resuming + if(!m_state->client_hello()) // not resuming { - m_state->client_hello = new Client_Hello( + m_state->client_hello(new Client_Hello( m_state->handshake_io(), m_state->hash, version, @@ -111,10 +111,10 @@ void Client::initiate_handshake(bool force_full_renegotiation, m_secure_renegotiation.for_client_hello(), send_npn_request, m_hostname, - srp_identifier); + srp_identifier)); } - m_secure_renegotiation.update(m_state->client_hello); + m_secure_renegotiation.update(m_state->client_hello()); } void Client::alert_notify(const Alert& alert) @@ -140,7 +140,7 @@ void Client::process_handshake_msg(Handshake_Type type, Hello_Request hello_request(contents); // Ignore request entirely if we are currently negotiating a handshake - if(m_state->client_hello) + if(m_state->client_hello()) return; if(!m_secure_renegotiation.supported() && !m_policy.allow_insecure_renegotiation()) @@ -172,58 +172,57 @@ void Client::process_handshake_msg(Handshake_Type type, std::unique_ptr<Client_Hello> client_hello_w_cookie( new Client_Hello(m_state->handshake_io(), m_state->hash, - *m_state->client_hello, + *m_state->client_hello(), hello_verify_request)); - delete m_state->client_hello; - m_state->client_hello = client_hello_w_cookie.release(); + m_state->client_hello(client_hello_w_cookie.release()); } else if(type == SERVER_HELLO) { - m_state->server_hello = new Server_Hello(contents); + m_state->server_hello(new Server_Hello(contents)); - if(!m_state->client_hello->offered_suite(m_state->server_hello->ciphersuite())) + if(!m_state->client_hello()->offered_suite(m_state->server_hello()->ciphersuite())) { throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Server replied with ciphersuite we didn't send"); } - if(!value_exists(m_state->client_hello->compression_methods(), - m_state->server_hello->compression_method())) + if(!value_exists(m_state->client_hello()->compression_methods(), + m_state->server_hello()->compression_method())) { throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Server replied with compression method we didn't send"); } - if(!m_state->client_hello->next_protocol_notification() && - m_state->server_hello->next_protocol_notification()) + if(!m_state->client_hello()->next_protocol_notification() && + m_state->server_hello()->next_protocol_notification()) { throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Server sent next protocol but we didn't request it"); } - if(m_state->server_hello->supports_session_ticket()) + if(m_state->server_hello()->supports_session_ticket()) { - if(!m_state->client_hello->supports_session_ticket()) + if(!m_state->client_hello()->supports_session_ticket()) throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Server sent session ticket extension but we did not"); } - m_state->set_version(m_state->server_hello->version()); + m_state->set_version(m_state->server_hello()->version()); m_writer.set_version(m_state->version()); m_reader.set_version(m_state->version()); - m_secure_renegotiation.update(m_state->server_hello); + m_secure_renegotiation.update(m_state->server_hello()); - m_peer_supports_heartbeats = m_state->server_hello->supports_heartbeats(); - m_heartbeat_sending_allowed = m_state->server_hello->peer_can_send_heartbeats(); + m_peer_supports_heartbeats = m_state->server_hello()->supports_heartbeats(); + m_heartbeat_sending_allowed = m_state->server_hello()->peer_can_send_heartbeats(); - m_state->suite = Ciphersuite::by_id(m_state->server_hello->ciphersuite()); + m_state->suite = Ciphersuite::by_id(m_state->server_hello()->ciphersuite()); const bool server_returned_same_session_id = - !m_state->server_hello->session_id().empty() && - (m_state->server_hello->session_id() == m_state->client_hello->session_id()); + !m_state->server_hello()->session_id().empty() && + (m_state->server_hello()->session_id() == m_state->client_hello()->session_id()); if(server_returned_same_session_id) { @@ -233,7 +232,7 @@ void Client::process_handshake_msg(Handshake_Type type, * In this case, we offered the version used in the original * session, and the server must resume with the same version. */ - if(m_state->server_hello->version() != m_state->client_hello->version()) + if(m_state->server_hello()->version() != m_state->client_hello()->version()) throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Server resumed session but with wrong version"); @@ -242,7 +241,7 @@ void Client::process_handshake_msg(Handshake_Type type, true); // The server is not strictly required to send us a new ticket - if(m_state->server_hello->supports_session_ticket()) + if(m_state->server_hello()->supports_session_ticket()) m_state->set_expected_next(NEW_SESSION_TICKET); m_state->set_expected_next(HANDSHAKE_CCS); @@ -251,7 +250,7 @@ void Client::process_handshake_msg(Handshake_Type type, { // new session - if(m_state->version() > m_state->client_hello->version()) + if(m_state->version() > m_state->client_hello()->version()) { throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Server replied with later version than in hello"); @@ -303,9 +302,9 @@ void Client::process_handshake_msg(Handshake_Type type, m_state->set_expected_next(SERVER_HELLO_DONE); } - m_state->server_certs = new Certificate(contents); + m_state->server_certs(new Certificate(contents)); - m_peer_certs = m_state->server_certs->cert_chain(); + m_peer_certs = m_state->server_certs()->cert_chain(); if(m_peer_certs.empty()) throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Client: No certificates sent by server"); @@ -330,14 +329,16 @@ void Client::process_handshake_msg(Handshake_Type type, m_state->set_expected_next(CERTIFICATE_REQUEST); // optional m_state->set_expected_next(SERVER_HELLO_DONE); - m_state->server_kex = new Server_Key_Exchange(contents, - m_state->suite.kex_algo(), - m_state->suite.sig_algo(), - m_state->version()); + m_state->server_kex( + new Server_Key_Exchange(contents, + m_state->suite.kex_algo(), + m_state->suite.sig_algo(), + m_state->version()) + ); if(m_state->suite.sig_algo() != "") { - if(!m_state->server_kex->verify(m_peer_certs[0], m_state.get())) + if(!m_state->server_kex()->verify(m_peer_certs[0], m_state.get())) { throw TLS_Exception(Alert::DECRYPT_ERROR, "Bad signature on server key exchange"); @@ -347,53 +348,62 @@ void Client::process_handshake_msg(Handshake_Type type, else if(type == CERTIFICATE_REQUEST) { m_state->set_expected_next(SERVER_HELLO_DONE); - m_state->cert_req = new Certificate_Req(contents, m_state->version()); + m_state->cert_req( + new Certificate_Req(contents, m_state->version()) + ); } else if(type == SERVER_HELLO_DONE) { - m_state->server_hello_done = new Server_Hello_Done(contents); + m_state->server_hello_done( + new Server_Hello_Done(contents) + ); if(m_state->received_handshake_msg(CERTIFICATE_REQUEST)) { const std::vector<std::string>& types = - m_state->cert_req->acceptable_cert_types(); + m_state->cert_req()->acceptable_cert_types(); std::vector<X509_Certificate> client_certs = m_creds.cert_chain(types, "tls-client", m_hostname); - m_state->client_certs = new Certificate(m_state->handshake_io(), - m_state->hash, - client_certs); + m_state->client_certs( + new Certificate(m_state->handshake_io(), + m_state->hash, + client_certs) + ); } - m_state->client_kex = + m_state->client_kex( new Client_Key_Exchange(m_state->handshake_io(), m_state.get(), m_policy, m_creds, m_peer_certs, m_hostname, - m_rng); + m_rng) + ); m_state->keys = Session_Keys(m_state.get(), - m_state->client_kex->pre_master_secret(), + m_state->client_kex()->pre_master_secret(), false); if(m_state->received_handshake_msg(CERTIFICATE_REQUEST) && - !m_state->client_certs->empty()) + !m_state->client_certs()->empty()) { Private_Key* private_key = - m_creds.private_key_for(m_state->client_certs->cert_chain()[0], + m_creds.private_key_for(m_state->client_certs()->cert_chain()[0], "tls-client", m_hostname); - m_state->client_verify = new Certificate_Verify(m_state->handshake_io(), - m_state.get(), - m_policy, - m_rng, - private_key); + m_state->client_verify( + new Certificate_Verify(m_state->handshake_io(), + m_state.get(), + m_policy, + m_rng, + private_key) + ); } m_writer.send(CHANGE_CIPHER_SPEC, 1); @@ -401,27 +411,30 @@ void Client::process_handshake_msg(Handshake_Type type, m_writer.change_cipher_spec(CLIENT, m_state->suite, m_state->keys, - m_state->server_hello->compression_method()); + m_state->server_hello()->compression_method()); - if(m_state->server_hello->next_protocol_notification()) + if(m_state->server_hello()->next_protocol_notification()) { const std::string protocol = - m_state->client_npn_cb(m_state->server_hello->next_protocols()); + m_state->client_npn_cb(m_state->server_hello()->next_protocols()); - m_state->next_protocol = new Next_Protocol(m_state->handshake_io(), m_state->hash, protocol); + m_state->next_protocol( + new Next_Protocol(m_state->handshake_io(), m_state->hash, protocol) + ); } - m_state->client_finished = new Finished(m_state->handshake_io(), - m_state.get(), CLIENT); + m_state->client_finished( + new Finished(m_state->handshake_io(), m_state.get(), CLIENT) + ); - if(m_state->server_hello->supports_session_ticket()) + if(m_state->server_hello()->supports_session_ticket()) m_state->set_expected_next(NEW_SESSION_TICKET); else m_state->set_expected_next(HANDSHAKE_CCS); } else if(type == NEW_SESSION_TICKET) { - m_state->new_session_ticket = new New_Session_Ticket(contents); + m_state->new_session_ticket(new New_Session_Ticket(contents)); m_state->set_expected_next(HANDSHAKE_CCS); } @@ -432,36 +445,38 @@ void Client::process_handshake_msg(Handshake_Type type, m_reader.change_cipher_spec(CLIENT, m_state->suite, m_state->keys, - m_state->server_hello->compression_method()); + m_state->server_hello()->compression_method()); } else if(type == FINISHED) { m_state->set_expected_next(HELLO_REQUEST); - m_state->server_finished = new Finished(contents); + m_state->server_finished(new Finished(contents)); - if(!m_state->server_finished->verify(m_state.get(), SERVER)) + if(!m_state->server_finished()->verify(m_state.get(), SERVER)) throw TLS_Exception(Alert::DECRYPT_ERROR, "Finished message didn't verify"); m_state->hash.update(m_state->handshake_io().format(contents, type)); - if(!m_state->client_finished) // session resume case + if(!m_state->client_finished()) // session resume case { m_writer.send(CHANGE_CIPHER_SPEC, 1); m_writer.change_cipher_spec(CLIENT, m_state->suite, m_state->keys, - m_state->server_hello->compression_method()); + m_state->server_hello()->compression_method()); - m_state->client_finished = new Finished(m_state->handshake_io(), - m_state.get(), CLIENT); + m_state->client_finished( + new Finished(m_state->handshake_io(), m_state.get(), CLIENT) + ); } - m_secure_renegotiation.update(m_state->client_finished, m_state->server_finished); + m_secure_renegotiation.update(m_state->client_finished(), + m_state->server_finished()); - std::vector<byte> session_id = m_state->server_hello->session_id(); + std::vector<byte> session_id = m_state->server_hello()->session_id(); const std::vector<byte>& session_ticket = m_state->session_ticket(); @@ -471,12 +486,12 @@ void Client::process_handshake_msg(Handshake_Type type, Session session_info( session_id, m_state->keys.master_secret(), - m_state->server_hello->version(), - m_state->server_hello->ciphersuite(), - m_state->server_hello->compression_method(), + m_state->server_hello()->version(), + m_state->server_hello()->ciphersuite(), + m_state->server_hello()->compression_method(), CLIENT, m_secure_renegotiation.supported(), - m_state->server_hello->fragment_size(), + m_state->server_hello()->fragment_size(), m_peer_certs, session_ticket, m_hostname, diff --git a/src/tls/tls_handshake_hash.cpp b/src/tls/tls_handshake_hash.cpp index ba3ee52db..440c6fb82 100644 --- a/src/tls/tls_handshake_hash.cpp +++ b/src/tls/tls_handshake_hash.cpp @@ -19,7 +19,7 @@ namespace TLS { * Return a TLS Handshake Hash */ secure_vector<byte> Handshake_Hash::final(Protocol_Version version, - const std::string& mac_algo) + const std::string& mac_algo) const { Algorithm_Factory& af = global_state().algorithm_factory(); @@ -42,7 +42,7 @@ secure_vector<byte> Handshake_Hash::final(Protocol_Version version, /** * Return a SSLv3 Handshake Hash */ -secure_vector<byte> Handshake_Hash::final_ssl3(const secure_vector<byte>& secret) +secure_vector<byte> Handshake_Hash::final_ssl3(const secure_vector<byte>& secret) const { const byte PAD_INNER = 0x36, PAD_OUTER = 0x5C; diff --git a/src/tls/tls_handshake_hash.h b/src/tls/tls_handshake_hash.h index e7fc24f64..840895963 100644 --- a/src/tls/tls_handshake_hash.h +++ b/src/tls/tls_handshake_hash.h @@ -31,9 +31,9 @@ class Handshake_Hash { data += in; } secure_vector<byte> final(Protocol_Version version, - const std::string& mac_algo); + const std::string& mac_algo) const; - secure_vector<byte> final_ssl3(const secure_vector<byte>& master_secret); + secure_vector<byte> final_ssl3(const secure_vector<byte>& master_secret) const; const std::vector<byte>& get_contents() const { return data; } diff --git a/src/tls/tls_handshake_state.cpp b/src/tls/tls_handshake_state.cpp index 2046652ec..8e9d6b0ba 100644 --- a/src/tls/tls_handshake_state.cpp +++ b/src/tls/tls_handshake_state.cpp @@ -1,6 +1,6 @@ /* * TLS Handshaking -* (C) 2004-2006,2011 Jack Lloyd +* (C) 2004-2006,2011,2012 Jack Lloyd * * Released under the terms of the Botan license */ @@ -91,6 +91,73 @@ Handshake_State::Handshake_State(Handshake_IO* io) : { } +Handshake_State::~Handshake_State() {} + +void Handshake_State::client_hello(Client_Hello* client_hello) + { + m_client_hello.reset(client_hello); + } + +void Handshake_State::server_hello(Server_Hello* server_hello) + { + m_server_hello.reset(server_hello); + } + +void Handshake_State::server_certs(Certificate* server_certs) + { + m_server_certs.reset(server_certs); + } + +void Handshake_State::server_kex(Server_Key_Exchange* server_kex) + { + m_server_kex.reset(server_kex); + } + +void Handshake_State::cert_req(Certificate_Req* cert_req) + { + m_cert_req.reset(cert_req); + } + +void Handshake_State::server_hello_done(Server_Hello_Done* server_hello_done) + { + m_server_hello_done.reset(server_hello_done); + } + +void Handshake_State::client_certs(Certificate* client_certs) + { + m_client_certs.reset(client_certs); + } + +void Handshake_State::client_kex(Client_Key_Exchange* client_kex) + { + m_client_kex.reset(client_kex); + } + +void Handshake_State::client_verify(Certificate_Verify* client_verify) + { + m_client_verify.reset(client_verify); + } + +void Handshake_State::next_protocol(Next_Protocol* next_protocol) + { + m_next_protocol.reset(next_protocol); + } + +void Handshake_State::new_session_ticket(New_Session_Ticket* new_session_ticket) + { + m_new_session_ticket.reset(new_session_ticket); + } + +void Handshake_State::server_finished(Finished* server_finished) + { + m_server_finished.reset(server_finished); + } + +void Handshake_State::client_finished(Finished* client_finished) + { + m_client_finished.reset(client_finished); + } + void Handshake_State::set_version(const Protocol_Version& version) { m_version = version; @@ -132,20 +199,20 @@ bool Handshake_State::received_handshake_msg(Handshake_Type handshake_msg) const std::string Handshake_State::srp_identifier() const { if(suite.valid() && suite.kex_algo() == "SRP_SHA") - return client_hello->srp_identifier(); + return client_hello()->srp_identifier(); return ""; } const std::vector<byte>& Handshake_State::session_ticket() const { - if(new_session_ticket && !new_session_ticket->ticket().empty()) - return new_session_ticket->ticket(); + if(new_session_ticket() && !new_session_ticket()->ticket().empty()) + return new_session_ticket()->ticket(); - return client_hello->session_ticket(); + return client_hello()->session_ticket(); } -KDF* Handshake_State::protocol_specific_prf() +KDF* Handshake_State::protocol_specific_prf() const { if(version() == Protocol_Version::SSL_V3) { @@ -173,8 +240,8 @@ std::string choose_hash(const std::string& sig_algo, Protocol_Version negotiated_version, const Policy& policy, bool for_client_auth, - Client_Hello* client_hello, - Certificate_Req* cert_req) + const Client_Hello* client_hello, + const Certificate_Req* cert_req) { if(!negotiated_version.supports_negotiable_signature_algorithms()) { @@ -226,7 +293,7 @@ Handshake_State::choose_sig_format(const Private_Key* key, std::string& hash_algo_out, std::string& sig_algo_out, bool for_client_auth, - const Policy& policy) + const Policy& policy) const { const std::string sig_algo = key->algo_name(); @@ -235,8 +302,8 @@ Handshake_State::choose_sig_format(const Private_Key* key, this->version(), policy, for_client_auth, - client_hello, - cert_req); + client_hello(), + cert_req()); if(this->version().supports_negotiable_signature_algorithms()) { @@ -264,7 +331,7 @@ std::pair<std::string, Signature_Format> Handshake_State::understand_sig_format(const Public_Key* key, std::string hash_algo, std::string sig_algo, - bool for_client_auth) + bool for_client_auth) const { const std::string algo_name = key->algo_name(); @@ -323,29 +390,6 @@ Handshake_State::understand_sig_format(const Public_Key* key, throw Invalid_Argument(algo_name + " is invalid/unknown for TLS signatures"); } -/* -* Destroy the SSL/TLS Handshake State -*/ -Handshake_State::~Handshake_State() - { - delete client_hello; - delete server_hello; - delete server_certs; - delete server_kex; - delete cert_req; - delete server_hello_done; - delete next_protocol; - delete new_session_ticket; - - delete client_certs; - delete client_kex; - delete client_verify; - delete client_finished; - delete server_finished; - - delete m_handshake_io; - } - } } diff --git a/src/tls/tls_handshake_state.h b/src/tls/tls_handshake_state.h index 49470fecb..7dea555cc 100644 --- a/src/tls/tls_handshake_state.h +++ b/src/tls/tls_handshake_state.h @@ -1,6 +1,6 @@ /* * TLS Handshake State -* (C) 2004-2006 Jack Lloyd +* (C) 2004-2006,2011,2012 Jack Lloyd * * Released under the terms of the Botan license */ @@ -16,6 +16,7 @@ #include <functional> #include <utility> +#include <memory> namespace Botan { @@ -25,6 +26,19 @@ namespace TLS { class Policy; +class Client_Hello; +class Server_Hello; +class Certificate; +class Server_Key_Exchange; +class Certificate_Req; +class Server_Hello_Done; +class Certificate; +class Client_Key_Exchange; +class Certificate_Verify; +class Next_Protocol; +class New_Session_Ticket; +class Finished; + /** * SSL/TLS Handshake State */ @@ -38,6 +52,8 @@ class Handshake_State Handshake_State(const Handshake_State&) = delete; Handshake_State& operator=(const Handshake_State&) = delete; + Handshake_IO& handshake_io() { return *m_handshake_io; } + bool received_handshake_msg(Handshake_Type handshake_msg) const; void confirm_transition_to(Handshake_Type handshake_msg); @@ -49,70 +65,119 @@ class Handshake_State understand_sig_format(const Public_Key* key, std::string hash_algo, std::string sig_algo, - bool for_client_auth); + bool for_client_auth) const; std::pair<std::string, Signature_Format> choose_sig_format(const Private_Key* key, std::string& hash_algo, std::string& sig_algo, bool for_client_auth, - const Policy& policy); + const Policy& policy) const; std::string srp_identifier() const; - KDF* protocol_specific_prf(); + KDF* protocol_specific_prf() const; Protocol_Version version() const { return m_version; } void set_version(const Protocol_Version& version); - class Client_Hello* client_hello = nullptr; - class Server_Hello* server_hello = nullptr; - class Certificate* server_certs = nullptr; - class Server_Key_Exchange* server_kex = nullptr; - class Certificate_Req* cert_req = nullptr; - class Server_Hello_Done* server_hello_done = nullptr; + void client_hello(Client_Hello* client_hello); + void server_hello(Server_Hello* server_hello); + void server_certs(Certificate* server_certs); + void server_kex(Server_Key_Exchange* server_kex); + void cert_req(Certificate_Req* cert_req); + void server_hello_done(Server_Hello_Done* server_hello_done); + void client_certs(Certificate* client_certs); + void client_kex(Client_Key_Exchange* client_kex); + void client_verify(Certificate_Verify* client_verify); + void next_protocol(Next_Protocol* next_protocol); + void new_session_ticket(New_Session_Ticket* new_session_ticket); + void server_finished(Finished* server_finished); + void client_finished(Finished* client_finished); + + const Client_Hello* client_hello() const + { return m_client_hello.get(); } + + const Server_Hello* server_hello() const + { return m_server_hello.get(); } + + const Certificate* server_certs() const + { return m_server_certs.get(); } + + const Server_Key_Exchange* server_kex() const + { return m_server_kex.get(); } + + const Certificate_Req* cert_req() const + { return m_cert_req.get(); } - class Certificate* client_certs = nullptr; - class Client_Key_Exchange* client_kex = nullptr; - class Certificate_Verify* client_verify = nullptr; + const Server_Hello_Done* server_hello_done() const + { return m_server_hello_done.get(); } - class Next_Protocol* next_protocol = nullptr; - class New_Session_Ticket* new_session_ticket = nullptr; + const Certificate* client_certs() const + { return m_client_certs.get(); } - class Finished* client_finished = nullptr; - class Finished* server_finished = nullptr; + const Client_Key_Exchange* client_kex() const + { return m_client_kex.get(); } + + const Certificate_Verify* client_verify() const + { return m_client_verify.get(); } + + const Next_Protocol* next_protocol() const + { return m_next_protocol.get(); } + + const New_Session_Ticket* new_session_ticket() const + { return m_new_session_ticket.get(); } + + const Finished* server_finished() const + { return m_server_finished.get(); } + + const Finished* client_finished() const + { return m_client_finished.get(); } // Used by the server only, in case of RSA key exchange - Private_Key* server_rsa_kex_key = nullptr; + Private_Key* server_rsa_kex_key = nullptr; // FIXME make private - Ciphersuite suite; - Session_Keys keys; - Handshake_Hash hash; + Ciphersuite suite; // FIXME make private + Session_Keys keys; // FIXME make private + Handshake_Hash hash; // FIXME make private /* * Only used by clients for session resumption */ - secure_vector<byte> resume_master_secret; + secure_vector<byte> resume_master_secret; // FIXME make private /* * Used by the server to know if resumption should be allowed on * a server-initiated renegotiation */ - bool allow_session_resumption = true; + bool allow_session_resumption = true; // FIXME make private /** - * Used by client using NPN + * Used by client using NPN FIXME make private */ std::function<std::string (std::vector<std::string>)> client_npn_cb; - Handshake_IO& handshake_io() { return *m_handshake_io; } private: - Handshake_IO* m_handshake_io = nullptr; + std::unique_ptr<Handshake_IO> m_handshake_io; u32bit m_hand_expecting_mask = 0; u32bit m_hand_received_mask = 0; Protocol_Version m_version; + + std::unique_ptr<Client_Hello> m_client_hello; + std::unique_ptr<Server_Hello> m_server_hello; + std::unique_ptr<Certificate> m_server_certs; + std::unique_ptr<Server_Key_Exchange> m_server_kex; + std::unique_ptr<Certificate_Req> m_cert_req; + std::unique_ptr<Server_Hello_Done> m_server_hello_done; + std::unique_ptr<Certificate> m_client_certs; + std::unique_ptr<Client_Key_Exchange> m_client_kex; + std::unique_ptr<Certificate_Verify> m_client_verify; + std::unique_ptr<Next_Protocol> m_next_protocol; + std::unique_ptr<New_Session_Ticket> m_new_session_ticket; + std::unique_ptr<Finished> m_server_finished; + std::unique_ptr<Finished> m_client_finished; }; } diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index 2834a916e..23b1d5634 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -91,7 +91,7 @@ class Client_Hello : public Handshake_Message bool secure_renegotiation() const { return m_secure_renegotiation; } - const std::vector<byte>& renegotiation_info() + const std::vector<byte>& renegotiation_info() const { return m_renegotiation_info; } bool offered_suite(u16bit ciphersuite) const; @@ -172,7 +172,7 @@ class Server_Hello : public Handshake_Message public: Handshake_Type type() const { return SERVER_HELLO; } - Protocol_Version version() { return m_version; } + Protocol_Version version() const { return m_version; } const std::vector<byte>& random() const { return m_random; } @@ -193,7 +193,7 @@ class Server_Hello : public Handshake_Message size_t fragment_size() const { return m_fragment_size; } - const std::vector<byte>& renegotiation_info() + const std::vector<byte>& renegotiation_info() const { return m_renegotiation_info; } bool supports_heartbeats() const { return m_supports_heartbeats; } @@ -338,7 +338,7 @@ class Certificate_Verify : public Handshake_Message * @param state the handshake state */ bool verify(const X509_Certificate& cert, - Handshake_State* state); + const Handshake_State* state) const; Certificate_Verify(Handshake_IO& io, Handshake_State* state, @@ -368,7 +368,7 @@ class Finished : public Handshake_Message { return m_verification_data; } bool verify(Handshake_State* state, - Connection_Side side); + Connection_Side side) const; Finished(Handshake_IO& io, Handshake_State* state, @@ -413,7 +413,7 @@ class Server_Key_Exchange : public Handshake_Message const Private_Key& server_kex_key() const; // Only valid for SRP negotiation - SRP6_Server_Session& server_srp_params(); + SRP6_Server_Session& server_srp_params() const; Server_Key_Exchange(Handshake_IO& io, Handshake_State* state, diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index 25716c144..9669693c5 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -21,7 +21,7 @@ namespace { bool check_for_resume(Session& session_info, Session_Manager& session_manager, Credentials_Manager& credentials, - Client_Hello* client_hello, + const Client_Hello* client_hello, std::chrono::seconds session_ticket_lifetime) { const std::vector<byte>& client_session_id = client_hello->session_id(); @@ -271,12 +271,12 @@ void Server::process_handshake_msg(Handshake_Type type, return; } - m_state->client_hello = new Client_Hello(contents, type); + m_state->client_hello(new Client_Hello(contents, type)); - if(m_state->client_hello->sni_hostname() != "") - m_hostname = m_state->client_hello->sni_hostname(); + if(m_state->client_hello()->sni_hostname() != "") + m_hostname = m_state->client_hello()->sni_hostname(); - Protocol_Version client_version = m_state->client_hello->version(); + Protocol_Version client_version = m_state->client_hello()->version(); const Protocol_Version prev_version = m_reader.get_version(); const bool is_renegotiation = prev_version.valid(); @@ -328,10 +328,10 @@ void Server::process_handshake_msg(Handshake_Type type, "Client version is unacceptable by policy"); } - m_secure_renegotiation.update(m_state->client_hello); + m_secure_renegotiation.update(m_state->client_hello()); - m_peer_supports_heartbeats = m_state->client_hello->supports_heartbeats(); - m_heartbeat_sending_allowed = m_state->client_hello->peer_can_send_heartbeats(); + m_peer_supports_heartbeats = m_state->client_hello()->supports_heartbeats(); + m_heartbeat_sending_allowed = m_state->client_hello()->peer_can_send_heartbeats(); m_writer.set_version(m_state->version()); m_reader.set_version(m_state->version()); @@ -342,7 +342,7 @@ void Server::process_handshake_msg(Handshake_Type type, check_for_resume(session_info, m_session_manager, m_creds, - m_state->client_hello, + m_state->client_hello(), std::chrono::seconds(m_policy.session_ticket_lifetime())); bool have_session_ticket_key = false; @@ -358,25 +358,30 @@ void Server::process_handshake_msg(Handshake_Type type, { // resume session - m_state->server_hello = new Server_Hello( - m_state->handshake_io(), - m_state->hash, - m_state->client_hello->session_id(), - Protocol_Version(session_info.version()), - session_info.ciphersuite_code(), - session_info.compression_method(), - session_info.fragment_size(), - m_secure_renegotiation.supported(), - m_secure_renegotiation.for_server_hello(), - (m_state->client_hello->supports_session_ticket() && - m_state->client_hello->session_ticket().empty() && - have_session_ticket_key), - m_state->client_hello->next_protocol_notification(), - m_possible_protocols, - m_state->client_hello->supports_heartbeats(), - m_rng); + const bool offer_new_session_ticket = + (m_state->client_hello()->supports_session_ticket() && + m_state->client_hello()->session_ticket().empty() && + have_session_ticket_key); + + m_state->server_hello( + new Server_Hello( + m_state->handshake_io(), + m_state->hash, + m_state->client_hello()->session_id(), + Protocol_Version(session_info.version()), + session_info.ciphersuite_code(), + session_info.compression_method(), + session_info.fragment_size(), + m_secure_renegotiation.supported(), + m_secure_renegotiation.for_server_hello(), + offer_new_session_ticket, + m_state->client_hello()->next_protocol_notification(), + m_possible_protocols, + m_state->client_hello()->supports_heartbeats(), + m_rng) + ); - m_secure_renegotiation.update(m_state->server_hello); + m_secure_renegotiation.update(m_state->server_hello()); if(session_info.fragment_size()) { @@ -384,7 +389,7 @@ void Server::process_handshake_msg(Handshake_Type type, m_writer.set_maximum_fragment_size(session_info.fragment_size()); } - m_state->suite = Ciphersuite::by_id(m_state->server_hello->ciphersuite()); + m_state->suite = Ciphersuite::by_id(m_state->server_hello()->ciphersuite()); m_state->keys = Session_Keys(m_state.get(), session_info.master_secret(), true); @@ -392,33 +397,35 @@ void Server::process_handshake_msg(Handshake_Type type, { m_session_manager.remove_entry(session_info.session_id()); - if(m_state->server_hello->supports_session_ticket()) // send an empty ticket + if(m_state->server_hello()->supports_session_ticket()) // send an empty ticket { - m_state->new_session_ticket = + m_state->new_session_ticket( new New_Session_Ticket(m_state->handshake_io(), - m_state->hash); + m_state->hash) + ); } } - if(m_state->server_hello->supports_session_ticket() && !m_state->new_session_ticket) + if(m_state->server_hello()->supports_session_ticket() && !m_state->new_session_ticket()) { try { const SymmetricKey ticket_key = m_creds.psk("tls-server", "session-ticket", ""); - m_state->new_session_ticket = + m_state->new_session_ticket( new New_Session_Ticket(m_state->handshake_io(), m_state->hash, session_info.encrypt(ticket_key, m_rng), - m_policy.session_ticket_lifetime()); + m_policy.session_ticket_lifetime()) + ); } catch(...) {} - if(!m_state->new_session_ticket) + if(!m_state->new_session_ticket()) { - m_state->new_session_ticket = - new New_Session_Ticket(m_state->handshake_io(), - m_state->hash); + m_state->new_session_ticket( + new New_Session_Ticket(m_state->handshake_io(), m_state->hash) + ); } } @@ -427,10 +434,11 @@ void Server::process_handshake_msg(Handshake_Type type, m_writer.change_cipher_spec(SERVER, m_state->suite, m_state->keys, - m_state->server_hello->compression_method()); + m_state->server_hello()->compression_method()); - m_state->server_finished = new Finished(m_state->handshake_io(), - m_state.get(), SERVER); + m_state->server_finished( + new Finished(m_state->handshake_io(), m_state.get(), SERVER) + ); m_state->set_expected_next(HANDSHAKE_CCS); } @@ -455,35 +463,37 @@ void Server::process_handshake_msg(Handshake_Type type, send_alert(Alert(Alert::UNRECOGNIZED_NAME)); } - m_state->server_hello = new Server_Hello( - m_state->handshake_io(), - m_state->hash, - make_hello_random(m_rng), // new session ID - m_state->version(), - choose_ciphersuite(m_policy, - m_state->version(), - m_creds, - cert_chains, - m_state->client_hello), - choose_compression(m_policy, m_state->client_hello->compression_methods()), - m_state->client_hello->fragment_size(), - m_secure_renegotiation.supported(), - m_secure_renegotiation.for_server_hello(), - m_state->client_hello->supports_session_ticket() && have_session_ticket_key, - m_state->client_hello->next_protocol_notification(), - m_possible_protocols, - m_state->client_hello->supports_heartbeats(), - m_rng); + m_state->server_hello( + new Server_Hello( + m_state->handshake_io(), + m_state->hash, + make_hello_random(m_rng), // new session ID + m_state->version(), + choose_ciphersuite(m_policy, + m_state->version(), + m_creds, + cert_chains, + m_state->client_hello()), + choose_compression(m_policy, m_state->client_hello()->compression_methods()), + m_state->client_hello()->fragment_size(), + m_secure_renegotiation.supported(), + m_secure_renegotiation.for_server_hello(), + m_state->client_hello()->supports_session_ticket() && have_session_ticket_key, + m_state->client_hello()->next_protocol_notification(), + m_possible_protocols, + m_state->client_hello()->supports_heartbeats(), + m_rng) + ); - m_secure_renegotiation.update(m_state->server_hello); + m_secure_renegotiation.update(m_state->server_hello()); - if(m_state->client_hello->fragment_size()) + if(m_state->client_hello()->fragment_size()) { - m_reader.set_maximum_fragment_size(m_state->client_hello->fragment_size()); - m_writer.set_maximum_fragment_size(m_state->client_hello->fragment_size()); + m_reader.set_maximum_fragment_size(m_state->client_hello()->fragment_size()); + m_writer.set_maximum_fragment_size(m_state->client_hello()->fragment_size()); } - m_state->suite = Ciphersuite::by_id(m_state->server_hello->ciphersuite()); + m_state->suite = Ciphersuite::by_id(m_state->server_hello()->ciphersuite()); const std::string sig_algo = m_state->suite.sig_algo(); const std::string kex_algo = m_state->suite.kex_algo(); @@ -493,9 +503,11 @@ void Server::process_handshake_msg(Handshake_Type type, BOTAN_ASSERT(!cert_chains[sig_algo].empty(), "Attempting to send empty certificate chain"); - m_state->server_certs = new Certificate(m_state->handshake_io(), - m_state->hash, - cert_chains[sig_algo]); + m_state->server_certs( + new Certificate(m_state->handshake_io(), + m_state->hash, + cert_chains[sig_algo]) + ); } Private_Key* private_key = nullptr; @@ -503,7 +515,7 @@ void Server::process_handshake_msg(Handshake_Type type, if(kex_algo == "RSA" || sig_algo != "") { private_key = m_creds.private_key_for( - m_state->server_certs->cert_chain()[0], + m_state->server_certs()->cert_chain()[0], "tls-server", m_hostname); @@ -517,13 +529,14 @@ void Server::process_handshake_msg(Handshake_Type type, } else { - m_state->server_kex = + m_state->server_kex( new Server_Key_Exchange(m_state->handshake_io(), m_state.get(), m_policy, m_creds, m_rng, - private_key); + private_key) + ); } std::vector<X509_Certificate> client_auth_CAs = @@ -531,11 +544,13 @@ void Server::process_handshake_msg(Handshake_Type type, if(!client_auth_CAs.empty() && m_state->suite.sig_algo() != "") { - m_state->cert_req = new Certificate_Req(m_state->handshake_io(), - m_state->hash, - m_policy, - client_auth_CAs, - m_state->version()); + m_state->cert_req( + new Certificate_Req(m_state->handshake_io(), + m_state->hash, + m_policy, + client_auth_CAs, + m_state->version()) + ); m_state->set_expected_next(CERTIFICATE); } @@ -547,42 +562,41 @@ void Server::process_handshake_msg(Handshake_Type type, */ m_state->set_expected_next(CLIENT_KEX); - m_state->server_hello_done = new Server_Hello_Done(m_state->handshake_io(), - m_state->hash); + m_state->server_hello_done( + new Server_Hello_Done(m_state->handshake_io(), m_state->hash) + ); } } else if(type == CERTIFICATE) { - m_state->client_certs = new Certificate(contents); + m_state->client_certs(new Certificate(contents)); m_state->set_expected_next(CLIENT_KEX); } else if(type == CLIENT_KEX) { - if(m_state->received_handshake_msg(CERTIFICATE) && !m_state->client_certs->empty()) + if(m_state->received_handshake_msg(CERTIFICATE) && !m_state->client_certs()->empty()) m_state->set_expected_next(CERTIFICATE_VERIFY); else m_state->set_expected_next(HANDSHAKE_CCS); - m_state->client_kex = new Client_Key_Exchange(contents, - m_state.get(), - m_creds, - m_policy, - m_rng); + m_state->client_kex( + new Client_Key_Exchange(contents, m_state.get(), m_creds, m_policy, m_rng) + ); m_state->keys = Session_Keys(m_state.get(), - m_state->client_kex->pre_master_secret(), + m_state->client_kex()->pre_master_secret(), false); } else if(type == CERTIFICATE_VERIFY) { - m_state->client_verify = new Certificate_Verify(contents, m_state->version()); + m_state->client_verify(new Certificate_Verify(contents, m_state->version())); - m_peer_certs = m_state->client_certs->cert_chain(); + m_peer_certs = m_state->client_certs()->cert_chain(); const bool sig_valid = - m_state->client_verify->verify(m_peer_certs[0], m_state.get()); + m_state->client_verify()->verify(m_peer_certs[0], m_state.get()); m_state->hash.update(m_state->handshake_io().format(contents, type)); @@ -607,7 +621,7 @@ void Server::process_handshake_msg(Handshake_Type type, } else if(type == HANDSHAKE_CCS) { - if(m_state->server_hello->next_protocol_notification()) + if(m_state->server_hello()->next_protocol_notification()) m_state->set_expected_next(NEXT_PROTOCOL); else m_state->set_expected_next(FINISHED); @@ -615,41 +629,42 @@ void Server::process_handshake_msg(Handshake_Type type, m_reader.change_cipher_spec(SERVER, m_state->suite, m_state->keys, - m_state->server_hello->compression_method()); + m_state->server_hello()->compression_method()); } else if(type == NEXT_PROTOCOL) { m_state->set_expected_next(FINISHED); - m_state->next_protocol = new Next_Protocol(contents); + m_state->next_protocol(new Next_Protocol(contents)); - m_next_protocol = m_state->next_protocol->protocol(); + // should this be a callback? + m_next_protocol = m_state->next_protocol()->protocol(); } else if(type == FINISHED) { m_state->set_expected_next(HANDSHAKE_NONE); - m_state->client_finished = new Finished(contents); + m_state->client_finished(new Finished(contents)); - if(!m_state->client_finished->verify(m_state.get(), CLIENT)) + if(!m_state->client_finished()->verify(m_state.get(), CLIENT)) throw TLS_Exception(Alert::DECRYPT_ERROR, "Finished message didn't verify"); - if(!m_state->server_finished) + if(!m_state->server_finished()) { // already sent finished if resuming, so this is a new session m_state->hash.update(m_state->handshake_io().format(contents, type)); Session session_info( - m_state->server_hello->session_id(), + m_state->server_hello()->session_id(), m_state->keys.master_secret(), - m_state->server_hello->version(), - m_state->server_hello->ciphersuite(), - m_state->server_hello->compression_method(), + m_state->server_hello()->version(), + m_state->server_hello()->ciphersuite(), + m_state->server_hello()->compression_method(), SERVER, m_secure_renegotiation.supported(), - m_state->server_hello->fragment_size(), + m_state->server_hello()->fragment_size(), m_peer_certs, std::vector<byte>(), m_hostname, @@ -658,17 +673,18 @@ void Server::process_handshake_msg(Handshake_Type type, if(m_handshake_fn(session_info)) { - if(m_state->server_hello->supports_session_ticket()) + if(m_state->server_hello()->supports_session_ticket()) { try { const SymmetricKey ticket_key = m_creds.psk("tls-server", "session-ticket", ""); - m_state->new_session_ticket = + m_state->new_session_ticket( new New_Session_Ticket(m_state->handshake_io(), m_state->hash, session_info.encrypt(ticket_key, m_rng), - m_policy.session_ticket_lifetime()); + m_policy.session_ticket_lifetime()) + ); } catch(...) {} } @@ -676,11 +692,12 @@ void Server::process_handshake_msg(Handshake_Type type, m_session_manager.save(session_info); } - if(m_state->server_hello->supports_session_ticket() && !m_state->new_session_ticket) + if(!m_state->new_session_ticket() && + m_state->server_hello()->supports_session_ticket()) { - m_state->new_session_ticket = new New_Session_Ticket(m_state->handshake_io(), - m_state->hash); - + m_state->new_session_ticket( + new New_Session_Ticket(m_state->handshake_io(), m_state->hash) + ); } m_writer.send(CHANGE_CIPHER_SPEC, 1); @@ -688,16 +705,17 @@ void Server::process_handshake_msg(Handshake_Type type, m_writer.change_cipher_spec(SERVER, m_state->suite, m_state->keys, - m_state->server_hello->compression_method()); + m_state->server_hello()->compression_method()); - m_state->server_finished = new Finished(m_state->handshake_io(), - m_state.get(), SERVER); + m_state->server_finished( + new Finished(m_state->handshake_io(), m_state.get(), SERVER) + ); } - m_secure_renegotiation.update(m_state->client_finished, - m_state->server_finished); + m_secure_renegotiation.update(m_state->client_finished(), + m_state->server_finished()); - m_active_session = m_state->server_hello->session_id(); + m_active_session = m_state->server_hello()->session_id(); m_state.reset(); m_handshake_completed = true; } diff --git a/src/tls/tls_session_key.cpp b/src/tls/tls_session_key.cpp index 0cd74a63a..bc636c0cb 100644 --- a/src/tls/tls_session_key.cpp +++ b/src/tls/tls_session_key.cpp @@ -18,7 +18,7 @@ namespace TLS { /** * Session_Keys Constructor */ -Session_Keys::Session_Keys(Handshake_State* state, +Session_Keys::Session_Keys(const Handshake_State* state, const secure_vector<byte>& pre_master_secret, bool resuming) { @@ -50,8 +50,8 @@ Session_Keys::Session_Keys(Handshake_State* state, if(state->version() != Protocol_Version::SSL_V3) salt += std::make_pair(MASTER_SECRET_MAGIC, sizeof(MASTER_SECRET_MAGIC)); - salt += state->client_hello->random(); - salt += state->server_hello->random(); + salt += state->client_hello()->random(); + salt += state->server_hello()->random(); master_sec = prf->derive_key(48, pre_master_secret, salt); } @@ -59,8 +59,8 @@ Session_Keys::Session_Keys(Handshake_State* state, secure_vector<byte> salt; if(state->version() != Protocol_Version::SSL_V3) salt += std::make_pair(KEY_GEN_MAGIC, sizeof(KEY_GEN_MAGIC)); - salt += state->server_hello->random(); - salt += state->client_hello->random(); + salt += state->server_hello()->random(); + salt += state->client_hello()->random(); SymmetricKey keyblock = prf->derive_key(prf_gen, master_sec, salt); diff --git a/src/tls/tls_session_key.h b/src/tls/tls_session_key.h index 0021694e3..b67606a08 100644 --- a/src/tls/tls_session_key.h +++ b/src/tls/tls_session_key.h @@ -35,7 +35,7 @@ class Session_Keys Session_Keys() {} - Session_Keys(class Handshake_State* state, + Session_Keys(const class Handshake_State* state, const secure_vector<byte>& pre_master, bool resuming); |