summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/tls/tls_channel.h
diff options
context:
space:
mode:
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.h318
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