Botan  2.4.0
Crypto and TLS for C++11
tls_callbacks.h
Go to the documentation of this file.
1 /*
2 * TLS Callbacks
3 * (C) 2016 Matthias Gierlings
4 * 2016 Jack Lloyd
5 * 2017 Harry Reimann, Rohde & Schwarz Cybersecurity
6 *
7 * Botan is released under the Simplified BSD License (see license.txt)
8 */
9 
10 #ifndef BOTAN_TLS_CALLBACKS_H_
11 #define BOTAN_TLS_CALLBACKS_H_
12 
13 #include <botan/tls_session.h>
14 #include <botan/tls_alert.h>
15 #include <botan/pubkey.h>
16 #include <functional>
17 
18 namespace Botan {
19 
20 class Certificate_Store;
21 class X509_Certificate;
22 
23 namespace OCSP {
24 
25 class Response;
26 
27 }
28 
29 namespace TLS {
30 
31 class Handshake_Message;
32 class Policy;
33 
34 /**
35 * Encapsulates the callbacks that a TLS channel will make which are due to
36 * channel specific operations.
37 */
39  {
40  public:
41  virtual ~Callbacks() = default;
42 
43  /**
44  * Mandatory callback: output function
45  * The channel will call this with data which needs to be sent to the peer
46  * (eg, over a socket or some other form of IPC). The array will be overwritten
47  * when the function returns so a copy must be made if the data cannot be
48  * sent immediately.
49  *
50  * @param data the vector of data to send
51  *
52  * @param size the number of bytes to send
53  */
54  virtual void tls_emit_data(const uint8_t data[], size_t size) = 0;
55 
56  /**
57  * Mandatory callback: process application data
58  * Called when application data record is received from the peer.
59  * Again the array is overwritten immediately after the function returns.
60  *
61  * @param seq_no the underlying TLS/DTLS record sequence number
62  *
63  * @param data the vector containing the received record
64  *
65  * @param size the length of the received record, in bytes
66  */
67  virtual void tls_record_received(uint64_t seq_no, const uint8_t data[], size_t size) = 0;
68 
69  /**
70  * Mandatory callback: alert received
71  * Called when an alert is received from the peer
72  * If fatal, the connection is closing. If not fatal, the connection may
73  * still be closing (depending on the error and the peer).
74  *
75  * @param alert the source of the alert
76  */
77  virtual void tls_alert(Alert alert) = 0;
78 
79  /**
80  * Mandatory callback: session established
81  * Called when a session is established. Throw an exception to abort
82  * the connection.
83  *
84  * @param session the session descriptor
85  *
86  * @return return false to prevent the session from being cached,
87  * return true to cache the session in the configured session manager
88  */
89  virtual bool tls_session_established(const Session& session) = 0;
90 
91  /**
92  * Optional callback: session activated
93  * Called when a session is active and can be written to
94  */
95  virtual void tls_session_activated() {}
96 
97  /**
98  * Optional callback with default impl: verify cert chain
99  *
100  * Default implementation performs a standard PKIX validation
101  * and initiates network OCSP request for end-entity cert.
102  * Override to provide different behavior.
103  *
104  * Check the certificate chain is valid up to a trusted root, and
105  * optionally (if hostname != "") that the hostname given is
106  * consistent with the leaf certificate.
107  *
108  * This function should throw an exception derived from
109  * std::exception with an informative what() result if the
110  * certificate chain cannot be verified.
111  *
112  * @param cert_chain specifies a certificate chain leading to a
113  * trusted root CA certificate.
114  * @param ocsp_responses the server may have provided some
115  * @param trusted_roots the list of trusted certificates
116  * @param usage what this cert chain is being used for
117  * Usage_Type::TLS_SERVER_AUTH for server chains,
118  * Usage_Type::TLS_CLIENT_AUTH for client chains,
119  * Usage_Type::UNSPECIFIED for other uses
120  * @param hostname when authenticating a server, this is the hostname
121  * the client requested (eg via SNI). When authenticating a client,
122  * this is the server name the client is authenticating *to*.
123  * Empty in other cases or if no hostname was used.
124  * @param policy the TLS policy associated with the session being authenticated
125  * using the certificate chain
126  */
127  virtual void tls_verify_cert_chain(
128  const std::vector<X509_Certificate>& cert_chain,
129  const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses,
130  const std::vector<Certificate_Store*>& trusted_roots,
131  Usage_Type usage,
132  const std::string& hostname,
133  const TLS::Policy& policy);
134 
135  /**
136  * Called by default `tls_verify_cert_chain` to get the timeout to use for OCSP
137  * requests. Return 0 to disable online OCSP checks.
138  */
139  virtual std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const
140  {
141  return std::chrono::milliseconds(0);
142  }
143 
144  /**
145  * Optional callback with default impl: sign a message
146  *
147  * Default implementation uses PK_Signer::sign_message().
148  * Override to provide a different approach, e.g. using an external device.
149  *
150  * @param key the private key of the signer
151  * @param rng a random number generator
152  * @param emsa the encoding method to be applied to the message
153  * @param format the signature format
154  * @param msg the input data for the signature
155  *
156  * @return the signature
157  */
158  virtual std::vector<uint8_t> tls_sign_message(
159  const Private_Key& key,
161  const std::string& emsa,
162  Signature_Format format,
163  const std::vector<uint8_t>& msg);
164 
165  /**
166  * Optional callback with default impl: verify a message signature
167  *
168  * Default implementation uses PK_Verifier::verify_message().
169  * Override to provide a different approach, e.g. using an external device.
170  *
171  * @param key the public key of the signer
172  * @param emsa the encoding method to be applied to the message
173  * @param format the signature format
174  * @param msg the input data for the signature
175  * @param sig the signature to be checked
176  *
177  * @return true if the signature is valid, false otherwise
178  */
179  virtual bool tls_verify_message(
180  const Public_Key& key,
181  const std::string& emsa,
182  Signature_Format format,
183  const std::vector<uint8_t>& msg,
184  const std::vector<uint8_t>& sig);
185 
186  /**
187  * Optional callback with default impl: client side DH agreement
188  *
189  * Default implementation uses PK_Key_Agreement::derive_key().
190  * Override to provide a different approach, e.g. using an external device.
191  *
192  * @param modulus the modulus p of the discrete logarithm group
193  * @param generator the generator of the DH subgroup
194  * @param peer_public_value the public value of the peer
195  * @param policy the TLS policy associated with the session being established
196  * @param rng a random number generator
197  *
198  * @return a pair consisting of the agreed raw secret and our public value
199  */
200  virtual std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> tls_dh_agree(
201  const std::vector<uint8_t>& modulus,
202  const std::vector<uint8_t>& generator,
203  const std::vector<uint8_t>& peer_public_value,
204  const Policy& policy,
205  RandomNumberGenerator& rng);
206 
207  /**
208  * Optional callback with default impl: client side ECDH agreement
209  *
210  * Default implementation uses PK_Key_Agreement::derive_key().
211  * Override to provide a different approach, e.g. using an external device.
212  *
213  * @param curve_name the name of the elliptic curve
214  * @param peer_public_value the public value of the peer
215  * @param policy the TLS policy associated with the session being established
216  * @param rng a random number generator
217  * @param compressed the compression preference for our public value
218  *
219  * @return a pair consisting of the agreed raw secret and our public value
220  */
221  virtual std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> tls_ecdh_agree(
222  const std::string& curve_name,
223  const std::vector<uint8_t>& peer_public_value,
224  const Policy& policy,
226  bool compressed);
227 
228  /**
229  * Optional callback: inspect handshake message
230  * Throw an exception to abort the handshake.
231  * Default simply ignores the message.
232  *
233  * @param message the handshake message
234  */
235  virtual void tls_inspect_handshake_msg(const Handshake_Message& message);
236 
237  /**
238  * Optional callback for server: choose ALPN protocol
239  * ALPN (RFC 7301) works by the client sending a list of application
240  * protocols it is willing to negotiate. The server then selects which
241  * protocol to use, which is not necessarily even on the list that
242  * the client sent.
243  *
244  * @param client_protos the vector of protocols the client is willing to negotiate
245  *
246  * @return the protocol selected by the server, which need not be on the
247  * list that the client sent; if this is the empty string, the server ignores the
248  * client ALPN extension. Default return value is empty string.
249  */
250  virtual std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos);
251 
252  /**
253  * Optional callback: error logging. (not currently called)
254  * @param err An error message related to this connection.
255  */
256  virtual void tls_log_error(const char* err)
257  {
258  BOTAN_UNUSED(err);
259  }
260 
261  /**
262  * Optional callback: debug logging. (not currently called)
263  * @param what Some hopefully informative string
264  */
265  virtual void tls_log_debug(const char* what)
266  {
267  BOTAN_UNUSED(what);
268  }
269 
270  /**
271  * Optional callback: debug logging taking a buffer. (not currently called)
272  * @param descr What this buffer is
273  * @param val the bytes
274  * @param val_len length of val
275  */
276  virtual void tls_log_debug_bin(const char* descr, const uint8_t val[], size_t val_len)
277  {
278  BOTAN_UNUSED(descr, val, val_len);
279  }
280  };
281 
282 /**
283 * TLS::Callbacks using std::function for compatability with the old API signatures.
284 * This type is only provided for backward compatibility.
285 * New implementations should derive from TLS::Callbacks instead.
286 */
287 class BOTAN_PUBLIC_API(2,0) Compat_Callbacks final : public Callbacks
288  {
289  public:
290  typedef std::function<void (const uint8_t[], size_t)> output_fn;
291  typedef std::function<void (const uint8_t[], size_t)> data_cb;
292  typedef std::function<void (Alert, const uint8_t[], size_t)> alert_cb;
293  typedef std::function<bool (const Session&)> handshake_cb;
294  typedef std::function<void (const Handshake_Message&)> handshake_msg_cb;
295  typedef std::function<std::string (std::vector<std::string>)> next_protocol_fn;
296 
297  /**
298  * @param output_fn is called with data for the outbound socket
299  *
300  * @param app_data_cb is called when new application data is received
301  *
302  * @param alert_cb is called when a TLS alert is received
303  *
304  * @param hs_cb is called when a handshake is completed
305  *
306  * @param hs_msg_cb is called for each handshake message received
307  *
308  * @param next_proto is called with ALPN protocol data sent by the client
309  */
310  BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).")
311  Compat_Callbacks(output_fn output_fn, data_cb app_data_cb, alert_cb alert_cb,
312  handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr,
313  next_protocol_fn next_proto = nullptr)
314  : m_output_function(output_fn), m_app_data_cb(app_data_cb),
315  m_alert_cb(std::bind(alert_cb, std::placeholders::_1, nullptr, 0)),
316  m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {}
317 
318  BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).")
319  Compat_Callbacks(output_fn output_fn, data_cb app_data_cb,
320  std::function<void (Alert)> alert_cb,
321  handshake_cb hs_cb,
322  handshake_msg_cb hs_msg_cb = nullptr,
323  next_protocol_fn next_proto = nullptr)
324  : m_output_function(output_fn), m_app_data_cb(app_data_cb),
325  m_alert_cb(alert_cb),
326  m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {}
327 
328  enum class SILENCE_DEPRECATION_WARNING { PLEASE = 0 };
330  output_fn output_fn, data_cb app_data_cb,
331  std::function<void (Alert)> alert_cb,
332  handshake_cb hs_cb,
333  handshake_msg_cb hs_msg_cb = nullptr,
334  next_protocol_fn next_proto = nullptr)
335  : m_output_function(output_fn), m_app_data_cb(app_data_cb),
336  m_alert_cb(alert_cb),
337  m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {}
338 
340  output_fn output_fn, data_cb app_data_cb, alert_cb alert_cb,
341  handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr,
342  next_protocol_fn next_proto = nullptr)
343  : m_output_function(output_fn), m_app_data_cb(app_data_cb),
344  m_alert_cb(std::bind(alert_cb, std::placeholders::_1, nullptr, 0)),
345  m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {}
346 
347 
348  void tls_emit_data(const uint8_t data[], size_t size) override
349  {
350  BOTAN_ASSERT(m_output_function != nullptr,
351  "Invalid TLS output function callback.");
352  m_output_function(data, size);
353  }
354 
355  void tls_record_received(uint64_t /*seq_no*/, const uint8_t data[], size_t size) override
356  {
357  BOTAN_ASSERT(m_app_data_cb != nullptr,
358  "Invalid TLS app data callback.");
359  m_app_data_cb(data, size);
360  }
361 
362  void tls_alert(Alert alert) override
363  {
364  BOTAN_ASSERT(m_alert_cb != nullptr,
365  "Invalid TLS alert callback.");
366  m_alert_cb(alert);
367  }
368 
369  bool tls_session_established(const Session& session) override
370  {
371  BOTAN_ASSERT(m_hs_cb != nullptr,
372  "Invalid TLS handshake callback.");
373  return m_hs_cb(session);
374  }
375 
376  std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos) override
377  {
378  if(m_next_proto != nullptr) { return m_next_proto(client_protos); }
379  return "";
380  }
381 
382  void tls_inspect_handshake_msg(const Handshake_Message& hmsg) override
383  {
384  // The handshake message callback is optional so we can
385  // not assume it has been set.
386  if(m_hs_msg_cb != nullptr) { m_hs_msg_cb(hmsg); }
387  }
388 
389  private:
390  const output_fn m_output_function;
391  const data_cb m_app_data_cb;
392  const std::function<void (Alert)> m_alert_cb;
393  const handshake_cb m_hs_cb;
394  const handshake_msg_cb m_hs_msg_cb;
395  const next_protocol_fn m_next_proto;
396  };
397 
398 }
399 
400 }
401 
402 #endif
std::function< void(const uint8_t[], size_t)> data_cb
Compat_Callbacks(SILENCE_DEPRECATION_WARNING, output_fn output_fn, data_cb app_data_cb, std::function< void(Alert)> alert_cb, handshake_cb hs_cb, handshake_msg_cb hs_msg_cb=nullptr, next_protocol_fn next_proto=nullptr)
void tls_emit_data(const uint8_t data[], size_t size) override
virtual void tls_log_debug(const char *what)
#define BOTAN_PUBLIC_API(maj, min)
Definition: compiler.h:27
Signature_Format
Definition: pubkey.h:27
Definition: bigint.h:635
void tls_alert(Alert alert) override
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:29
std::function< bool(const Session &)> handshake_cb
Compat_Callbacks(SILENCE_DEPRECATION_WARNING, output_fn output_fn, data_cb app_data_cb, alert_cb alert_cb, handshake_cb hs_cb, handshake_msg_cb hs_msg_cb=nullptr, next_protocol_fn next_proto=nullptr)
std::function< void(Alert, const uint8_t[], size_t)> alert_cb
bool tls_session_established(const Session &session) override
virtual std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const
Definition: alg_id.cpp:13
#define BOTAN_UNUSED(...)
Definition: assert.h:106
virtual void tls_session_activated()
Definition: tls_callbacks.h:95
std::function< void(const uint8_t[], size_t)> output_fn
std::function< void(const Handshake_Message &)> handshake_msg_cb
std::function< std::string(std::vector< std::string >)> next_protocol_fn
void tls_inspect_handshake_msg(const Handshake_Message &hmsg) override
std::string tls_server_choose_app_protocol(const std::vector< std::string > &client_protos) override
virtual void tls_log_error(const char *err)
virtual void tls_log_debug_bin(const char *descr, const uint8_t val[], size_t val_len)
Usage_Type
Definition: x509cert.h:25
void tls_record_received(uint64_t, const uint8_t data[], size_t size) override