diff options
Diffstat (limited to 'comm/third_party/botan/src/lib/tls/tls_channel.h')
-rw-r--r-- | comm/third_party/botan/src/lib/tls/tls_channel.h | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/tls/tls_channel.h b/comm/third_party/botan/src/lib/tls/tls_channel.h new file mode 100644 index 0000000000..046560e228 --- /dev/null +++ b/comm/third_party/botan/src/lib/tls/tls_channel.h @@ -0,0 +1,318 @@ +/* +* TLS Channel +* (C) 2011,2012,2014,2015 Jack Lloyd +* 2016 Matthias Gierlings +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_TLS_CHANNEL_H_ +#define BOTAN_TLS_CHANNEL_H_ + +#include <botan/tls_session.h> +#include <botan/tls_alert.h> +#include <botan/tls_session_manager.h> +#include <botan/tls_callbacks.h> +#include <botan/x509cert.h> +#include <functional> +#include <vector> +#include <string> +#include <map> + +namespace Botan { + +namespace TLS { + +class Connection_Cipher_State; +class Connection_Sequence_Numbers; +class Handshake_State; +class Handshake_Message; +class Client_Hello; +class Server_Hello; +class Policy; + +/** +* Generic interface for TLS endpoint +*/ +class BOTAN_PUBLIC_API(2,0) Channel + { + public: + typedef std::function<void (const uint8_t[], size_t)> output_fn; + typedef std::function<void (const uint8_t[], size_t)> data_cb; + typedef std::function<void (Alert, const uint8_t[], size_t)> alert_cb; + typedef std::function<bool (const Session&)> handshake_cb; + typedef std::function<void (const Handshake_Message&)> handshake_msg_cb; + static size_t IO_BUF_DEFAULT_SIZE; + + /** + * Set up a new TLS session + * + * @param callbacks contains a set of callback function references + * required by the TLS endpoint. + * @param session_manager manages session state + * @param rng a random number generator + * @param policy specifies other connection policy information + * @param is_server whether this is a server session or not + * @param is_datagram whether this is a DTLS session + * @param io_buf_sz This many bytes of memory will + * be preallocated for the read and write buffers. Smaller + * values just mean reallocations and copies are more likely. + */ + Channel(Callbacks& callbacks, + Session_Manager& session_manager, + RandomNumberGenerator& rng, + const Policy& policy, + bool is_server, + bool is_datagram, + size_t io_buf_sz = IO_BUF_DEFAULT_SIZE); + + /** + * DEPRECATED. This constructor is only provided for backward + * compatibility and should not be used in new implementations. + * (Not marked deprecated since it is only called internally, by + * other deprecated constructors) + */ + Channel(output_fn out, + data_cb app_data_cb, + alert_cb alert_cb, + handshake_cb hs_cb, + handshake_msg_cb hs_msg_cb, + Session_Manager& session_manager, + RandomNumberGenerator& rng, + const Policy& policy, + bool is_server, + bool is_datagram, + size_t io_buf_sz = IO_BUF_DEFAULT_SIZE); + + Channel(const Channel&) = delete; + + Channel& operator=(const Channel&) = delete; + + virtual ~Channel(); + + /** + * Inject TLS traffic received from counterparty + * @return a hint as the how many more bytes we need to process the + * current record (this may be 0 if on a record boundary) + */ + size_t received_data(const uint8_t buf[], size_t buf_size); + + /** + * Inject TLS traffic received from counterparty + * @return a hint as the how many more bytes we need to process the + * current record (this may be 0 if on a record boundary) + */ + size_t received_data(const std::vector<uint8_t>& buf); + + /** + * Inject plaintext intended for counterparty + * Throws an exception if is_active() is false + */ + void send(const uint8_t buf[], size_t buf_size); + + /** + * Inject plaintext intended for counterparty + * Throws an exception if is_active() is false + */ + void send(const std::string& val); + + /** + * Inject plaintext intended for counterparty + * Throws an exception if is_active() is false + */ + template<typename Alloc> + void send(const std::vector<unsigned char, Alloc>& val) + { + send(val.data(), val.size()); + } + + /** + * Send a TLS alert message. If the alert is fatal, the internal + * state (keys, etc) will be reset. + * @param alert the Alert to send + */ + void send_alert(const Alert& alert); + + /** + * Send a warning alert + */ + void send_warning_alert(Alert::Type type) { send_alert(Alert(type, false)); } + + /** + * Send a fatal alert + */ + void send_fatal_alert(Alert::Type type) { send_alert(Alert(type, true)); } + + /** + * Send a close notification alert + */ + void close() { send_warning_alert(Alert::CLOSE_NOTIFY); } + + /** + * @return true iff the connection is active for sending application data + */ + bool is_active() const; + + /** + * @return true iff the connection has been definitely closed + */ + bool is_closed() const; + + /** + * @return certificate chain of the peer (may be empty) + */ + std::vector<X509_Certificate> peer_cert_chain() const; + + /** + * Key material export (RFC 5705) + * @param label a disambiguating label string + * @param context a per-association context value + * @param length the length of the desired key in bytes + * @return key of length bytes + */ + SymmetricKey key_material_export(const std::string& label, + const std::string& context, + size_t length) const; + + /** + * Attempt to renegotiate the session + * @param force_full_renegotiation if true, require a full renegotiation, + * otherwise allow session resumption + */ + void renegotiate(bool force_full_renegotiation = false); + + /** + * @return true iff the counterparty supports the secure + * renegotiation extensions. + */ + bool secure_renegotiation_supported() const; + + /** + * Perform a handshake timeout check. This does nothing unless + * this is a DTLS channel with a pending handshake state, in + * which case we check for timeout and potentially retransmit + * handshake packets. + */ + bool timeout_check(); + + virtual std::string application_protocol() const = 0; + + protected: + + virtual void process_handshake_msg(const Handshake_State* active_state, + Handshake_State& pending_state, + Handshake_Type type, + const std::vector<uint8_t>& contents, + bool epoch0_restart) = 0; + + virtual void initiate_handshake(Handshake_State& state, + bool force_full_renegotiation) = 0; + + virtual std::vector<X509_Certificate> + get_peer_cert_chain(const Handshake_State& state) const = 0; + + virtual Handshake_State* new_handshake_state(class Handshake_IO* io) = 0; + + Handshake_State& create_handshake_state(Protocol_Version version); + + void inspect_handshake_message(const Handshake_Message& msg); + + void activate_session(); + + void change_cipher_spec_reader(Connection_Side side); + + void change_cipher_spec_writer(Connection_Side side); + + /* secure renegotiation handling */ + + void secure_renegotiation_check(const Client_Hello* client_hello); + void secure_renegotiation_check(const Server_Hello* server_hello); + + std::vector<uint8_t> secure_renegotiation_data_for_client_hello() const; + std::vector<uint8_t> secure_renegotiation_data_for_server_hello() const; + + RandomNumberGenerator& rng() { return m_rng; } + + Session_Manager& session_manager() { return m_session_manager; } + + const Policy& policy() const { return m_policy; } + + bool save_session(const Session& session); + + Callbacks& callbacks() const { return m_callbacks; } + + void reset_active_association_state(); + + private: + void init(size_t io_buf_sze); + + void send_record(uint8_t record_type, const std::vector<uint8_t>& record); + + void send_record_under_epoch(uint16_t epoch, uint8_t record_type, + const std::vector<uint8_t>& record); + + void send_record_array(uint16_t epoch, uint8_t record_type, + const uint8_t input[], size_t length); + + void write_record(Connection_Cipher_State* cipher_state, + uint16_t epoch, uint8_t type, const uint8_t input[], size_t length); + + void reset_state(); + + Connection_Sequence_Numbers& sequence_numbers() const; + + std::shared_ptr<Connection_Cipher_State> read_cipher_state_epoch(uint16_t epoch) const; + + std::shared_ptr<Connection_Cipher_State> write_cipher_state_epoch(uint16_t epoch) const; + + const Handshake_State* active_state() const { return m_active_state.get(); } + + const Handshake_State* pending_state() const { return m_pending_state.get(); } + + /* methods to handle incoming traffic through Channel::receive_data. */ + void process_handshake_ccs(const secure_vector<uint8_t>& record, + uint64_t record_sequence, + Record_Type record_type, + Protocol_Version record_version, + bool epoch0_restart); + + void process_application_data(uint64_t req_no, const secure_vector<uint8_t>& record); + + void process_alert(const secure_vector<uint8_t>& record); + + const bool m_is_server; + const bool m_is_datagram; + + /* callbacks */ + std::unique_ptr<Compat_Callbacks> m_compat_callbacks; + Callbacks& m_callbacks; + + /* external state */ + Session_Manager& m_session_manager; + const Policy& m_policy; + RandomNumberGenerator& m_rng; + + /* sequence number state */ + std::unique_ptr<Connection_Sequence_Numbers> m_sequence_numbers; + + /* pending and active connection states */ + std::unique_ptr<Handshake_State> m_active_state; + std::unique_ptr<Handshake_State> m_pending_state; + + /* cipher states for each epoch */ + std::map<uint16_t, std::shared_ptr<Connection_Cipher_State>> m_write_cipher_states; + std::map<uint16_t, std::shared_ptr<Connection_Cipher_State>> m_read_cipher_states; + + /* I/O buffers */ + secure_vector<uint8_t> m_writebuf; + secure_vector<uint8_t> m_readbuf; + secure_vector<uint8_t> m_record_buf; + + bool m_has_been_closed; + }; + +} + +} + +#endif |