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