/* * TLS Server * (C) 2004-2011,2012,2016 Jack Lloyd * 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include #include #include #include #include #include #include namespace Botan::TLS { class Server_Handshake_State final : public Handshake_State { public: Server_Handshake_State(std::unique_ptr io, Callbacks& cb) : Handshake_State(std::move(io), cb) {} Private_Key* server_rsa_kex_key() { return m_server_rsa_kex_key.get(); } void set_server_rsa_kex_key(std::shared_ptr key) { m_server_rsa_kex_key = std::move(key); } bool allow_session_resumption() const { return m_allow_session_resumption; } void set_allow_session_resumption(bool allow_session_resumption) { m_allow_session_resumption = allow_session_resumption; } const std::vector& resume_peer_certs() const { return m_resume_peer_certs; } void set_resume_certs(const std::vector& certs) { m_resume_peer_certs = certs; } void mark_as_resumption() { m_is_a_resumption = true; } bool is_a_resumption() const { return m_is_a_resumption; } private: // Used by the server only, in case of RSA key exchange. std::shared_ptr m_server_rsa_kex_key; /* * Used by the server to know if resumption should be allowed on * a server-initiated renegotiation */ bool m_allow_session_resumption = true; bool m_is_a_resumption = false; std::vector m_resume_peer_certs; }; namespace { std::optional check_for_resume(const Session_Handle& handle_to_resume, Session_Manager& session_manager, Callbacks& cb, const Policy& policy, const Client_Hello_12* client_hello) { auto session = session_manager.retrieve(handle_to_resume, cb, policy); if(!session.has_value()) { return std::nullopt; } // wrong version if(client_hello->legacy_version() != session->version()) { return std::nullopt; } // client didn't send original ciphersuite if(!value_exists(client_hello->ciphersuites(), session->ciphersuite_code())) { return std::nullopt; } // client sent a different SNI hostname if(!client_hello->sni_hostname().empty() && client_hello->sni_hostname() != session->server_info().hostname()) { return std::nullopt; } // Checking extended_master_secret on resume (RFC 7627 section 5.3) if(client_hello->supports_extended_master_secret() != session->supports_extended_master_secret()) { if(!session->supports_extended_master_secret()) { return std::nullopt; // force new handshake with extended master secret } else { /* Client previously negotiated session with extended master secret, but has now attempted to resume without the extension: abort */ throw TLS_Exception(Alert::HandshakeFailure, "Client resumed extended ms session without sending extension"); } } // Checking encrypt_then_mac on resume (RFC 7366 section 3.1) if(!client_hello->supports_encrypt_then_mac() && session->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::HandshakeFailure, "Client resumed Encrypt-then-MAC session without sending extension"); } return session; } /* * Choose which ciphersuite to use */ uint16_t choose_ciphersuite(const Policy& policy, Protocol_Version version, const std::map>& cert_chains, const Client_Hello_12& client_hello) { const bool our_choice = policy.server_uses_own_ciphersuite_preferences(); const std::vector& client_suites = client_hello.ciphersuites(); const std::vector server_suites = policy.ciphersuite_list(version); if(server_suites.empty()) { throw TLS_Exception(Alert::HandshakeFailure, "Policy forbids us from negotiating any ciphersuite"); } const bool have_shared_ecc_curve = (policy.choose_key_exchange_group(client_hello.supported_ecc_curves(), {}) != Group_Params::NONE); const bool client_supports_ffdhe_groups = !client_hello.supported_dh_groups().empty(); const bool have_shared_dh_group = (policy.choose_key_exchange_group(client_hello.supported_dh_groups(), {}) != Group_Params::NONE); /* Walk down one list in preference order */ std::vector pref_list = server_suites; std::vector other_list = client_suites; if(!our_choice) { std::swap(pref_list, other_list); } for(auto suite_id : pref_list) { if(!value_exists(other_list, suite_id)) { continue; } const auto suite = Ciphersuite::by_id(suite_id); if(!suite.has_value() || !suite->valid()) { continue; } if(have_shared_ecc_curve == false && suite->ecc_ciphersuite()) { continue; } if(suite->kex_method() == Kex_Algo::DH && client_supports_ffdhe_groups && !have_shared_dh_group) { continue; } // For non-anon ciphersuites if(suite->signature_used()) { const std::string sig_algo = suite->sig_algo(); // Do we have any certificates for this sig? if(!cert_chains.contains(sig_algo)) { continue; } const std::vector allowed = policy.allowed_signature_schemes(); std::vector client_sig_methods = client_hello.signature_schemes(); /* Contrary to the wording of draft-ietf-tls-md5-sha1-deprecate we do not enforce that clients do not offer support SHA-1 or MD5 signatures; we just ignore it. */ bool we_support_some_hash_by_client = false; for(Signature_Scheme scheme : client_sig_methods) { if(!scheme.is_available()) { continue; } if(scheme.algorithm_name() == suite->sig_algo() && policy.allowed_signature_hash(scheme.hash_function_name())) { we_support_some_hash_by_client = true; } } if(we_support_some_hash_by_client == false) { throw TLS_Exception(Alert::HandshakeFailure, "Policy does not accept any hash function supported by client"); } } return suite_id; } // RFC 7919 Section 4. // If the [Supported Groups] extension is present // with FFDHE groups, none of the client’s offered groups are acceptable // by the server, and none of the client’s proposed non-FFDHE cipher // suites are acceptable to the server, the server MUST end the // connection with a fatal TLS alert of type insufficient_security(71). if(client_supports_ffdhe_groups && !have_shared_dh_group) { throw TLS_Exception(Alert::InsufficientSecurity, "Can't agree on a sufficiently strong ciphersuite with client"); } throw TLS_Exception(Alert::HandshakeFailure, "Can't agree on a ciphersuite with client"); } std::map> get_server_certs( std::string_view hostname, const std::vector& cert_sig_schemes, Credentials_Manager& creds) { const char* cert_types[] = {"RSA", "ECDSA", "DSA", nullptr}; std::map> cert_chains; for(size_t i = 0; cert_types[i]; ++i) { const std::vector certs = creds.cert_chain_single_type( cert_types[i], to_algorithm_identifiers(cert_sig_schemes), "tls-server", std::string(hostname)); if(!certs.empty()) { cert_chains[cert_types[i]] = certs; } } return cert_chains; } } // namespace Server_Impl_12::Server_Impl_12(const std::shared_ptr& callbacks, const std::shared_ptr& session_manager, const std::shared_ptr& creds, const std::shared_ptr& policy, const std::shared_ptr& rng, bool is_datagram, size_t io_buf_sz) : Channel_Impl_12(callbacks, session_manager, rng, policy, true, is_datagram, io_buf_sz), m_creds(creds) { BOTAN_ASSERT_NONNULL(m_creds); } Server_Impl_12::Server_Impl_12(const Channel_Impl::Downgrade_Information& downgrade_info) : Channel_Impl_12(downgrade_info.callbacks, downgrade_info.session_manager, downgrade_info.rng, downgrade_info.policy, true /* is_server*/, false /* TLS 1.3 does not support DTLS yet */, downgrade_info.io_buffer_size), m_creds(downgrade_info.creds) {} std::unique_ptr Server_Impl_12::new_handshake_state(std::unique_ptr io) { auto state = std::make_unique(std::move(io), callbacks()); state->set_expected_next(Handshake_Type::ClientHello); return state; } std::vector Server_Impl_12::get_peer_cert_chain(const Handshake_State& state_base) const { const Server_Handshake_State& state = dynamic_cast(state_base); if(!state.resume_peer_certs().empty()) { return state.resume_peer_certs(); } if(state.client_certs()) { return state.client_certs()->cert_chain(); } return std::vector(); } /* * Send a hello request to the client */ void Server_Impl_12::initiate_handshake(Handshake_State& state, bool force_full_renegotiation) { dynamic_cast(state).set_allow_session_resumption(!force_full_renegotiation); Hello_Request hello_req(state.handshake_io()); } namespace { Protocol_Version select_version(const TLS::Policy& policy, Protocol_Version client_offer, Protocol_Version active_version, const std::vector& supported_versions) { const bool is_datagram = client_offer.is_datagram_protocol(); const bool initial_handshake = (active_version.valid() == false); if(!supported_versions.empty()) { if(is_datagram) { if(policy.allow_dtls12() && value_exists(supported_versions, Protocol_Version(Protocol_Version::DTLS_V12))) { return Protocol_Version::DTLS_V12; } throw TLS_Exception(Alert::ProtocolVersion, "No shared DTLS version"); } else { if(policy.allow_tls12() && value_exists(supported_versions, Protocol_Version(Protocol_Version::TLS_V12))) { return Protocol_Version::TLS_V12; } throw TLS_Exception(Alert::ProtocolVersion, "No shared TLS version"); } } if(!initial_handshake) { /* * If this is a renegotiation, and the client has offered a * later version than what it initially negotiated, negotiate * the old version. This matches OpenSSL's behavior. If the * client is offering a version earlier than what it initially * negotiated, reject as a probable attack. */ if(active_version > client_offer) { throw TLS_Exception( Alert::ProtocolVersion, "Client negotiated " + active_version.to_string() + " then renegotiated with " + client_offer.to_string()); } else { return active_version; } } if(is_datagram) { if(policy.allow_dtls12() && client_offer >= Protocol_Version::DTLS_V12) { return Protocol_Version::DTLS_V12; } } else { if(policy.allow_tls12() && client_offer >= Protocol_Version::TLS_V12) { return Protocol_Version::TLS_V12; } } throw TLS_Exception(Alert::ProtocolVersion, "Client version " + client_offer.to_string() + " is unacceptable by policy"); } } // namespace /* * Process a Client Hello Message */ void Server_Impl_12::process_client_hello_msg(const Handshake_State* active_state, Server_Handshake_State& pending_state, const std::vector& contents, bool epoch0_restart) { BOTAN_ASSERT_IMPLICATION(epoch0_restart, active_state != nullptr, "Can't restart with a dead connection"); const bool initial_handshake = epoch0_restart || !active_state; if(initial_handshake == false && policy().allow_client_initiated_renegotiation() == false) { if(policy().abort_connection_on_undesired_renegotiation()) { throw TLS_Exception(Alert::NoRenegotiation, "Server policy prohibits renegotiation"); } else { send_warning_alert(Alert::NoRenegotiation); } return; } if(!policy().allow_insecure_renegotiation() && !(initial_handshake || secure_renegotiation_supported())) { send_warning_alert(Alert::NoRenegotiation); return; } if(pending_state.handshake_io().have_more_data()) { throw TLS_Exception(Alert::UnexpectedMessage, "Have data remaining in buffer after ClientHello"); } pending_state.client_hello(new Client_Hello_12(contents)); const Protocol_Version client_offer = pending_state.client_hello()->legacy_version(); const bool datagram = client_offer.is_datagram_protocol(); if(datagram) { if(client_offer.major_version() == 0xFF) { throw TLS_Exception(Alert::ProtocolVersion, "Client offered DTLS version with major version 0xFF"); } } else { if(client_offer.major_version() < 3) { throw TLS_Exception(Alert::ProtocolVersion, "Client offered TLS version with major version under 3"); } if(client_offer.major_version() == 3 && client_offer.minor_version() == 0) { throw TLS_Exception(Alert::ProtocolVersion, "Client offered SSLv3 which is not supported"); } } /* * BoGo test suite expects that we will send the hello verify with a record * version matching the version that is eventually negotiated. This is wrong * but harmless, so go with it. Also doing the version negotiation step first * allows to immediately close the connection with an alert if the client has * offered a version that we are not going to negotiate anyway, instead of * making them first do the cookie exchange and then telling them no. * * There is no issue with amplification here, since the alert is just 2 bytes. */ const Protocol_Version negotiated_version = select_version(policy(), client_offer, active_state ? active_state->version() : Protocol_Version(), pending_state.client_hello()->supported_versions()); pending_state.set_version(negotiated_version); const auto compression_methods = pending_state.client_hello()->compression_methods(); if(!value_exists(compression_methods, uint8_t(0))) { throw TLS_Exception(Alert::IllegalParameter, "Client did not offer NULL compression"); } if(initial_handshake && datagram) { SymmetricKey cookie_secret; try { cookie_secret = m_creds->psk("tls-server", "dtls-cookie-secret", ""); } catch(...) {} if(!cookie_secret.empty()) { const std::string client_identity = callbacks().tls_peer_network_identity(); Hello_Verify_Request verify(pending_state.client_hello()->cookie_input_data(), client_identity, cookie_secret); if(pending_state.client_hello()->cookie() != verify.cookie()) { if(epoch0_restart) { pending_state.handshake_io().send_under_epoch(verify, 0); } else { pending_state.handshake_io().send(verify); } pending_state.client_hello(static_cast(nullptr)); pending_state.set_expected_next(Handshake_Type::ClientHello); return; } } else if(epoch0_restart) { throw TLS_Exception(Alert::HandshakeFailure, "Reuse of DTLS association requires DTLS cookie secret be set"); } } if(epoch0_restart) { // If we reached here then we were able to verify the cookie reset_active_association_state(); } secure_renegotiation_check(pending_state.client_hello()); callbacks().tls_examine_extensions( pending_state.client_hello()->extensions(), Connection_Side::Client, Handshake_Type::ClientHello); const auto session_handle = pending_state.client_hello()->session_handle(); std::optional session_info; if(pending_state.allow_session_resumption() && session_handle.has_value()) { session_info = check_for_resume( session_handle.value(), session_manager(), callbacks(), policy(), pending_state.client_hello()); } m_next_protocol = ""; if(pending_state.client_hello()->supports_alpn()) { m_next_protocol = callbacks().tls_server_choose_app_protocol(pending_state.client_hello()->next_protocols()); } if(session_info.has_value()) { this->session_resume(pending_state, {session_info.value(), session_handle.value()}); } else { // new session this->session_create(pending_state); } } void Server_Impl_12::process_certificate_msg(Server_Handshake_State& pending_state, const std::vector& contents) { pending_state.client_certs(new Certificate_12(contents, policy())); // CERTIFICATE_REQUIRED would make more sense but BoGo expects handshake failure alert if(pending_state.client_certs()->empty() && policy().require_client_certificate_authentication()) { throw TLS_Exception(Alert::HandshakeFailure, "Policy requires client send a certificate, but it did not"); } pending_state.set_expected_next(Handshake_Type::ClientKeyExchange); } void Server_Impl_12::process_client_key_exchange_msg(Server_Handshake_State& pending_state, const std::vector& contents) { if(pending_state.received_handshake_msg(Handshake_Type::Certificate) && !pending_state.client_certs()->empty()) { pending_state.set_expected_next(Handshake_Type::CertificateVerify); } else { pending_state.set_expected_next(Handshake_Type::HandshakeCCS); } 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(); if(policy().allow_ssl_key_log_file()) { // draft-thomson-tls-keylogfile-00 Section 3.2 // An implementation of TLS 1.2 (and also earlier versions) use // the label "CLIENT_RANDOM" to identify the "master" secret for // the connection. callbacks().tls_ssl_key_log_data( "CLIENT_RANDOM", pending_state.client_hello()->random(), pending_state.session_keys().master_secret()); } } void Server_Impl_12::process_change_cipher_spec_msg(Server_Handshake_State& pending_state) { pending_state.set_expected_next(Handshake_Type::Finished); change_cipher_spec_reader(Connection_Side::Server); } void Server_Impl_12::process_certificate_verify_msg(Server_Handshake_State& pending_state, Handshake_Type type, const std::vector& contents) { pending_state.client_verify(new Certificate_Verify_12(contents)); const std::vector& client_certs = pending_state.client_certs()->cert_chain(); if(client_certs.empty()) { throw TLS_Exception(Alert::DecodeError, "No client certificate sent"); } if(!client_certs[0].allowed_usage(Key_Constraints::DigitalSignature)) { throw TLS_Exception(Alert::BadCertificate, "Client certificate does not support signing"); } 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::DecryptError, "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::BadCertificate, e.what()); } pending_state.set_expected_next(Handshake_Type::HandshakeCCS); } void Server_Impl_12::process_finished_msg(Server_Handshake_State& pending_state, Handshake_Type type, const std::vector& contents) { pending_state.set_expected_next(Handshake_Type::None); if(pending_state.handshake_io().have_more_data()) { throw TLS_Exception(Alert::UnexpectedMessage, "Have data remaining in buffer after Finished"); } pending_state.client_finished(new Finished_12(contents)); if(!pending_state.client_finished()->verify(pending_state, Connection_Side::Client)) { throw TLS_Exception(Alert::DecryptError, "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.session_keys().master_secret(), pending_state.server_hello()->legacy_version(), pending_state.server_hello()->ciphersuite(), Connection_Side::Server, pending_state.server_hello()->supports_extended_master_secret(), pending_state.server_hello()->supports_encrypt_then_mac(), get_peer_cert_chain(pending_state), Server_Information(pending_state.client_hello()->sni_hostname()), pending_state.server_hello()->srtp_profile(), callbacks().tls_current_timestamp()); // Give the application a chance for a final veto before fully // establishing the connection. callbacks().tls_session_established([&, this] { Session_Summary summary(session_info, pending_state.is_a_resumption(), external_psk_identity()); summary.set_session_id(pending_state.server_hello()->session_id()); return summary; }()); if(callbacks().tls_should_persist_resumption_information(session_info)) { auto handle = session_manager().establish(session_info, pending_state.server_hello()->session_id(), !pending_state.server_hello()->supports_session_ticket()); if(pending_state.server_hello()->supports_session_ticket() && handle.has_value() && handle->is_ticket()) { pending_state.new_session_ticket(new New_Session_Ticket_12(pending_state.handshake_io(), pending_state.hash(), handle->ticket().value(), policy().session_ticket_lifetime())); } } if(!pending_state.new_session_ticket() && pending_state.server_hello()->supports_session_ticket()) { pending_state.new_session_ticket( new New_Session_Ticket_12(pending_state.handshake_io(), pending_state.hash())); } pending_state.handshake_io().send(Change_Cipher_Spec()); change_cipher_spec_writer(Connection_Side::Server); pending_state.server_finished( new Finished_12(pending_state.handshake_io(), pending_state, Connection_Side::Server)); } activate_session(); } /* * Process a handshake message */ void Server_Impl_12::process_handshake_msg(const Handshake_State* active_state, Handshake_State& state_base, Handshake_Type type, const std::vector& contents, bool epoch0_restart) { Server_Handshake_State& state = dynamic_cast(state_base); state.confirm_transition_to(type); /* * The change cipher spec message isn't technically a handshake * message so it's not included in the hash. The finished and * certificate verify messages are verified based on the current * state of the hash *before* this message so we delay adding them * to the hash computation until we've processed them below. */ if(type != Handshake_Type::HandshakeCCS && type != Handshake_Type::Finished && type != Handshake_Type::CertificateVerify) { state.hash().update(state.handshake_io().format(contents, type)); } switch(type) { case Handshake_Type::ClientHello: return this->process_client_hello_msg(active_state, state, contents, epoch0_restart); case Handshake_Type::Certificate: return this->process_certificate_msg(state, contents); case Handshake_Type::ClientKeyExchange: return this->process_client_key_exchange_msg(state, contents); case Handshake_Type::CertificateVerify: return this->process_certificate_verify_msg(state, type, contents); case Handshake_Type::HandshakeCCS: return this->process_change_cipher_spec_msg(state); case Handshake_Type::Finished: return this->process_finished_msg(state, type, contents); default: throw Unexpected_Message("Unknown handshake message received"); } } void Server_Impl_12::session_resume(Server_Handshake_State& pending_state, const Session_with_Handle& session) { // 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() && session_manager().emits_session_tickets(); pending_state.server_hello(new Server_Hello_12(pending_state.handshake_io(), pending_state.hash(), policy(), callbacks(), rng(), secure_renegotiation_data_for_server_hello(), *pending_state.client_hello(), session.session, offer_new_session_ticket, m_next_protocol)); secure_renegotiation_check(pending_state.server_hello()); pending_state.mark_as_resumption(); pending_state.compute_session_keys(session.session.master_secret()); if(policy().allow_ssl_key_log_file()) { // draft-thomson-tls-keylogfile-00 Section 3.2 // An implementation of TLS 1.2 (and also earlier versions) use // the label "CLIENT_RANDOM" to identify the "master" secret for // the connection. callbacks().tls_ssl_key_log_data( "CLIENT_RANDOM", pending_state.client_hello()->random(), pending_state.session_keys().master_secret()); } pending_state.set_resume_certs(session.session.peer_certs()); // Give the application a chance for a final veto before fully // establishing the connection. callbacks().tls_session_established([&, this] { Session_Summary summary(session.session, pending_state.is_a_resumption(), external_psk_identity()); summary.set_session_id(pending_state.server_hello()->session_id()); if(auto ticket = session.handle.ticket()) { summary.set_session_ticket(std::move(ticket.value())); } return summary; }()); auto new_handle = [&, this]() -> std::optional { if(!callbacks().tls_should_persist_resumption_information(session.session)) { session_manager().remove(session.handle); return std::nullopt; } else { return session_manager().establish(session.session, session.handle.id()); } }(); if(pending_state.server_hello()->supports_session_ticket()) { if(new_handle.has_value() && new_handle->is_ticket()) { pending_state.new_session_ticket(new New_Session_Ticket_12(pending_state.handshake_io(), pending_state.hash(), new_handle->ticket().value(), policy().session_ticket_lifetime())); } else { pending_state.new_session_ticket( new New_Session_Ticket_12(pending_state.handshake_io(), pending_state.hash())); } } pending_state.handshake_io().send(Change_Cipher_Spec()); change_cipher_spec_writer(Connection_Side::Server); pending_state.server_finished(new Finished_12(pending_state.handshake_io(), pending_state, Connection_Side::Server)); pending_state.set_expected_next(Handshake_Type::HandshakeCCS); } void Server_Impl_12::session_create(Server_Handshake_State& pending_state) { std::map> cert_chains; const std::string sni_hostname = pending_state.client_hello()->sni_hostname(); // RFC 8446 1.3 // The "signature_algorithms_cert" extension allows a client to indicate // which signature algorithms it can validate in X.509 certificates. // // RFC 8446 4.2.3 // TLS 1.2 implementations SHOULD also process this extension. const auto cert_signature_schemes = pending_state.client_hello()->certificate_signature_schemes(); cert_chains = get_server_certs(sni_hostname, cert_signature_schemes, *m_creds); if(!sni_hostname.empty() && cert_chains.empty()) { cert_chains = get_server_certs("", cert_signature_schemes, *m_creds); /* * Only send the unrecognized_name alert if we couldn't * find any certs for the requested name but did find at * least one cert to use in general. That avoids sending an * unrecognized_name when a server is configured for purely * anonymous/PSK operation. */ if(!cert_chains.empty()) { send_warning_alert(Alert::UnrecognizedName); } } const uint16_t ciphersuite = choose_ciphersuite(policy(), pending_state.version(), cert_chains, *pending_state.client_hello()); Server_Hello_12::Settings srv_settings(Session_ID(make_hello_random(rng(), callbacks(), policy())), pending_state.version(), ciphersuite, session_manager().emits_session_tickets()); pending_state.server_hello(new Server_Hello_12(pending_state.handshake_io(), pending_state.hash(), policy(), callbacks(), rng(), secure_renegotiation_data_for_server_hello(), *pending_state.client_hello(), srv_settings, m_next_protocol)); secure_renegotiation_check(pending_state.server_hello()); const Ciphersuite& pending_suite = pending_state.ciphersuite(); std::shared_ptr private_key; if(pending_suite.signature_used() || pending_suite.kex_method() == Kex_Algo::STATIC_RSA) { const std::string algo_used = pending_suite.signature_used() ? pending_suite.sig_algo() : "RSA"; BOTAN_ASSERT(!cert_chains[algo_used].empty(), "Attempting to send empty certificate chain"); pending_state.server_certs( new Certificate_12(pending_state.handshake_io(), pending_state.hash(), cert_chains[algo_used])); if(pending_state.client_hello()->supports_cert_status_message() && pending_state.is_a_resumption() == false) { auto* csr = pending_state.client_hello()->extensions().get(); // csr is non-null if client_hello()->supports_cert_status_message() BOTAN_ASSERT_NOMSG(csr != nullptr); const auto resp_bytes = callbacks().tls_provide_cert_status(cert_chains[algo_used], *csr); if(!resp_bytes.empty()) { pending_state.server_cert_status( new Certificate_Status(pending_state.handshake_io(), pending_state.hash(), resp_bytes)); } } private_key = m_creds->private_key_for(pending_state.server_certs()->cert_chain()[0], "tls-server", sni_hostname); if(!private_key) { throw Internal_Error("No private key located for associated server cert"); } } if(pending_suite.kex_method() == Kex_Algo::STATIC_RSA) { pending_state.set_server_rsa_kex_key(private_key); } else { pending_state.server_kex(new Server_Key_Exchange( pending_state.handshake_io(), pending_state, policy(), *m_creds, rng(), private_key.get())); } auto trusted_CAs = m_creds->trusted_certificate_authorities("tls-server", sni_hostname); std::vector client_auth_CAs; for(auto* store : trusted_CAs) { auto subjects = store->all_subjects(); client_auth_CAs.insert(client_auth_CAs.end(), subjects.begin(), subjects.end()); } const bool request_cert = (client_auth_CAs.empty() == false) || policy().request_client_certificate_authentication(); if(request_cert && pending_state.ciphersuite().signature_used()) { pending_state.cert_req( new Certificate_Request_12(pending_state.handshake_io(), pending_state.hash(), policy(), client_auth_CAs)); /* SSLv3 allowed clients to skip the Certificate message entirely if they wanted. In TLS v1.0 and later clients must send a (possibly empty) Certificate message */ pending_state.set_expected_next(Handshake_Type::Certificate); } else { pending_state.set_expected_next(Handshake_Type::ClientKeyExchange); } pending_state.server_hello_done(new Server_Hello_Done(pending_state.handshake_io(), pending_state.hash())); } } // namespace Botan::TLS