diff options
Diffstat (limited to 'comm/third_party/botan/src/lib/tls/tls_messages.h')
-rw-r--r-- | comm/third_party/botan/src/lib/tls/tls_messages.h | 653 |
1 files changed, 653 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/tls/tls_messages.h b/comm/third_party/botan/src/lib/tls/tls_messages.h new file mode 100644 index 0000000000..fc95a1c020 --- /dev/null +++ b/comm/third_party/botan/src/lib/tls/tls_messages.h @@ -0,0 +1,653 @@ +/* +* 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 <botan/tls_extensions.h> +#include <botan/tls_handshake_msg.h> +#include <botan/tls_session.h> +#include <botan/tls_policy.h> +#include <botan/tls_ciphersuite.h> +#include <botan/pk_keys.h> +#include <botan/x509cert.h> +#include <botan/ocsp.h> +#include <vector> +#include <string> +#include <set> + +#if defined(BOTAN_HAS_CECPQ1) + #include <botan/cecpq1.h> +#endif + +#if defined(BOTAN_HAS_SRP6) + #include <botan/srp6.h> +#endif + +namespace Botan { + +class Public_Key; +class Credentials_Manager; + +namespace TLS { + +class Session; +class Handshake_IO; +class Handshake_State; +class Callbacks; + +std::vector<uint8_t> 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<uint8_t> serialize() const override; + Handshake_Type type() const override { return HELLO_VERIFY_REQUEST; } + + const std::vector<uint8_t>& cookie() const { return m_cookie; } + + explicit Hello_Verify_Request(const std::vector<uint8_t>& buf); + + Hello_Verify_Request(const std::vector<uint8_t>& client_hello_bits, + const std::string& client_identity, + const SymmetricKey& secret_key); + private: + std::vector<uint8_t> 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; } + + std::vector<Protocol_Version> supported_versions() const; + + const std::vector<uint8_t>& random() const { return m_random; } + + const std::vector<uint8_t>& session_id() const { return m_session_id; } + + const std::vector<uint8_t>& compression_methods() const { return m_comp_methods; } + + const std::vector<uint16_t>& ciphersuites() const { return m_suites; } + + bool offered_suite(uint16_t ciphersuite) const; + + bool sent_fallback_scsv() const; + + std::vector<Signature_Scheme> signature_schemes() const; + + std::vector<Group_Params> supported_ecc_curves() const; + + std::vector<Group_Params> 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<uint8_t> renegotiation_info() const; + + bool supports_session_ticket() const; + + std::vector<uint8_t> 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<std::string> next_protocols() const; + + std::vector<uint16_t> srtp_profiles() const; + + void update_hello_cookie(const Hello_Verify_Request& hello_verify); + + const std::vector<uint8_t>& cookie() const { return m_hello_cookie; } + + std::vector<uint8_t> cookie_input_data() const; + + std::set<Handshake_Extension_Type> 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<uint8_t>& reneg_info, + const Client_Hello::Settings& client_settings, + const std::vector<std::string>& next_protocols); + + Client_Hello(Handshake_IO& io, + Handshake_Hash& hash, + const Policy& policy, + Callbacks& cb, + RandomNumberGenerator& rng, + const std::vector<uint8_t>& reneg_info, + const Session& resumed_session, + const std::vector<std::string>& next_protocols); + + explicit Client_Hello(const std::vector<uint8_t>& buf); + + private: + std::vector<uint8_t> serialize() const override; + + Protocol_Version m_version; + std::vector<uint8_t> m_session_id; + std::vector<uint8_t> m_random; + std::vector<uint16_t> m_suites; + std::vector<uint8_t> m_comp_methods; + std::vector<uint8_t> 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<uint8_t> 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<uint8_t>& 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<uint8_t> 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<uint8_t>& random() const { return m_random; } + + const std::vector<uint8_t>& 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<Renegotiation_Extension>(); + } + + std::vector<uint8_t> renegotiation_info() const + { + if(Renegotiation_Extension* reneg = m_extensions.get<Renegotiation_Extension>()) + return reneg->renegotiation_info(); + return std::vector<uint8_t>(); + } + + bool supports_extended_master_secret() const + { + return m_extensions.has<Extended_Master_Secret>(); + } + + bool supports_encrypt_then_mac() const + { + return m_extensions.has<Encrypt_then_MAC>(); + } + + bool supports_certificate_status_message() const + { + return m_extensions.has<Certificate_Status_Request>(); + } + + bool supports_session_ticket() const + { + return m_extensions.has<Session_Ticket>(); + } + + uint16_t srtp_profile() const + { + if(auto srtp = m_extensions.get<SRTP_Protection_Profiles>()) + { + 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<Application_Layer_Protocol_Notification>()) + return alpn->single_protocol(); + return ""; + } + + std::set<Handshake_Extension_Type> 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<Supported_Point_Formats>()) + { + return ecc_formats->prefers_compressed(); + } + return false; + } + + bool random_signals_downgrade() const; + + Server_Hello(Handshake_IO& io, + Handshake_Hash& hash, + const Policy& policy, + Callbacks& cb, + RandomNumberGenerator& rng, + const std::vector<uint8_t>& 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<uint8_t>& 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<uint8_t>& buf); + private: + std::vector<uint8_t> serialize() const override; + + Protocol_Version m_version; + std::vector<uint8_t> 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<uint8_t>& 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<uint8_t>& buf, + const Handshake_State& state, + const Private_Key* server_rsa_kex_key, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng); + + private: + std::vector<uint8_t> serialize() const override + { return m_key_material; } + + std::vector<uint8_t> m_key_material; + secure_vector<uint8_t> 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<X509_Certificate>& 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<X509_Certificate>& certs); + + explicit Certificate(const std::vector<uint8_t>& buf, const Policy &policy); + private: + std::vector<uint8_t> serialize() const override; + + std::vector<X509_Certificate> 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<const OCSP::Response> response() const { return m_response; } + + const std::vector<uint8_t>& response() const { return m_response; } + + Certificate_Status(const std::vector<uint8_t>& buf); + + Certificate_Status(Handshake_IO& io, + Handshake_Hash& hash, + std::shared_ptr<const OCSP::Response> response); + + /* + * Create a Certificate_Status message using an already DER encoded OCSP response. + */ + Certificate_Status(Handshake_IO& io, + Handshake_Hash& hash, + std::vector<uint8_t> const& raw_response_bytes ); + + private: + std::vector<uint8_t> serialize() const override; + std::vector<uint8_t> 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<std::string>& acceptable_cert_types() const + { return m_cert_key_types; } + + const std::vector<X509_DN>& acceptable_CAs() const { return m_names; } + + const std::vector<Signature_Scheme>& signature_schemes() const + { + return m_schemes; + } + + Certificate_Req(Handshake_IO& io, + Handshake_Hash& hash, + const Policy& policy, + const std::vector<X509_DN>& allowed_cas, + Protocol_Version version); + + Certificate_Req(const std::vector<uint8_t>& buf, + Protocol_Version version); + private: + std::vector<uint8_t> serialize() const override; + + std::vector<X509_DN> m_names; + std::vector<std::string> m_cert_key_types; + + std::vector<Signature_Scheme> 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<uint8_t>& buf, + Protocol_Version version); + private: + std::vector<uint8_t> serialize() const override; + + std::vector<uint8_t> 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<uint8_t> 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<uint8_t>& buf); + private: + std::vector<uint8_t> serialize() const override; + + std::vector<uint8_t> 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<uint8_t>& buf); + private: + std::vector<uint8_t> 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<uint8_t>& 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<uint8_t>& buf, + Kex_Algo kex_alg, + Auth_Method sig_alg, + Protocol_Version version); + + ~Server_Key_Exchange() = default; + private: + std::vector<uint8_t> serialize() const override; + +#if defined(BOTAN_HAS_SRP6) + std::unique_ptr<SRP6_Server_Session> m_srp_params; +#endif + +#if defined(BOTAN_HAS_CECPQ1) + std::unique_ptr<CECPQ1_key> m_cecpq1_key; +#endif + + std::unique_ptr<Private_Key> m_kex_key; + + std::vector<uint8_t> m_params; + + std::vector<uint8_t> 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<uint8_t>& buf); + private: + std::vector<uint8_t> 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<uint8_t>& ticket() const { return m_ticket; } + + New_Session_Ticket(Handshake_IO& io, + Handshake_Hash& hash, + const std::vector<uint8_t>& ticket, + uint32_t lifetime); + + New_Session_Ticket(Handshake_IO& io, + Handshake_Hash& hash); + + explicit New_Session_Ticket(const std::vector<uint8_t>& buf); + private: + std::vector<uint8_t> serialize() const override; + + uint32_t m_ticket_lifetime_hint = 0; + std::vector<uint8_t> 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<uint8_t> serialize() const override + { return std::vector<uint8_t>(1, 1); } + }; + +} + +} + +#endif |