aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/tls/tls_server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/tls/tls_server.cpp')
-rw-r--r--src/lib/tls/tls_server.cpp372
1 files changed, 179 insertions, 193 deletions
diff --git a/src/lib/tls/tls_server.cpp b/src/lib/tls/tls_server.cpp
index 66a0e0e1d..5bc5410f5 100644
--- a/src/lib/tls/tls_server.cpp
+++ b/src/lib/tls/tls_server.cpp
@@ -131,16 +131,14 @@ bool check_for_resume(Session& session_info,
}
// Checking encrypt_then_mac on resume (RFC 7366 section 3.1)
- if( !client_hello->supports_encrypt_then_mac() && session_info.supports_encrypt_then_mac())
+ if(!client_hello->supports_encrypt_then_mac() && session_info.supports_encrypt_then_mac())
{
-
/*
Client previously negotiated session with Encrypt-then-MAC,
but has now attempted to resume without the extension: abort
*/
throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
"Client resumed Encrypt-then-MAC session without sending extension");
-
}
return true;
@@ -511,153 +509,147 @@ void Server::process_client_hello_msg(const Handshake_State* active_state,
{
this->session_create(pending_state, have_session_ticket_key);
}
-}
+ }
void Server::process_certificate_msg(Server_Handshake_State& pending_state,
const std::vector<uint8_t>& contents)
-{
+ {
pending_state.client_certs(new Certificate(contents, policy()));
pending_state.set_expected_next(CLIENT_KEX);
-}
+ }
void Server::process_client_key_exchange_msg(Server_Handshake_State& pending_state,
const std::vector<uint8_t>& contents)
-{
+ {
if(pending_state.received_handshake_msg(CERTIFICATE) && !pending_state.client_certs()->empty())
pending_state.set_expected_next(CERTIFICATE_VERIFY);
else
pending_state.set_expected_next(HANDSHAKE_CCS);
- pending_state.client_kex(
- new Client_Key_Exchange(contents, pending_state,
- pending_state.server_rsa_kex_key(),
- m_creds, policy(), rng())
- );
+ pending_state.client_kex(new Client_Key_Exchange(contents, pending_state,
+ pending_state.server_rsa_kex_key(),
+ m_creds, policy(), rng()));
pending_state.compute_session_keys();
-}
+ }
void Server::process_change_cipher_spec_msg(Server_Handshake_State& pending_state)
-{
+ {
pending_state.set_expected_next(FINISHED);
change_cipher_spec_reader(SERVER);
-}
+ }
void Server::process_certificate_verify_msg(Server_Handshake_State& pending_state,
Handshake_Type type,
const std::vector<uint8_t>& contents)
-{
- pending_state.client_verify ( new Certificate_Verify ( contents, pending_state.version() ) );
-
- const std::vector<X509_Certificate>& client_certs =
- pending_state.client_certs()->cert_chain();
-
- const bool sig_valid =
- pending_state.client_verify()->verify ( client_certs[0], pending_state, policy() );
-
- pending_state.hash().update ( pending_state.handshake_io().format ( contents, type ) );
-
- /*
- * Using DECRYPT_ERROR looks weird here, but per RFC 4346 is for
- * "A handshake cryptographic operation failed, including being
- * unable to correctly verify a signature, ..."
- */
- if ( !sig_valid )
- throw TLS_Exception ( Alert::DECRYPT_ERROR, "Client cert verify failed" );
-
- try
- {
- const std::string sni_hostname = pending_state.client_hello()->sni_hostname();
- auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-server", sni_hostname);
-
- callbacks().tls_verify_cert_chain(client_certs,
- {}, // ocsp
- trusted_CAs,
- Usage_Type::TLS_CLIENT_AUTH,
- sni_hostname,
- policy());
- }
- catch ( std::exception& e )
- {
- throw TLS_Exception ( Alert::BAD_CERTIFICATE, e.what() );
- }
-
- pending_state.set_expected_next ( HANDSHAKE_CCS );
-}
+ {
+ pending_state.client_verify(new Certificate_Verify(contents, pending_state.version()));
+
+ const std::vector<X509_Certificate>& client_certs =
+ pending_state.client_certs()->cert_chain();
+
+ const bool sig_valid =
+ pending_state.client_verify()->verify(client_certs[0], pending_state, policy());
+
+ pending_state.hash().update(pending_state.handshake_io().format(contents, type));
+
+ /*
+ * Using DECRYPT_ERROR looks weird here, but per RFC 4346 is for
+ * "A handshake cryptographic operation failed, including being
+ * unable to correctly verify a signature, ..."
+ */
+ if(!sig_valid)
+ throw TLS_Exception(Alert::DECRYPT_ERROR, "Client cert verify failed");
+
+ try
+ {
+ const std::string sni_hostname = pending_state.client_hello()->sni_hostname();
+ auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-server", sni_hostname);
+
+ callbacks().tls_verify_cert_chain(client_certs,
+ {}, // ocsp
+ trusted_CAs,
+ Usage_Type::TLS_CLIENT_AUTH,
+ sni_hostname,
+ policy());
+ }
+ catch(std::exception& e)
+ {
+ throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what());
+ }
+
+ pending_state.set_expected_next(HANDSHAKE_CCS);
+ }
void Server::process_finished_msg(Server_Handshake_State& pending_state,
Handshake_Type type,
const std::vector<uint8_t>& contents)
-{
- pending_state.set_expected_next ( HANDSHAKE_NONE );
-
- pending_state.client_finished ( new Finished ( contents ) );
-
- if ( !pending_state.client_finished()->verify ( pending_state, CLIENT ) )
- throw TLS_Exception ( Alert::DECRYPT_ERROR,
- "Finished message didn't verify" );
-
- if ( !pending_state.server_finished() )
- {
- // already sent finished if resuming, so this is a new session
-
- pending_state.hash().update ( pending_state.handshake_io().format ( contents, type ) );
-
- Session session_info(
- pending_state.server_hello()->session_id(),
- pending_state.session_keys().master_secret(),
- pending_state.server_hello()->version(),
- pending_state.server_hello()->ciphersuite(),
- pending_state.server_hello()->compression_method(),
- SERVER,
- pending_state.server_hello()->supports_extended_master_secret(),
- pending_state.server_hello()->supports_encrypt_then_mac(),
- get_peer_cert_chain ( pending_state ),
- std::vector<uint8_t>(),
- Server_Information(pending_state.client_hello()->sni_hostname()),
- pending_state.srp_identifier(),
- pending_state.server_hello()->srtp_profile()
- );
-
- if ( save_session ( session_info ) )
- {
- if ( pending_state.server_hello()->supports_session_ticket() )
- {
- try
- {
- const SymmetricKey ticket_key = m_creds.psk ( "tls-server", "session-ticket", "" );
-
- pending_state.new_session_ticket (
- new New_Session_Ticket ( pending_state.handshake_io(),
- pending_state.hash(),
- session_info.encrypt ( ticket_key, rng() ),
- policy().session_ticket_lifetime() )
- );
- }
- catch ( ... ) {}
- }
- else
- session_manager().save ( session_info );
- }
+ {
+ pending_state.set_expected_next(HANDSHAKE_NONE);
+
+ pending_state.client_finished(new Finished(contents));
- if ( !pending_state.new_session_ticket() &&
- pending_state.server_hello()->supports_session_ticket() )
+ if(!pending_state.client_finished()->verify(pending_state, CLIENT))
+ throw TLS_Exception(Alert::DECRYPT_ERROR,
+ "Finished message didn't verify");
+
+ if(!pending_state.server_finished())
+ {
+ // already sent finished if resuming, so this is a new session
+
+ pending_state.hash().update(pending_state.handshake_io().format(contents, type));
+
+ Session session_info(
+ pending_state.server_hello()->session_id(),
+ pending_state.session_keys().master_secret(),
+ pending_state.server_hello()->version(),
+ pending_state.server_hello()->ciphersuite(),
+ pending_state.server_hello()->compression_method(),
+ SERVER,
+ pending_state.server_hello()->supports_extended_master_secret(),
+ pending_state.server_hello()->supports_encrypt_then_mac(),
+ get_peer_cert_chain(pending_state),
+ std::vector<uint8_t>(),
+ Server_Information(pending_state.client_hello()->sni_hostname()),
+ pending_state.srp_identifier(),
+ pending_state.server_hello()->srtp_profile());
+
+ if(save_session(session_info))
+ {
+ if(pending_state.server_hello()->supports_session_ticket())
{
- pending_state.new_session_ticket (
- new New_Session_Ticket ( pending_state.handshake_io(), pending_state.hash() )
- );
+ try
+ {
+ const SymmetricKey ticket_key = m_creds.psk("tls-server", "session-ticket", "");
+
+ pending_state.new_session_ticket(
+ new New_Session_Ticket(pending_state.handshake_io(),
+ pending_state.hash(),
+ session_info.encrypt(ticket_key, rng()),
+ policy().session_ticket_lifetime()));
+ }
+ catch(...) {}
}
+ else
+ session_manager().save(session_info);
+ }
- pending_state.handshake_io().send ( Change_Cipher_Spec() );
+ if(!pending_state.new_session_ticket() &&
+ pending_state.server_hello()->supports_session_ticket())
+ {
+ pending_state.new_session_ticket(
+ new New_Session_Ticket(pending_state.handshake_io(), pending_state.hash()));
+ }
- change_cipher_spec_writer ( SERVER );
+ pending_state.handshake_io().send(Change_Cipher_Spec());
- pending_state.server_finished ( new Finished ( pending_state.handshake_io(), pending_state, SERVER ) );
- }
+ change_cipher_spec_writer(SERVER);
- activate_session();
+ pending_state.server_finished(new Finished(pending_state.handshake_io(), pending_state, SERVER));
+ }
-}
+ activate_session();
+ }
/*
* Process a handshake message
@@ -711,72 +703,68 @@ void Server::session_resume(Server_Handshake_State& pending_state,
bool have_session_ticket_key,
Session& session_info)
{
- // Only offer a resuming client a new ticket if they didn't send one this time,
- // ie, resumed via server-side resumption. TODO: also send one if expiring soon?
-
- const bool offer_new_session_ticket =
- (pending_state.client_hello()->supports_session_ticket() &&
- pending_state.client_hello()->session_ticket().empty() &&
- have_session_ticket_key);
-
- pending_state.server_hello(new Server_Hello(
- pending_state.handshake_io(),
- pending_state.hash(),
- policy(),
- rng(),
- secure_renegotiation_data_for_server_hello(),
- *pending_state.client_hello(),
- session_info,
- offer_new_session_ticket,
- m_next_protocol
- ));
-
- secure_renegotiation_check(pending_state.server_hello());
-
- pending_state.compute_session_keys(session_info.master_secret());
-
- if(!save_session(session_info))
- {
- session_manager().remove_entry(session_info.session_id());
+ // Only offer a resuming client a new ticket if they didn't send one this time,
+ // ie, resumed via server-side resumption. TODO: also send one if expiring soon?
- if(pending_state.server_hello()->supports_session_ticket()) // send an empty ticket
- {
- pending_state.new_session_ticket(
- new New_Session_Ticket(pending_state.handshake_io(),
- pending_state.hash())
- );
- }
+ const bool offer_new_session_ticket =
+ (pending_state.client_hello()->supports_session_ticket() &&
+ pending_state.client_hello()->session_ticket().empty() &&
+ have_session_ticket_key);
+
+ pending_state.server_hello(new Server_Hello(
+ pending_state.handshake_io(),
+ pending_state.hash(),
+ policy(),
+ rng(),
+ secure_renegotiation_data_for_server_hello(),
+ *pending_state.client_hello(),
+ session_info,
+ offer_new_session_ticket,
+ m_next_protocol));
+
+ secure_renegotiation_check(pending_state.server_hello());
+
+ pending_state.compute_session_keys(session_info.master_secret());
+
+ if(!save_session(session_info))
+ {
+ session_manager().remove_entry(session_info.session_id());
+
+ if(pending_state.server_hello()->supports_session_ticket()) // send an empty ticket
+ {
+ pending_state.new_session_ticket(
+ new New_Session_Ticket(pending_state.handshake_io(),
+ pending_state.hash()));
}
+ }
- if(pending_state.server_hello()->supports_session_ticket() && !pending_state.new_session_ticket())
+ if(pending_state.server_hello()->supports_session_ticket() && !pending_state.new_session_ticket())
+ {
+ try
{
- try
- {
- const SymmetricKey ticket_key = m_creds.psk("tls-server", "session-ticket", "");
-
- pending_state.new_session_ticket(
- new New_Session_Ticket(pending_state.handshake_io(),
- pending_state.hash(),
- session_info.encrypt(ticket_key, rng()),
- policy().session_ticket_lifetime())
- );
- }
- catch(...) {}
+ const SymmetricKey ticket_key = m_creds.psk("tls-server", "session-ticket", "");
- if(!pending_state.new_session_ticket())
- {
- pending_state.new_session_ticket(
- new New_Session_Ticket(pending_state.handshake_io(), pending_state.hash())
- );
- }
+ pending_state.new_session_ticket(
+ new New_Session_Ticket(pending_state.handshake_io(),
+ pending_state.hash(),
+ session_info.encrypt(ticket_key, rng()),
+ policy().session_ticket_lifetime()));
}
+ catch(...) {}
- pending_state.handshake_io().send(Change_Cipher_Spec());
+ if(!pending_state.new_session_ticket())
+ {
+ pending_state.new_session_ticket(
+ new New_Session_Ticket(pending_state.handshake_io(), pending_state.hash()));
+ }
+ }
- change_cipher_spec_writer(SERVER);
+ pending_state.handshake_io().send(Change_Cipher_Spec());
- pending_state.server_finished(new Finished(pending_state.handshake_io(), pending_state, SERVER));
- pending_state.set_expected_next(HANDSHAKE_CCS);
+ change_cipher_spec_writer(SERVER);
+
+ pending_state.server_finished(new Finished(pending_state.handshake_io(), pending_state, SERVER));
+ pending_state.set_expected_next(HANDSHAKE_CCS);
}
void Server::session_create(Server_Handshake_State& pending_state,
@@ -803,28 +791,26 @@ void Server::session_create(Server_Handshake_State& pending_state,
send_alert(Alert(Alert::UNRECOGNIZED_NAME));
}
- Server_Hello::Settings srv_settings(
- make_hello_random(rng(), policy()), // new session ID
- pending_state.version(),
- choose_ciphersuite(policy(),
- pending_state.version(),
- m_creds,
- cert_chains,
- *pending_state.client_hello()),
- choose_compression(policy(),
- pending_state.client_hello()->compression_methods()),
- have_session_ticket_key);
+ const uint16_t ciphersuite = choose_ciphersuite(policy(), pending_state.version(),
+ m_creds, cert_chains,
+ *pending_state.client_hello());
+
+ Server_Hello::Settings srv_settings(
+ make_hello_random(rng(), policy()), // new session ID
+ pending_state.version(),
+ ciphersuite,
+ choose_compression(policy(), pending_state.client_hello()->compression_methods()),
+ have_session_ticket_key);
pending_state.server_hello(new Server_Hello(
- pending_state.handshake_io(),
- pending_state.hash(),
- policy(),
- rng(),
- secure_renegotiation_data_for_server_hello(),
- *pending_state.client_hello(),
- srv_settings,
- m_next_protocol)
- );
+ pending_state.handshake_io(),
+ pending_state.hash(),
+ policy(),
+ rng(),
+ secure_renegotiation_data_for_server_hello(),
+ *pending_state.client_hello(),
+ srv_settings,
+ m_next_protocol));
secure_renegotiation_check(pending_state.server_hello());
@@ -834,7 +820,7 @@ void Server::session_create(Server_Handshake_State& pending_state,
if(sig_algo != "")
{
BOTAN_ASSERT(!cert_chains[sig_algo].empty(),
- "Attempting to send empty certificate chain");
+ "Attempting to send empty certificate chain");
pending_state.server_certs(new Certificate(pending_state.handshake_io(),
pending_state.hash(),