Botan 3.0.0
Crypto and TLS for C&
tls_session.h
Go to the documentation of this file.
1/*
2* TLS Session
3* (C) 2011-2012,2015 Jack Lloyd
4* (C) 2022 René Meusel - Rohde & Schwarz Cybersecurity
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#ifndef BOTAN_TLS_SESSION_STATE_H_
10#define BOTAN_TLS_SESSION_STATE_H_
11
12#include <botan/x509cert.h>
13#include <botan/tls_version.h>
14#include <botan/tls_ciphersuite.h>
15#include <botan/tls_magic.h>
16#include <botan/tls_server_info.h>
17#include <botan/secmem.h>
18#include <botan/strong_type.h>
19#include <botan/symkey.h>
20
21#include <algorithm>
22#include <chrono>
23#include <span>
24#include <variant>
25
26namespace Botan {
27
28namespace TLS {
29
30// Different flavors of session handles are used, depending on the usage
31// scenario and the TLS protocol version.
32
33/// @brief holds a TLS 1.2 session ID for stateful resumption
34using Session_ID = Strong<std::vector<uint8_t>, struct Session_ID_>;
35
36/// @brief holds a TLS 1.2 session ticket for stateless resumption
37using Session_Ticket = Strong<std::vector<uint8_t>, struct Session_Ticket_>;
38
39/// @brief holds an opaque session handle as used in TLS 1.3 that could be
40/// either a ticket for stateless resumption or a database handle.
41using Opaque_Session_Handle = Strong<std::vector<uint8_t>, struct Opaque_Session_Handle_>;
42
43inline auto operator<(const Session_ID& id1, const Session_ID& id2)
44 {
45 // TODO: C++20 better use std::lexicographical_compare_three_way
46 // that was not available on all target platforms at the time
47 // of this writing.
48 return std::lexicographical_compare(id1.begin(), id1.end(),
49 id2.begin(), id2.end());
50 }
51
52/**
53 * @brief Helper class to embody a session handle in all protocol versions
54 *
55 * Sessions in TLS 1.2 are identified by an arbitrary and unique ID of up to
56 * 32 bytes or by a self-contained arbitrary-length ticket (RFC 5077).
57 *
58 * TLS 1.3 does not distinct between the two and handles both as tickets. Also
59 * a TLS 1.3 server can issue multiple tickets in one connection and the
60 * resumption mechanism is compatible with the PSK establishment.
61 *
62 * Concrete implementations of Session_Manager use this helper to distinguish
63 * the different states and manage sessions for TLS 1.2 and 1.3 connections.
64 *
65 * Note that all information stored in a Session_Handle might be transmitted in
66 * unprotected form. Hence, it should not contain any confidential information.
67 */
69 {
70 public:
71 /**
72 * Constructs a Session_Handle from a session ID which is an
73 * arbitrary byte vector that must be 32 bytes long at most.
74 */
75 Session_Handle(Session_ID id) : m_handle(std::move(id))
76 { validate_constraints(); }
77
78 /**
79 * Constructs a Session_Handle from a session ticket which is a
80 * non-empty byte vector that must be 64kB long at most.
81 * Typically, tickets facilitate stateless server implementations
82 * and contain all relevant context in encrypted/authenticated form.
83 *
84 * Note that (for technical reasons) we enforce that tickets are
85 * longer than 32 bytes.
86 */
87 Session_Handle(Session_Ticket ticket) : m_handle(std::move(ticket))
88 { validate_constraints(); }
89
90 /**
91 * Constructs a Session_Handle from an Opaque_Handle such as TLS 1.3
92 * uses them in its resumption mechanism. This could be either a
93 * Session_ID or a Session_Ticket and it is up to the Session_Manager
94 * to figure out what it actually is.
95 */
96 Session_Handle(Opaque_Session_Handle ticket) : m_handle(std::move(ticket))
97 { validate_constraints(); }
98
99 bool is_id() const { return std::holds_alternative<Session_ID>(m_handle); }
100 bool is_ticket() const { return std::holds_alternative<Session_Ticket>(m_handle); }
101 bool is_opaque_handle() const { return std::holds_alternative<Opaque_Session_Handle>(m_handle); }
102
103 /**
104 * Returns the Session_Handle as an opaque handle. If the object was not
105 * constructed as an Opaque_Session_Handle, the contained value is
106 * converted.
107 */
108 Opaque_Session_Handle opaque_handle() const;
109
110 /**
111 * If the Session_Handle was constructed with a Session_ID or an
112 * Opaque_Session_Handle that can be converted to a Session_ID (up to
113 * 32 bytes long), this returns the handle as a Session_ID. Otherwise,
114 * std::nullopt is returned.
115 */
116 std::optional<Session_ID> id() const;
117
118 /**
119 * If the Session_Handle was constructed with a Session_Ticket or an
120 * Opaque_Session_Handle this returns the handle as a Session_ID.
121 * Otherwise, std::nullopt is returned.
122 */
123 std::optional<Session_Ticket> ticket() const;
124
125 decltype(auto) get() const { return m_handle; }
126
127 private:
128 void validate_constraints() const;
129
130 private:
131 std::variant<Session_ID, Session_Ticket, Opaque_Session_Handle> m_handle;
132 };
133
134class Client_Hello_13;
135class Server_Hello_13;
136class Callbacks;
137
138/**
139 * Represents basic information about a session that can be both
140 * persisted for resumption and presented to the application as
141 * a summary of a specific just-established TLS session.
142 */
144 {
145 public:
146 Session_Base(std::chrono::system_clock::time_point start_time,
147 Protocol_Version version,
148 uint16_t ciphersuite,
149 Connection_Side connection_side,
150 uint16_t srtp_profile,
151 bool extended_master_secret,
152 bool encrypt_then_mac,
153 std::vector<X509_Certificate> peer_certs,
154 Server_Information server_info)
155 : m_start_time(start_time)
156 , m_version(version)
157 , m_ciphersuite(ciphersuite)
158 , m_connection_side(connection_side)
159 , m_srtp_profile(srtp_profile)
160 , m_extended_master_secret(extended_master_secret)
161 , m_encrypt_then_mac(encrypt_then_mac)
162 , m_peer_certs(std::move(peer_certs))
163 , m_server_info(std::move(server_info)) {}
164
165 protected:
167
168 public:
169 /**
170 * Get the wall clock time this session began
171 */
172 std::chrono::system_clock::time_point start_time() const { return m_start_time; }
173
174 /**
175 * Get the negotiated protocol version of the TLS session
176 */
177 Protocol_Version version() const { return m_version; }
178
179 /**
180 * Get the ciphersuite code of the negotiated TLS session
181 */
182 uint16_t ciphersuite_code() const { return m_ciphersuite; }
183
184 /**
185 * Get the ciphersuite info of the negotiated TLS session
186 */
187 Ciphersuite ciphersuite() const;
188
189 /**
190 * Get which side of the connection we are/were acting as.
191 */
192 Connection_Side side() const { return m_connection_side; }
193
194 /**
195 * Get the negotiated DTLS-SRTP algorithm (RFC 5764)
196 */
197 uint16_t dtls_srtp_profile() const { return m_srtp_profile; }
198
199 /**
200 * Returns true if a TLS 1.2 session negotiated "encrypt then MAC";
201 * TLS 1.3 sessions will always return false as they always use an AEAD.
202 */
203 bool supports_encrypt_then_mac() const { return m_encrypt_then_mac; }
204
205 /**
206 * Returns true if a TLS 1.2 session negotiated "extended master secret";
207 * TLS 1.3 sessions will always return true (see RFC 8446 Appendix D).
208 */
209 bool supports_extended_master_secret() const { return m_extended_master_secret; }
210
211 /**
212 * Return the certificate chain of the peer (possibly empty)
213 */
214 const std::vector<X509_Certificate>& peer_certs() const { return m_peer_certs; }
215
216 /**
217 * Get information about the TLS server
218 */
219 const Server_Information& server_info() const { return m_server_info; }
220
221 protected:
222 std::chrono::system_clock::time_point m_start_time;
223
228
231
232 std::vector<X509_Certificate> m_peer_certs;
234 };
235
236
237/**
238 * Summarizes the negotiated features after a TLS handshake. Applications may
239 * query those in Callbacks::tls_session_established().
240 */
242 {
243 public:
244 /**
245 * The Session_ID negotiated during the handshake.
246 * Note that this does not carry any meaning in TLS 1.3 and might even
247 * be empty.
248 */
249 const Session_ID& session_id() const { return m_session_id; }
250
251 /**
252 * The session ticket a TLS 1.2 server issued for this session.
253 * Note that this may be set in TLS 1.2 clients only. It is _not_ the
254 * ticket used to establish this session.
255 */
256 const std::optional<Session_Ticket>& session_ticket() const { return m_session_ticket; }
257
258 bool psk_used() const { return m_psk_used; }
259 bool was_resumption() const { return m_was_resumption; }
260 std::string kex_algo() const { return m_kex_algo; }
261 std::string cipher_algo() const { return ciphersuite().cipher_algo(); }
262 std::string mac_algo() const { return ciphersuite().mac_algo(); }
263 std::string prf_algo() const { return ciphersuite().prf_algo(); }
264
265 private:
266 friend class Server_Impl_12;
267 friend class Server_Impl_13;
268 friend class Client_Impl_12;
269 friend class Client_Impl_13;
270
271 Session_Summary(const Session_Base& base, bool was_resumption);
272
273#if defined(BOTAN_HAS_TLS_13)
274 Session_Summary(const Server_Hello_13& server_hello,
275 Connection_Side side,
276 std::vector<X509_Certificate> peer_certs,
277 Server_Information server_info,
278 std::chrono::system_clock::time_point current_timestamp);
279#endif
280
281 void set_session_id(Session_ID id) { m_session_id = std::move(id); }
282 void set_session_ticket(Session_Ticket ticket) { m_session_ticket = std::move(ticket); }
283
284 private:
285 Session_ID m_session_id;
286 std::optional<Session_Ticket> m_session_ticket;
287
288 bool m_psk_used;
289 bool m_was_resumption;
290 std::string m_kex_algo;
291 };
292
293
294/**
295 * Represents a session's negotiated features along with all resumption
296 * information to re-establish a TLS connection later on.
297 */
299 {
300 public:
301 /**
302 * New TLS 1.2 session (sets session start time)
303 */
304 Session(const secure_vector<uint8_t>& master_secret,
305 Protocol_Version version,
306 uint16_t ciphersuite,
307 Connection_Side side,
308 bool supports_extended_master_secret,
309 bool supports_encrypt_then_mac,
310 const std::vector<X509_Certificate>& peer_certs,
311 const Server_Information& server_info,
312 uint16_t srtp_profile,
313 std::chrono::system_clock::time_point current_timestamp,
314 std::chrono::seconds lifetime_hint = std::chrono::seconds::max());
315
316#if defined(BOTAN_HAS_TLS_13)
317
318 /**
319 * New TLS 1.3 session (sets session start time)
320 */
321 Session(const secure_vector<uint8_t>& session_psk,
322 const std::optional<uint32_t>& max_early_data_bytes,
323 uint32_t ticket_age_add,
324 std::chrono::seconds lifetime_hint,
325 Protocol_Version version,
326 uint16_t ciphersuite,
327 Connection_Side side,
328 const std::vector<X509_Certificate>& peer_certs,
329 const Server_Information& server_info,
330 std::chrono::system_clock::time_point current_timestamp);
331
332 /**
333 * Create a new TLS 1.3 session object from server data structures
334 * after a successful handshake with a TLS 1.3 client
335 */
336 Session(secure_vector<uint8_t>&& session_psk,
337 const std::optional<uint32_t>& max_early_data_bytes,
338 std::chrono::seconds lifetime_hint,
339 const std::vector<X509_Certificate>& peer_certs,
340 const Client_Hello_13& client_hello,
341 const Server_Hello_13& server_hello,
342 Callbacks& callbacks,
344
345#endif
346
347 /**
348 * Load a session from DER representation (created by DER_encode)
349 * @param ber_data DER representation buffer
350 */
351 Session(std::span<const uint8_t> ber_data);
352
353 /**
354 * Load a session from PEM representation (created by PEM_encode)
355 * @param pem PEM representation
356 */
357 explicit Session(std::string_view pem);
358
359 /**
360 * Encode this session data for storage
361 * @warning if the master secret is compromised so is the
362 * session traffic
363 */
364 secure_vector<uint8_t> DER_encode() const;
365
366 /**
367 * Encrypt a session (useful for serialization or session tickets)
368 */
369 std::vector<uint8_t> encrypt(const SymmetricKey& key,
370 RandomNumberGenerator& rng) const;
371
372 /**
373 * Decrypt a session created by encrypt
374 * @param ctext the ciphertext returned by encrypt
375 * @param ctext_size the size of ctext in bytes
376 * @param key the same key used by the encrypting side
377 */
378 static inline Session decrypt(const uint8_t ctext[],
379 size_t ctext_size,
380 const SymmetricKey& key)
381 { return Session::decrypt(std::span(ctext, ctext_size), key); }
382
383 /**
384 * Decrypt a session created by encrypt
385 * @param ctext the ciphertext returned by encrypt
386 * @param key the same key used by the encrypting side
387 */
388 static Session decrypt(std::span<const uint8_t> ctext, const SymmetricKey& key);
389
390 /**
391 * Encode this session data for storage
392 * @warning if the master secret is compromised so is the
393 * session traffic
394 */
395 std::string PEM_encode() const;
396
397 /**
398 * Get a reference to the contained master secret
399 */
400 const secure_vector<uint8_t>& master_secret() const { return m_master_secret; }
401
402 /**
403 * Get the contained master secret as a moved-out object
404 */
405 secure_vector<uint8_t> extract_master_secret();
406
407 /**
408 * Get whether the saved session supports sending/receiving of early data
409 */
410 bool supports_early_data() const { return m_early_data_allowed; }
411
412 /**
413 * Return the ticket obfuscation adder
414 */
415 uint32_t session_age_add() const { return m_ticket_age_add; }
416
417 /**
418 * Return the number of bytes allowed for 0-RTT early data
419 */
420 uint32_t max_early_data_bytes() const { return m_max_early_data_bytes; }
421
422 /**
423 * @return the lifetime of the ticket as defined by the TLS server
424 */
425 std::chrono::seconds lifetime_hint() const { return m_lifetime_hint; }
426
427 private:
428 // Struct Version history
429 //
430 // 20160812 - Pre TLS 1.3
431 // 20220505 - Introduction of TLS 1.3 sessions
432 // - added fields:
433 // - m_early_data_allowed
434 // - m_max_early_data_bytes
435 // - m_ticket_age_add
436 // - m_lifetime_hint
437 // 20230112 - Remove Session_ID and Session_Ticket from this object
438 // (association is now in the hands of the Session_Manager)
439 // - Peer certificates are now stored as a SEQUENCE
440 // 20230222 - Remove deprecated and unused fields
441 // - compression method (always 0)
442 // - fragment size (always 0)
443 // - SRP identifier (always "")
444 enum
445 {
446 TLS_SESSION_PARAM_STRUCT_VERSION = 20230222
447 };
448
449 secure_vector<uint8_t> m_master_secret;
450
451 bool m_early_data_allowed;
452 uint32_t m_max_early_data_bytes;
453 uint32_t m_ticket_age_add;
454 std::chrono::seconds m_lifetime_hint;
455 };
456
457/**
458 * Helper struct to conveniently pass a Session and its Session_Handle around
459 */
461 {
464 };
465
466}
467
468}
469
470#endif
std::vector< X509_Certificate > m_peer_certs
Definition: tls_session.h:232
uint16_t dtls_srtp_profile() const
Definition: tls_session.h:197
Protocol_Version version() const
Definition: tls_session.h:177
Connection_Side side() const
Definition: tls_session.h:192
bool supports_encrypt_then_mac() const
Definition: tls_session.h:203
Protocol_Version m_version
Definition: tls_session.h:224
std::chrono::system_clock::time_point m_start_time
Definition: tls_session.h:222
Server_Information m_server_info
Definition: tls_session.h:233
std::chrono::system_clock::time_point start_time() const
Definition: tls_session.h:172
uint16_t ciphersuite_code() const
Definition: tls_session.h:182
bool supports_extended_master_secret() const
Definition: tls_session.h:209
Session_Base(std::chrono::system_clock::time_point start_time, Protocol_Version version, uint16_t ciphersuite, Connection_Side connection_side, uint16_t srtp_profile, bool extended_master_secret, bool encrypt_then_mac, std::vector< X509_Certificate > peer_certs, Server_Information server_info)
Definition: tls_session.h:146
const std::vector< X509_Certificate > & peer_certs() const
Definition: tls_session.h:214
const Server_Information & server_info() const
Definition: tls_session.h:219
Connection_Side m_connection_side
Definition: tls_session.h:226
Helper class to embody a session handle in all protocol versions.
Definition: tls_session.h:69
decltype(auto) get() const
Definition: tls_session.h:125
Session_Handle(Session_Ticket ticket)
Definition: tls_session.h:87
bool is_opaque_handle() const
Definition: tls_session.h:101
Session_Handle(Session_ID id)
Definition: tls_session.h:75
Session_Handle(Opaque_Session_Handle ticket)
Definition: tls_session.h:96
std::string cipher_algo() const
Definition: tls_session.h:261
std::string mac_algo() const
Definition: tls_session.h:262
std::string kex_algo() const
Definition: tls_session.h:260
const std::optional< Session_Ticket > & session_ticket() const
Definition: tls_session.h:256
const Session_ID & session_id() const
Definition: tls_session.h:249
std::string prf_algo() const
Definition: tls_session.h:263
std::chrono::seconds lifetime_hint() const
Definition: tls_session.h:425
static Session decrypt(const uint8_t ctext[], size_t ctext_size, const SymmetricKey &key)
Definition: tls_session.h:378
bool supports_early_data() const
Definition: tls_session.h:410
uint32_t session_age_add() const
Definition: tls_session.h:415
const secure_vector< uint8_t > & master_secret() const
Definition: tls_session.h:400
uint32_t max_early_data_bytes() const
Definition: tls_session.h:420
int(* final)(unsigned char *, CTX *)
#define BOTAN_PUBLIC_API(maj, min)
Definition: compiler.h:31
bool operator<(const Server_Information &a, const Server_Information &b)
Definition: alg_id.cpp:12
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:64
Definition: bigint.h:1092