Botan 3.11.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/secmem.h>
13#include <botan/strong_type.h>
14#include <botan/symkey.h>
15#include <botan/tls_ciphersuite.h>
16#include <botan/tls_magic.h>
17#include <botan/tls_server_info.h>
18#include <botan/tls_session_id.h>
19#include <botan/tls_version.h>
20#include <chrono>
21#include <memory>
22#include <span>
23
24namespace Botan {
25
26class Public_Key;
28
29} // namespace Botan
30
31namespace Botan::TLS {
32
33class Client_Hello_13;
34class Server_Hello_13;
35class Callbacks;
36
37/**
38 * Represents basic information about a session that can be both
39 * persisted for resumption and presented to the application as
40 * a summary of a specific just-established TLS session.
41 */
43 public:
44 Session_Base(std::chrono::system_clock::time_point start_time,
46 uint16_t ciphersuite,
47 Connection_Side connection_side,
48 uint16_t srtp_profile,
49 bool extended_master_secret,
50 bool encrypt_then_mac,
51 const std::vector<X509_Certificate>& peer_certs,
52 std::shared_ptr<const Public_Key> peer_raw_public_key,
54
57
58 Session_Base(Session_Base&& other) noexcept;
60
62
63 protected:
65
66 public:
67 /**
68 * Get the wall clock time this session began
69 */
70 std::chrono::system_clock::time_point start_time() const { return m_start_time; }
71
72 /**
73 * Get the negotiated protocol version of the TLS session
74 */
76
77 /**
78 * Get the ciphersuite code of the negotiated TLS session
79 */
80 uint16_t ciphersuite_code() const { return m_ciphersuite; }
81
82 /**
83 * Get the ciphersuite info of the negotiated TLS session
84 */
85 Ciphersuite ciphersuite() const;
86
87 /**
88 * Get which side of the connection we are/were acting as.
89 */
91
92 /**
93 * Get the negotiated DTLS-SRTP algorithm (RFC 5764)
94 */
95 uint16_t dtls_srtp_profile() const { return m_srtp_profile; }
96
97 /**
98 * Returns true if a TLS 1.2 session negotiated "encrypt then MAC";
99 * TLS 1.3 sessions will always return false as they always use an AEAD.
100 */
102
103 /**
104 * Returns true if a TLS 1.2 session negotiated "extended master secret";
105 * TLS 1.3 sessions will always return true (see RFC 8446 Appendix D).
106 */
108
109 /**
110 * Return the certificate chain of the peer (possibly empty)
111 */
112 const std::vector<X509_Certificate>& peer_certs() const { return m_peer_certs; }
113
114 /**
115 * Return the raw public key of the peer (possibly empty)
116 */
117 std::shared_ptr<const Public_Key> peer_raw_public_key() const { return m_peer_raw_public_key; }
118
119 /**
120 * Get information about the TLS server
121 *
122 * Returns information that identifies the server side of the connection.
123 * This is useful for the client in that it identifies what was originally
124 * passed to the constructor. For the server, it includes the name the
125 * client specified in the server name indicator extension.
126 */
128
129 protected:
130 std::chrono::system_clock::time_point m_start_time; // NOLINT(*non-private-member-variable*)
131
132 Protocol_Version m_version; // NOLINT(*non-private-member-variable*)
133 uint16_t m_ciphersuite = 0; // NOLINT(*non-private-member-variable*)
134 Connection_Side m_connection_side = Connection_Side::Client; // NOLINT(*non-private-member-variable*)
135 uint16_t m_srtp_profile = 0; // NOLINT(*non-private-member-variable*)
136
137 bool m_extended_master_secret = false; // NOLINT(*non-private-member-variable*)
138 bool m_encrypt_then_mac = false; // NOLINT(*non-private-member-variable*)
139
140 std::vector<X509_Certificate> m_peer_certs; // NOLINT(*non-private-member-variable*)
141 std::shared_ptr<const Public_Key> m_peer_raw_public_key; // NOLINT(*non-private-member-variable*)
142 Server_Information m_server_info; // NOLINT(*non-private-member-variable*)
143};
144
145/**
146 * Summarizes the negotiated features after a TLS handshake. Applications may
147 * query those in Callbacks::tls_session_established().
148 */
149class BOTAN_PUBLIC_API(3, 0) Session_Summary : public Session_Base {
150 public:
151 /**
152 * The Session_ID negotiated during the handshake.
153 * Note that this does not carry any meaning in TLS 1.3 and might even
154 * be empty.
155 */
156 const Session_ID& session_id() const { return m_session_id; }
157
158 /**
159 * The session ticket a TLS 1.2 server issued for this session.
160 * Note that this may be set in TLS 1.2 clients only. It is _not_ the
161 * ticket used to establish this session.
162 */
163 const std::optional<Session_Ticket>& session_ticket() const { return m_session_ticket; }
164
165 /**
166 * The negotiated identity of an externally provided preshared key used to
167 * establish this session. For TLS 1.3 this may be any of the externally
168 * provided PSKs offered by the client. PSK identities used as session
169 * tickets for TLS 1.3 session resumption won't be shown here.
170 */
171 const std::optional<std::string>& external_psk_identity() const { return m_external_psk_identity; }
172
173 /**
174 * Indicates that the session was established using an externally provided
175 * PSK. Session resumptions in TLS 1.3 (while technically implemented
176 * using a PSK) are not considered here. @sa was_resumption()
177 *
178 * @note Botan 3.0 and 3.1 did incorrectly report true for session resumption.
179 *
180 * @returns true if the session was established using an externally
181 * provided PSK.
182 */
183 bool psk_used() const { return m_external_psk_identity.has_value(); }
184
185 /**
186 * Indicates that the session was resumed from a previous handshake state.
187 *
188 * @returns true if this session is a resumption, otherwise false
189 */
190 bool was_resumption() const { return m_was_resumption; }
191
192 std::string kex_algo() const { return m_kex_algo; }
193
194 std::optional<std::string> kex_parameters() const { return m_kex_parameters; }
195
196 std::string cipher_algo() const { return ciphersuite().cipher_algo(); }
197
198 std::string mac_algo() const { return ciphersuite().mac_algo(); }
199
200 std::string prf_algo() const { return ciphersuite().prf_algo(); }
201
202 private:
203 friend class Server_Impl_12;
204 friend class Server_Impl_13;
205 friend class Client_Impl_12;
206 friend class Client_Impl_13;
207
208 Session_Summary(const Session_Base& base, bool was_resumption, std::optional<std::string> psk_identity);
209
210#if defined(BOTAN_HAS_TLS_13)
211 Session_Summary(const Server_Hello_13& server_hello,
213 const std::vector<X509_Certificate>& peer_certs,
214 std::shared_ptr<const Public_Key> peer_raw_public_key,
215 std::optional<std::string> psk_identity,
216 bool session_was_resumed,
218 std::chrono::system_clock::time_point current_timestamp);
219#endif
220
221 void set_session_id(Session_ID id) { m_session_id = std::move(id); }
222
223 void set_session_ticket(Session_Ticket ticket) { m_session_ticket = std::move(ticket); }
224
225 private:
226 Session_ID m_session_id;
227 std::optional<Session_Ticket> m_session_ticket;
228 std::optional<std::string> m_external_psk_identity;
229
230 bool m_was_resumption;
231 std::string m_kex_algo;
232 std::optional<std::string> m_kex_parameters;
233};
234
235/**
236 * Represents a session's negotiated features along with all resumption
237 * information to re-establish a TLS connection later on.
238 */
239class BOTAN_PUBLIC_API(3, 0) Session final : public Session_Base {
240 public:
241 /**
242 * New TLS 1.2 session (sets session start time)
243 */
246 uint16_t ciphersuite,
250 const std::vector<X509_Certificate>& peer_certs,
252 uint16_t srtp_profile,
253 std::chrono::system_clock::time_point current_timestamp,
254 std::chrono::seconds lifetime_hint = std::chrono::seconds::max());
255
256#if defined(BOTAN_HAS_TLS_13)
257
258 /**
259 * New TLS 1.3 session (sets session start time)
260 */
261 Session(const secure_vector<uint8_t>& session_psk,
262 const std::optional<uint32_t>& max_early_data_bytes,
263 uint32_t ticket_age_add,
264 std::chrono::seconds lifetime_hint,
266 uint16_t ciphersuite,
268 const std::vector<X509_Certificate>& peer_certs,
269 std::shared_ptr<const Public_Key> peer_raw_public_key,
271 std::chrono::system_clock::time_point current_timestamp);
272
273 /**
274 * Create a new TLS 1.3 session object from server data structures
275 * after a successful handshake with a TLS 1.3 client
276 */
277 Session(secure_vector<uint8_t>&& session_psk,
278 const std::optional<uint32_t>& max_early_data_bytes,
279 std::chrono::seconds lifetime_hint,
280 const std::vector<X509_Certificate>& peer_certs,
281 std::shared_ptr<const Public_Key> peer_raw_public_key,
282 const Client_Hello_13& client_hello,
283 const Server_Hello_13& server_hello,
284 Callbacks& callbacks,
286
287#endif
288
289 /**
290 * Load a session from DER representation (created by DER_encode)
291 * @param ber_data DER representation buffer
292 */
293 BOTAN_FUTURE_EXPLICIT Session(std::span<const uint8_t> ber_data);
294
295 /**
296 * Load a session from PEM representation (created by PEM_encode)
297 * @param pem PEM representation
298 */
299 explicit Session(std::string_view pem);
300
301 /**
302 * Encode this session data for storage
303 * @warning if the master secret is compromised so is the
304 * session traffic
305 */
307
308 /**
309 * Encrypt a session (useful for serialization or session tickets)
310 */
311 std::vector<uint8_t> encrypt(const SymmetricKey& key, RandomNumberGenerator& rng) const;
312
313 /**
314 * Decrypt a session created by encrypt
315 * @param ctext the ciphertext returned by encrypt
316 * @param ctext_size the size of ctext in bytes
317 * @param key the same key used by the encrypting side
318 */
319 static inline Session decrypt(const uint8_t ctext[], size_t ctext_size, const SymmetricKey& key) {
320 return Session::decrypt(std::span(ctext, ctext_size), key);
321 }
322
323 /**
324 * Decrypt a session created by encrypt
325 * @param ctext the ciphertext returned by encrypt
326 * @param key the same key used by the encrypting side
327 */
328 static Session decrypt(std::span<const uint8_t> ctext, const SymmetricKey& key);
329
330 /**
331 * Encode this session data for storage
332 * @warning if the master secret is compromised so is the
333 * session traffic
334 */
335 std::string PEM_encode() const;
336
337 /**
338 * Get a reference to the contained master secret
339 */
340 const secure_vector<uint8_t>& master_secret() const { return m_master_secret; }
341
342 /**
343 * Get the contained master secret as a moved-out object
344 */
345 secure_vector<uint8_t> extract_master_secret();
346
347 /**
348 * Get whether the saved session supports sending/receiving of early data
349 */
350 bool supports_early_data() const { return m_early_data_allowed; }
351
352 /**
353 * Return the ticket obfuscation adder
354 */
355 uint32_t session_age_add() const { return m_ticket_age_add; }
356
357 /**
358 * Return the number of bytes allowed for 0-RTT early data
359 */
360 uint32_t max_early_data_bytes() const { return m_max_early_data_bytes; }
361
362 /**
363 * @return the lifetime of the ticket as defined by the TLS server
364 */
365 std::chrono::seconds lifetime_hint() const { return m_lifetime_hint; }
366
367 private:
368 /*
369 * Struct Version history
370 *
371 * 20160812 - Pre TLS 1.3
372 * 20220505 - Introduction of TLS 1.3 sessions
373 * - added fields:
374 * - m_early_data_allowed
375 * - m_max_early_data_bytes
376 * - m_ticket_age_add
377 * - m_lifetime_hint
378 * 20230112 - Remove Session_ID and Session_Ticket from this object
379 * (association is now in the hands of the Session_Manager)
380 * - Peer certificates are now stored as a SEQUENCE
381 * 20230222 - Remove deprecated and unused fields
382 * - compression method (always 0)
383 * - fragment size (always 0)
384 * - SRP identifier (always "")
385 * 20231031 - Allow storage of peer's raw public key
386 */
387 static constexpr size_t TLS_SESSION_PARAM_STRUCT_VERSION = 20231031;
388
389 secure_vector<uint8_t> m_master_secret;
390
391 bool m_early_data_allowed;
392 uint32_t m_max_early_data_bytes;
393 uint32_t m_ticket_age_add;
394 std::chrono::seconds m_lifetime_hint;
395};
396
397/**
398 * Helper struct to conveniently pass a Session and its Session_Handle around
399 */
405
406} // namespace Botan::TLS
407
408#endif
#define BOTAN_PUBLIC_API(maj, min)
Definition api.h:21
#define BOTAN_FUTURE_EXPLICIT
Definition api.h:52
std::vector< X509_Certificate > m_peer_certs
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, const std::vector< X509_Certificate > &peer_certs, std::shared_ptr< const Public_Key > peer_raw_public_key, Server_Information server_info)
std::shared_ptr< const Public_Key > peer_raw_public_key() const
Session_Base & operator=(Session_Base &&other) noexcept
Session_Base(const Session_Base &other)
uint16_t dtls_srtp_profile() const
Definition tls_session.h:95
Protocol_Version version() const
Definition tls_session.h:75
Connection_Side side() const
Definition tls_session.h:90
bool supports_encrypt_then_mac() const
Protocol_Version m_version
std::chrono::system_clock::time_point m_start_time
Server_Information m_server_info
std::chrono::system_clock::time_point start_time() const
Definition tls_session.h:70
uint16_t ciphersuite_code() const
Definition tls_session.h:80
bool supports_extended_master_secret() const
Session_Base(Session_Base &&other) noexcept
Session_Base & operator=(const Session_Base &other)
Ciphersuite ciphersuite() const
const std::vector< X509_Certificate > & peer_certs() const
const Server_Information & server_info() const
std::shared_ptr< const Public_Key > m_peer_raw_public_key
Connection_Side m_connection_side
Helper class to embody a session handle in all protocol versions.
std::string cipher_algo() const
std::string mac_algo() const
std::string kex_algo() const
const std::optional< Session_Ticket > & session_ticket() const
const std::optional< std::string > & external_psk_identity() const
const Session_ID & session_id() const
std::string prf_algo() const
std::optional< std::string > kex_parameters() const
secure_vector< uint8_t > DER_encode() const
std::vector< uint8_t > encrypt(const SymmetricKey &key, RandomNumberGenerator &rng) const
std::chrono::seconds lifetime_hint() const
static Session decrypt(const uint8_t ctext[], size_t ctext_size, const SymmetricKey &key)
bool supports_early_data() const
uint32_t session_age_add() const
Session(const secure_vector< uint8_t > &master_secret, Protocol_Version version, uint16_t ciphersuite, Connection_Side side, bool supports_extended_master_secret, bool supports_encrypt_then_mac, const std::vector< X509_Certificate > &peer_certs, const Server_Information &server_info, uint16_t srtp_profile, std::chrono::system_clock::time_point current_timestamp, std::chrono::seconds lifetime_hint=std::chrono::seconds::max())
const secure_vector< uint8_t > & master_secret() const
uint32_t max_early_data_bytes() const
Strong< std::vector< uint8_t >, struct Session_ID_ > Session_ID
holds a TLS 1.2 session ID for stateful resumption
Strong< std::vector< uint8_t >, struct Session_Ticket_ > Session_Ticket
holds a TLS 1.2 session ticket for stateless resumption
OctetString SymmetricKey
Definition symkey.h:140
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:68