/* * TLS Messages * (C) 2004-2011,2015 Jack Lloyd * 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ #ifndef BOTAN_TLS_MESSAGES_H_ #define BOTAN_TLS_MESSAGES_H_ #include #include #include #include #include #include #include #include #include #include #include #if defined(BOTAN_HAS_CECPQ1) #include #endif #if defined(BOTAN_HAS_SRP6) #include #endif namespace Botan { class Public_Key; class Credentials_Manager; namespace TLS { class Session; class Handshake_IO; class Handshake_State; class Callbacks; std::vector make_hello_random(RandomNumberGenerator& rng, const Policy& policy); /** * DTLS Hello Verify Request */ class BOTAN_UNSTABLE_API Hello_Verify_Request final : public Handshake_Message { public: std::vector serialize() const override; Handshake_Type type() const override { return HELLO_VERIFY_REQUEST; } std::vector cookie() const { return m_cookie; } explicit Hello_Verify_Request(const std::vector& buf); Hello_Verify_Request(const std::vector& client_hello_bits, const std::string& client_identity, const SymmetricKey& secret_key); private: std::vector m_cookie; }; /** * Client Hello Message */ class BOTAN_UNSTABLE_API Client_Hello final : public Handshake_Message { public: class Settings final { public: Settings(const Protocol_Version version, const std::string& hostname = "", const std::string& srp_identifier = "") : m_new_session_version(version), m_hostname(hostname), m_srp_identifier(srp_identifier) {} const Protocol_Version protocol_version() const { return m_new_session_version; } const std::string& hostname() const { return m_hostname; } const std::string& srp_identifier() const { return m_srp_identifier; } private: const Protocol_Version m_new_session_version; const std::string m_hostname; const std::string m_srp_identifier; }; Handshake_Type type() const override { return CLIENT_HELLO; } Protocol_Version version() const { return m_version; } const std::vector& random() const { return m_random; } const std::vector& session_id() const { return m_session_id; } const std::vector& ciphersuites() const { return m_suites; } bool offered_suite(uint16_t ciphersuite) const; bool sent_fallback_scsv() const; std::vector signature_schemes() const; std::vector supported_ecc_curves() const; std::vector supported_dh_groups() const; bool prefers_compressed_ec_points() const; std::string sni_hostname() const; #if defined(BOTAN_HAS_SRP6) std::string srp_identifier() const; #endif bool secure_renegotiation() const; std::vector renegotiation_info() const; bool supports_session_ticket() const; std::vector session_ticket() const; bool supports_alpn() const; bool supports_extended_master_secret() const; bool supports_cert_status_message() const; bool supports_encrypt_then_mac() const; bool sent_signature_algorithms() const; std::vector next_protocols() const; std::vector srtp_profiles() const; void update_hello_cookie(const Hello_Verify_Request& hello_verify); std::set extension_types() const { return m_extensions.extension_types(); } const Extensions& extensions() const { return m_extensions; } Client_Hello(Handshake_IO& io, Handshake_Hash& hash, const Policy& policy, Callbacks& cb, RandomNumberGenerator& rng, const std::vector& reneg_info, const Client_Hello::Settings& client_settings, const std::vector& next_protocols); Client_Hello(Handshake_IO& io, Handshake_Hash& hash, const Policy& policy, Callbacks& cb, RandomNumberGenerator& rng, const std::vector& reneg_info, const Session& resumed_session, const std::vector& next_protocols); explicit Client_Hello(const std::vector& buf); private: std::vector serialize() const override; Protocol_Version m_version; std::vector m_session_id; std::vector m_random; std::vector m_suites; std::vector m_comp_methods; std::vector m_hello_cookie; // DTLS only Extensions m_extensions; }; /** * Server Hello Message */ class BOTAN_UNSTABLE_API Server_Hello final : public Handshake_Message { public: class Settings final { public: Settings(const std::vector new_session_id, Protocol_Version new_session_version, uint16_t ciphersuite, bool offer_session_ticket) : m_new_session_id(new_session_id), m_new_session_version(new_session_version), m_ciphersuite(ciphersuite), m_offer_session_ticket(offer_session_ticket) {} const std::vector& session_id() const { return m_new_session_id; } Protocol_Version protocol_version() const { return m_new_session_version; } uint16_t ciphersuite() const { return m_ciphersuite; } bool offer_session_ticket() const { return m_offer_session_ticket; } private: const std::vector m_new_session_id; Protocol_Version m_new_session_version; uint16_t m_ciphersuite; bool m_offer_session_ticket; }; Handshake_Type type() const override { return SERVER_HELLO; } Protocol_Version version() const { return m_version; } const std::vector& random() const { return m_random; } const std::vector& session_id() const { return m_session_id; } uint16_t ciphersuite() const { return m_ciphersuite; } uint8_t compression_method() const { return m_comp_method; } bool secure_renegotiation() const { return m_extensions.has(); } std::vector renegotiation_info() const { if(Renegotiation_Extension* reneg = m_extensions.get()) return reneg->renegotiation_info(); return std::vector(); } bool supports_extended_master_secret() const { return m_extensions.has(); } bool supports_encrypt_then_mac() const { return m_extensions.has(); } bool supports_certificate_status_message() const { return m_extensions.has(); } bool supports_session_ticket() const { return m_extensions.has(); } uint16_t srtp_profile() const { if(auto srtp = m_extensions.get()) { auto prof = srtp->profiles(); if(prof.size() != 1 || prof[0] == 0) throw Decoding_Error("Server sent malformed DTLS-SRTP extension"); return prof[0]; } return 0; } std::string next_protocol() const { if(auto alpn = m_extensions.get()) return alpn->single_protocol(); return ""; } std::set extension_types() const { return m_extensions.extension_types(); } const Extensions& extensions() const { return m_extensions; } bool prefers_compressed_ec_points() const { if(auto ecc_formats = m_extensions.get()) { return ecc_formats->prefers_compressed(); } return false; } Server_Hello(Handshake_IO& io, Handshake_Hash& hash, const Policy& policy, Callbacks& cb, RandomNumberGenerator& rng, const std::vector& secure_reneg_info, const Client_Hello& client_hello, const Server_Hello::Settings& settings, const std::string next_protocol); Server_Hello(Handshake_IO& io, Handshake_Hash& hash, const Policy& policy, Callbacks& cb, RandomNumberGenerator& rng, const std::vector& secure_reneg_info, const Client_Hello& client_hello, Session& resumed_session, bool offer_session_ticket, const std::string& next_protocol); explicit Server_Hello(const std::vector& buf); private: std::vector serialize() const override; Protocol_Version m_version; std::vector m_session_id, m_random; uint16_t m_ciphersuite; uint8_t m_comp_method; Extensions m_extensions; }; /** * Client Key Exchange Message */ class BOTAN_UNSTABLE_API Client_Key_Exchange final : public Handshake_Message { public: Handshake_Type type() const override { return CLIENT_KEX; } const secure_vector& pre_master_secret() const { return m_pre_master; } Client_Key_Exchange(Handshake_IO& io, Handshake_State& state, const Policy& policy, Credentials_Manager& creds, const Public_Key* server_public_key, const std::string& hostname, RandomNumberGenerator& rng); Client_Key_Exchange(const std::vector& buf, const Handshake_State& state, const Private_Key* server_rsa_kex_key, Credentials_Manager& creds, const Policy& policy, RandomNumberGenerator& rng); private: std::vector serialize() const override { return m_key_material; } std::vector m_key_material; secure_vector m_pre_master; }; /** * Certificate Message */ class BOTAN_UNSTABLE_API Certificate final : public Handshake_Message { public: Handshake_Type type() const override { return CERTIFICATE; } const std::vector& cert_chain() const { return m_certs; } size_t count() const { return m_certs.size(); } bool empty() const { return m_certs.empty(); } Certificate(Handshake_IO& io, Handshake_Hash& hash, const std::vector& certs); explicit Certificate(const std::vector& buf, const Policy &policy); private: std::vector serialize() const override; std::vector m_certs; }; /** * Certificate Status (RFC 6066) */ class BOTAN_UNSTABLE_API Certificate_Status final : public Handshake_Message { public: Handshake_Type type() const override { return CERTIFICATE_STATUS; } std::shared_ptr response() const { return m_response; } Certificate_Status(const std::vector& buf); Certificate_Status(Handshake_IO& io, Handshake_Hash& hash, std::shared_ptr response); private: std::vector serialize() const override; std::shared_ptr m_response; }; /** * Certificate Request Message */ class BOTAN_UNSTABLE_API Certificate_Req final : public Handshake_Message { public: Handshake_Type type() const override { return CERTIFICATE_REQUEST; } const std::vector& acceptable_cert_types() const { return m_cert_key_types; } const std::vector& acceptable_CAs() const { return m_names; } const std::vector& signature_schemes() const { return m_schemes; } Certificate_Req(Handshake_IO& io, Handshake_Hash& hash, const Policy& policy, const std::vector& allowed_cas, Protocol_Version version); Certificate_Req(const std::vector& buf, Protocol_Version version); private: std::vector serialize() const override; std::vector m_names; std::vector m_cert_key_types; std::vector m_schemes; }; /** * Certificate Verify Message */ class BOTAN_UNSTABLE_API Certificate_Verify final : public Handshake_Message { public: Handshake_Type type() const override { return CERTIFICATE_VERIFY; } /** * Check the signature on a certificate verify message * @param cert the purported certificate * @param state the handshake state * @param policy the TLS policy */ bool verify(const X509_Certificate& cert, const Handshake_State& state, const Policy& policy) const; Certificate_Verify(Handshake_IO& io, Handshake_State& state, const Policy& policy, RandomNumberGenerator& rng, const Private_Key* key); Certificate_Verify(const std::vector& buf, Protocol_Version version); private: std::vector serialize() const override; std::vector m_signature; Signature_Scheme m_scheme = Signature_Scheme::NONE; }; /** * Finished Message */ class BOTAN_UNSTABLE_API Finished final : public Handshake_Message { public: Handshake_Type type() const override { return FINISHED; } std::vector verify_data() const { return m_verification_data; } bool verify(const Handshake_State& state, Connection_Side side) const; Finished(Handshake_IO& io, Handshake_State& state, Connection_Side side); explicit Finished(const std::vector& buf); private: std::vector serialize() const override; std::vector m_verification_data; }; /** * Hello Request Message */ class BOTAN_UNSTABLE_API Hello_Request final : public Handshake_Message { public: Handshake_Type type() const override { return HELLO_REQUEST; } explicit Hello_Request(Handshake_IO& io); explicit Hello_Request(const std::vector& buf); private: std::vector serialize() const override; }; /** * Server Key Exchange Message */ class BOTAN_UNSTABLE_API Server_Key_Exchange final : public Handshake_Message { public: Handshake_Type type() const override { return SERVER_KEX; } const std::vector& params() const { return m_params; } bool verify(const Public_Key& server_key, const Handshake_State& state, const Policy& policy) const; // Only valid for certain kex types const Private_Key& server_kex_key() const; #if defined(BOTAN_HAS_SRP6) // Only valid for SRP negotiation SRP6_Server_Session& server_srp_params() const { BOTAN_ASSERT_NONNULL(m_srp_params); return *m_srp_params; } #endif #if defined(BOTAN_HAS_CECPQ1) // Only valid for CECPQ1 negotiation const CECPQ1_key& cecpq1_key() const { BOTAN_ASSERT_NONNULL(m_cecpq1_key); return *m_cecpq1_key; } #endif Server_Key_Exchange(Handshake_IO& io, Handshake_State& state, const Policy& policy, Credentials_Manager& creds, RandomNumberGenerator& rng, const Private_Key* signing_key = nullptr); Server_Key_Exchange(const std::vector& buf, Kex_Algo kex_alg, Auth_Method sig_alg, Protocol_Version version); ~Server_Key_Exchange() = default; private: std::vector serialize() const override; #if defined(BOTAN_HAS_SRP6) std::unique_ptr m_srp_params; #endif #if defined(BOTAN_HAS_CECPQ1) std::unique_ptr m_cecpq1_key; #endif std::unique_ptr m_kex_key; std::vector m_params; std::vector m_signature; Signature_Scheme m_scheme = Signature_Scheme::NONE; }; /** * Server Hello Done Message */ class BOTAN_UNSTABLE_API Server_Hello_Done final : public Handshake_Message { public: Handshake_Type type() const override { return SERVER_HELLO_DONE; } Server_Hello_Done(Handshake_IO& io, Handshake_Hash& hash); explicit Server_Hello_Done(const std::vector& buf); private: std::vector serialize() const override; }; /** * New Session Ticket Message */ class BOTAN_UNSTABLE_API New_Session_Ticket final : public Handshake_Message { public: Handshake_Type type() const override { return NEW_SESSION_TICKET; } uint32_t ticket_lifetime_hint() const { return m_ticket_lifetime_hint; } const std::vector& ticket() const { return m_ticket; } New_Session_Ticket(Handshake_IO& io, Handshake_Hash& hash, const std::vector& ticket, uint32_t lifetime); New_Session_Ticket(Handshake_IO& io, Handshake_Hash& hash); explicit New_Session_Ticket(const std::vector& buf); private: std::vector serialize() const override; uint32_t m_ticket_lifetime_hint = 0; std::vector m_ticket; }; /** * Change Cipher Spec */ class BOTAN_UNSTABLE_API Change_Cipher_Spec final : public Handshake_Message { public: Handshake_Type type() const override { return HANDSHAKE_CCS; } std::vector serialize() const override { return std::vector(1, 1); } }; } } #endif