summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/tls/tls_callbacks.h
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/src/lib/tls/tls_callbacks.h')
-rw-r--r--comm/third_party/botan/src/lib/tls/tls_callbacks.h484
1 files changed, 484 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/tls/tls_callbacks.h b/comm/third_party/botan/src/lib/tls/tls_callbacks.h
new file mode 100644
index 0000000000..995c02e2d4
--- /dev/null
+++ b/comm/third_party/botan/src/lib/tls/tls_callbacks.h
@@ -0,0 +1,484 @@
+/*
+* TLS Callbacks
+* (C) 2016 Matthias Gierlings
+* 2016 Jack Lloyd
+* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_TLS_CALLBACKS_H_
+#define BOTAN_TLS_CALLBACKS_H_
+
+#include <botan/tls_session.h>
+#include <botan/tls_alert.h>
+#include <botan/pubkey.h>
+#include <functional>
+
+namespace Botan {
+
+class Certificate_Store;
+class X509_Certificate;
+
+namespace OCSP {
+
+class Response;
+
+}
+
+namespace TLS {
+
+class Handshake_Message;
+class Policy;
+class Extensions;
+class Certificate_Status_Request;
+
+/**
+* Encapsulates the callbacks that a TLS channel will make which are due to
+* channel specific operations.
+*/
+class BOTAN_PUBLIC_API(2,0) Callbacks
+ {
+ public:
+ virtual ~Callbacks() = default;
+
+ /**
+ * Mandatory callback: output function
+ * The channel will call this with data which needs to be sent to the peer
+ * (eg, over a socket or some other form of IPC). The array will be overwritten
+ * when the function returns so a copy must be made if the data cannot be
+ * sent immediately.
+ *
+ * @param data the vector of data to send
+ *
+ * @param size the number of bytes to send
+ */
+ virtual void tls_emit_data(const uint8_t data[], size_t size) = 0;
+
+ /**
+ * Mandatory callback: process application data
+ * Called when application data record is received from the peer.
+ * Again the array is overwritten immediately after the function returns.
+ *
+ * @param seq_no the underlying TLS/DTLS record sequence number
+ *
+ * @param data the vector containing the received record
+ *
+ * @param size the length of the received record, in bytes
+ */
+ virtual void tls_record_received(uint64_t seq_no, const uint8_t data[], size_t size) = 0;
+
+ /**
+ * Mandatory callback: alert received
+ * Called when an alert is received from the peer
+ * If fatal, the connection is closing. If not fatal, the connection may
+ * still be closing (depending on the error and the peer).
+ *
+ * @param alert the source of the alert
+ */
+ virtual void tls_alert(Alert alert) = 0;
+
+ /**
+ * Mandatory callback: session established
+ * Called when a session is established. Throw an exception to abort
+ * the connection.
+ *
+ * @param session the session descriptor
+ *
+ * @return return false to prevent the session from being cached,
+ * return true to cache the session in the configured session manager
+ */
+ virtual bool tls_session_established(const Session& session) = 0;
+
+ /**
+ * Optional callback: session activated
+ * Called when a session is active and can be written to
+ */
+ virtual void tls_session_activated() {}
+
+ /**
+ * Optional callback with default impl: verify cert chain
+ *
+ * Default implementation performs a standard PKIX validation
+ * and initiates network OCSP request for end-entity cert.
+ * Override to provide different behavior.
+ *
+ * Check the certificate chain is valid up to a trusted root, and
+ * optionally (if hostname != "") that the hostname given is
+ * consistent with the leaf certificate.
+ *
+ * This function should throw an exception derived from
+ * std::exception with an informative what() result if the
+ * certificate chain cannot be verified.
+ *
+ * @param cert_chain specifies a certificate chain leading to a
+ * trusted root CA certificate.
+ * @param ocsp_responses the server may have provided some
+ * @param trusted_roots the list of trusted certificates
+ * @param usage what this cert chain is being used for
+ * Usage_Type::TLS_SERVER_AUTH for server chains,
+ * Usage_Type::TLS_CLIENT_AUTH for client chains,
+ * Usage_Type::UNSPECIFIED for other uses
+ * @param hostname when authenticating a server, this is the hostname
+ * the client requested (eg via SNI). When authenticating a client,
+ * this is the server name the client is authenticating *to*.
+ * Empty in other cases or if no hostname was used.
+ * @param policy the TLS policy associated with the session being authenticated
+ * using the certificate chain
+ */
+ virtual void tls_verify_cert_chain(
+ const std::vector<X509_Certificate>& cert_chain,
+ const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses,
+ const std::vector<Certificate_Store*>& trusted_roots,
+ Usage_Type usage,
+ const std::string& hostname,
+ const TLS::Policy& policy);
+
+ /**
+ * Called by default `tls_verify_cert_chain` to get the timeout to use for OCSP
+ * requests. Return 0 to disable online OCSP checks.
+ *
+ * This function should not be "const" since the implementation might need
+ * to perform some side effecting operation to compute the result.
+ */
+ virtual std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const
+ {
+ return std::chrono::milliseconds(0);
+ }
+
+ /**
+ * Called by the TLS server whenever the client included the
+ * status_request extension (see RFC 6066, a.k.a OCSP stapling)
+ * in the ClientHello.
+ *
+ * @return the encoded OCSP response to be sent to the client which
+ * indicates the revocation status of the server certificate. Return an
+ * empty vector to indicate that no response is available, and thus
+ * suppress the Certificate_Status message.
+ */
+ virtual std::vector<uint8_t> tls_provide_cert_status(const std::vector<X509_Certificate>& chain,
+ const Certificate_Status_Request& csr)
+ {
+ BOTAN_UNUSED(chain);
+ BOTAN_UNUSED(csr);
+ return std::vector<uint8_t>();
+ }
+
+ /**
+ * Optional callback with default impl: sign a message
+ *
+ * Default implementation uses PK_Signer::sign_message().
+ * Override to provide a different approach, e.g. using an external device.
+ *
+ * @param key the private key of the signer
+ * @param rng a random number generator
+ * @param emsa the encoding method to be applied to the message
+ * @param format the signature format
+ * @param msg the input data for the signature
+ *
+ * @return the signature
+ */
+ virtual std::vector<uint8_t> tls_sign_message(
+ const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& emsa,
+ Signature_Format format,
+ const std::vector<uint8_t>& msg);
+
+ /**
+ * Optional callback with default impl: verify a message signature
+ *
+ * Default implementation uses PK_Verifier::verify_message().
+ * Override to provide a different approach, e.g. using an external device.
+ *
+ * @param key the public key of the signer
+ * @param emsa the encoding method to be applied to the message
+ * @param format the signature format
+ * @param msg the input data for the signature
+ * @param sig the signature to be checked
+ *
+ * @return true if the signature is valid, false otherwise
+ */
+ virtual bool tls_verify_message(
+ const Public_Key& key,
+ const std::string& emsa,
+ Signature_Format format,
+ const std::vector<uint8_t>& msg,
+ const std::vector<uint8_t>& sig);
+
+ /**
+ * Optional callback with default impl: client side DH agreement
+ *
+ * Default implementation uses PK_Key_Agreement::derive_key().
+ * Override to provide a different approach, e.g. using an external device.
+ *
+ * @param modulus the modulus p of the discrete logarithm group
+ * @param generator the generator of the DH subgroup
+ * @param peer_public_value the public value of the peer
+ * @param policy the TLS policy associated with the session being established
+ * @param rng a random number generator
+ *
+ * @return a pair consisting of the agreed raw secret and our public value
+ */
+ virtual std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> tls_dh_agree(
+ const std::vector<uint8_t>& modulus,
+ const std::vector<uint8_t>& generator,
+ const std::vector<uint8_t>& peer_public_value,
+ const Policy& policy,
+ RandomNumberGenerator& rng);
+
+ /**
+ * Optional callback with default impl: client side ECDH agreement
+ *
+ * Default implementation uses PK_Key_Agreement::derive_key().
+ * Override to provide a different approach, e.g. using an external device.
+ *
+ * @param curve_name the name of the elliptic curve
+ * @param peer_public_value the public value of the peer
+ * @param policy the TLS policy associated with the session being established
+ * @param rng a random number generator
+ * @param compressed the compression preference for our public value
+ *
+ * @return a pair consisting of the agreed raw secret and our public value
+ */
+ virtual std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> tls_ecdh_agree(
+ const std::string& curve_name,
+ const std::vector<uint8_t>& peer_public_value,
+ const Policy& policy,
+ RandomNumberGenerator& rng,
+ bool compressed);
+
+ /**
+ * Optional callback: inspect handshake message
+ * Throw an exception to abort the handshake.
+ * Default simply ignores the message.
+ *
+ * @param message the handshake message
+ */
+ virtual void tls_inspect_handshake_msg(const Handshake_Message& message);
+
+ /**
+ * Optional callback for server: choose ALPN protocol
+ * ALPN (RFC 7301) works by the client sending a list of application
+ * protocols it is willing to negotiate. The server then selects which
+ * protocol to use, which is not necessarily even on the list that
+ * the client sent.
+ *
+ * @param client_protos the vector of protocols the client is willing to negotiate
+ *
+ * @return the protocol selected by the server, which need not be on the
+ * list that the client sent; if this is the empty string, the server ignores the
+ * client ALPN extension. Default return value is empty string.
+ */
+ virtual std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos);
+
+ /**
+ * Optional callback: examine/modify Extensions before sending.
+ *
+ * Both client and server will call this callback on the Extensions object
+ * before serializing it in the client/server hellos. This allows an
+ * application to modify which extensions are sent during the
+ * handshake.
+ *
+ * Default implementation does nothing.
+ *
+ * @param extn the extensions
+ * @param which_side will be CLIENT or SERVER which is the current
+ * applications role in the exchange.
+ */
+ virtual void tls_modify_extensions(Extensions& extn, Connection_Side which_side);
+
+ /**
+ * Optional callback: examine peer extensions.
+ *
+ * Both client and server will call this callback with the Extensions
+ * object after receiving it from the peer. This allows examining the
+ * Extensions, for example to implement a custom extension. It also allows
+ * an application to require that a particular extension be implemented;
+ * throw an exception from this function to abort the handshake.
+ *
+ * Default implementation does nothing.
+ *
+ * @param extn the extensions
+ * @param which_side will be CLIENT if these are are the clients extensions (ie we are
+ * the server) or SERVER if these are the server extensions (we are the client).
+ */
+ virtual void tls_examine_extensions(const Extensions& extn, Connection_Side which_side);
+
+ /**
+ * Optional callback: decode TLS group ID
+ *
+ * TLS uses a 16-bit field to identify ECC and DH groups. This callback
+ * handles the decoding. You only need to implement this if you are using
+ * a custom ECC or DH group (this is extremely uncommon).
+ *
+ * Default implementation uses the standard (IETF-defined) mappings.
+ */
+ virtual std::string tls_decode_group_param(Group_Params group_param);
+
+ /**
+ * Optional callback: return peer network identity
+ *
+ * There is no expected or specified format. The only expectation is this
+ * function will return a unique value. For example returning the peer
+ * host IP and port.
+ *
+ * This is used to bind the DTLS cookie to a particular network identity.
+ * It is only called if the dtls-cookie-secret PSK is also defined.
+ */
+ virtual std::string tls_peer_network_identity();
+
+ /**
+ * Optional callback: error logging. (not currently called)
+ * @param err An error message related to this connection.
+ */
+ virtual void tls_log_error(const char* err)
+ {
+ BOTAN_UNUSED(err);
+ }
+
+ /**
+ * Optional callback: debug logging. (not currently called)
+ * @param what Some hopefully informative string
+ */
+ virtual void tls_log_debug(const char* what)
+ {
+ BOTAN_UNUSED(what);
+ }
+
+ /**
+ * Optional callback: debug logging taking a buffer. (not currently called)
+ * @param descr What this buffer is
+ * @param val the bytes
+ * @param val_len length of val
+ */
+ virtual void tls_log_debug_bin(const char* descr, const uint8_t val[], size_t val_len)
+ {
+ BOTAN_UNUSED(descr, val, val_len);
+ }
+ };
+
+/**
+* TLS::Callbacks using std::function for compatability with the old API signatures.
+* This type is only provided for backward compatibility.
+* New implementations should derive from TLS::Callbacks instead.
+*/
+class BOTAN_PUBLIC_API(2,0) Compat_Callbacks final : public Callbacks
+ {
+ 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;
+ typedef std::function<std::string (std::vector<std::string>)> next_protocol_fn;
+
+ /**
+ * @param data_output_fn is called with data for the outbound socket
+ *
+ * @param app_data_cb is called when new application data is received
+ *
+ * @param recv_alert_cb is called when a TLS alert is received
+ *
+ * @param hs_cb is called when a handshake is completed
+ *
+ * @param hs_msg_cb is called for each handshake message received
+ *
+ * @param next_proto is called with ALPN protocol data sent by the client
+ */
+ BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).")
+ Compat_Callbacks(output_fn data_output_fn, data_cb app_data_cb, alert_cb recv_alert_cb,
+ handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr,
+ next_protocol_fn next_proto = nullptr)
+ : m_output_function(data_output_fn), m_app_data_cb(app_data_cb),
+ m_alert_cb(std::bind(recv_alert_cb, std::placeholders::_1, nullptr, 0)),
+ m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {}
+
+ BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).")
+ Compat_Callbacks(output_fn data_output_fn, data_cb app_data_cb,
+ std::function<void (Alert)> recv_alert_cb,
+ handshake_cb hs_cb,
+ handshake_msg_cb hs_msg_cb = nullptr,
+ next_protocol_fn next_proto = nullptr)
+ : m_output_function(data_output_fn), m_app_data_cb(app_data_cb),
+ m_alert_cb(recv_alert_cb),
+ m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {}
+
+ enum class SILENCE_DEPRECATION_WARNING { PLEASE = 0 };
+ Compat_Callbacks(SILENCE_DEPRECATION_WARNING,
+ output_fn data_output_fn, data_cb app_data_cb,
+ std::function<void (Alert)> recv_alert_cb,
+ handshake_cb hs_cb,
+ handshake_msg_cb hs_msg_cb = nullptr,
+ next_protocol_fn next_proto = nullptr)
+ : m_output_function(data_output_fn),
+ m_app_data_cb(app_data_cb),
+ m_alert_cb(recv_alert_cb),
+ m_hs_cb(hs_cb),
+ m_hs_msg_cb(hs_msg_cb),
+ m_next_proto(next_proto) {}
+
+ Compat_Callbacks(SILENCE_DEPRECATION_WARNING,
+ output_fn data_output_fn, data_cb app_data_cb, alert_cb recv_alert_cb,
+ handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr,
+ next_protocol_fn next_proto = nullptr)
+ : m_output_function(data_output_fn), m_app_data_cb(app_data_cb),
+ m_alert_cb(std::bind(recv_alert_cb, std::placeholders::_1, nullptr, 0)),
+ m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {}
+
+
+ void tls_emit_data(const uint8_t data[], size_t size) override
+ {
+ BOTAN_ASSERT(m_output_function != nullptr,
+ "Invalid TLS output function callback.");
+ m_output_function(data, size);
+ }
+
+ void tls_record_received(uint64_t /*seq_no*/, const uint8_t data[], size_t size) override
+ {
+ BOTAN_ASSERT(m_app_data_cb != nullptr,
+ "Invalid TLS app data callback.");
+ m_app_data_cb(data, size);
+ }
+
+ void tls_alert(Alert alert) override
+ {
+ BOTAN_ASSERT(m_alert_cb != nullptr,
+ "Invalid TLS alert callback.");
+ m_alert_cb(alert);
+ }
+
+ bool tls_session_established(const Session& session) override
+ {
+ BOTAN_ASSERT(m_hs_cb != nullptr,
+ "Invalid TLS handshake callback.");
+ return m_hs_cb(session);
+ }
+
+ std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos) override
+ {
+ if(m_next_proto != nullptr) { return m_next_proto(client_protos); }
+ return "";
+ }
+
+ void tls_inspect_handshake_msg(const Handshake_Message& hmsg) override
+ {
+ // The handshake message callback is optional so we can
+ // not assume it has been set.
+ if(m_hs_msg_cb != nullptr) { m_hs_msg_cb(hmsg); }
+ }
+
+ private:
+ const output_fn m_output_function;
+ const data_cb m_app_data_cb;
+ const std::function<void (Alert)> m_alert_cb;
+ const handshake_cb m_hs_cb;
+ const handshake_msg_cb m_hs_msg_cb;
+ const next_protocol_fn m_next_proto;
+ };
+
+}
+
+}
+
+#endif