8#include <botan/tls_session.h>
9#include <botan/internal/loadstor.h>
10#include <botan/der_enc.h>
11#include <botan/ber_dec.h>
12#include <botan/asn1_obj.h>
14#include <botan/aead.h>
18#include <botan/tls_messages.h>
19#include <botan/tls_callbacks.h>
21#include <botan/internal/stl_util.h>
27void Session_Handle::validate_constraints()
const
37 "Session ID cannot be longer than 32 bytes");
43 "Ticket cannot be longer than 64kB");
49 BOTAN_ARG_CHECK(!handle.empty(),
"Opaque session handle must not be empty");
51 "Opaque session handle cannot be longer than 64kB");
65 {
return std::get<Session_ID>(m_handle); }
70 const auto& handle = std::get<Opaque_Session_Handle>(m_handle);
71 if(handle.size() <= 32)
81 {
return std::get<Session_Ticket>(m_handle); }
94 if (!suite.has_value())
103Session_Summary::Session_Summary(
const Session_Base& base,
108 "Instantiated a TLS 1.2 session summary with an newer TLS version");
111 m_psk_used = cs.psk_ciphersuite();
112 m_kex_algo = cs.kex_algo();
113 m_was_resumption = was_resumption;
116#if defined(BOTAN_HAS_TLS_13)
118Session_Summary::Session_Summary(
const Server_Hello_13& server_hello,
120 std::vector<X509_Certificate> peer_certs,
121 Server_Information server_info,
122 std::chrono::system_clock::time_point current_timestamp) :
125 server_hello.selected_version(),
126 server_hello.ciphersuite(),
141 std::move(peer_certs),
142 std::move(server_info))
145 "Instantiated a TLS 1.3 session summary with an older TLS version");
146 set_session_id(server_hello.session_id());
153 m_psk_used = server_hello.extensions().has<
PSK>();
154 m_was_resumption = m_psk_used;
162 if(
const auto keyshare = server_hello.extensions().get<Key_Share>())
164 const auto group = keyshare->selected_group();
166 { return Kex_Algo::DHE_PSK; }
175 const auto keyshare = server_hello.extensions().get<Key_Share>();
177 const auto group = keyshare->selected_group();
193 uint16_t ciphersuite,
195 bool extended_master_secret,
196 bool encrypt_then_mac,
197 const std::vector<X509_Certificate>& certs,
199 uint16_t srtp_profile,
200 std::chrono::system_clock::time_point current_timestamp,
201 std::chrono::seconds lifetime_hint) :
208 extended_master_secret,
212 m_master_secret(master_secret),
213 m_early_data_allowed(false),
214 m_max_early_data_bytes(0),
216 m_lifetime_hint(lifetime_hint)
219 "Instantiated a TLS 1.2 session object with a TLS version newer than 1.2");
222#if defined(BOTAN_HAS_TLS_13)
225 const std::optional<uint32_t>& max_early_data_bytes,
226 uint32_t ticket_age_add,
227 std::chrono::seconds lifetime_hint,
229 uint16_t ciphersuite,
231 const std::vector<X509_Certificate>& peer_certs,
233 std::chrono::system_clock::time_point current_timestamp) :
254 m_master_secret(session_psk),
255 m_early_data_allowed(max_early_data_bytes.has_value()),
256 m_max_early_data_bytes(max_early_data_bytes.value_or(0)),
257 m_ticket_age_add(ticket_age_add),
258 m_lifetime_hint(lifetime_hint)
261 "Instantiated a TLS 1.3 session object with a TLS version older than 1.3");
265 const std::optional<uint32_t>& max_early_data_bytes,
266 std::chrono::seconds lifetime_hint,
267 const std::vector<X509_Certificate>& peer_certs,
268 const Client_Hello_13& client_hello,
269 const Server_Hello_13& server_hello,
270 Callbacks& callbacks,
273 callbacks.tls_current_timestamp(),
274 server_hello.selected_version(),
275 server_hello.ciphersuite(),
279 Server_Information(client_hello.sni_hostname())),
280 m_master_secret(
std::move(session_psk)),
281 m_early_data_allowed(max_early_data_bytes.has_value()),
282 m_max_early_data_bytes(max_early_data_bytes.value_or(0)),
283 m_ticket_age_add(
load_be<uint32_t>(rng.random_vec(4).data(), 0)),
284 m_lifetime_hint(lifetime_hint)
287 "Instantiated a TLS 1.3 session object with a TLS version older than 1.3");
293 :
Session(PEM_Code::decode_check_label(pem,
"TLS SESSION")) {}
297 uint8_t side_code = 0;
303 uint8_t major_version = 0, minor_version = 0;
306 size_t srtp_profile = 0;
313 "Unknown version in serialized TLS session")
323 .decode(server_hostname)
324 .decode(server_service)
326 .decode(srtp_profile)
327 .decode(m_early_data_allowed)
328 .decode_integer_type(m_max_early_data_bytes)
329 .decode_integer_type(m_ticket_age_add)
336 throw Decoding_Error(
"Serialized TLS session contains unknown cipher suite "
347 server_service.
value(),
348 static_cast<uint16_t
>(server_port));
357 .
encode(
static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION))
375 .
encode(m_early_data_allowed)
376 .
encode(
static_cast<size_t>(m_max_early_data_bytes))
377 .
encode(
static_cast<size_t>(m_ticket_age_add))
378 .
encode(
static_cast<size_t>(m_lifetime_hint.count()))
391 return std::exchange(m_master_secret, {});
397const char*
const TLS_SESSION_CRYPT_HMAC =
"HMAC(SHA-512-256)";
399const char*
const TLS_SESSION_CRYPT_AEAD =
"AES-256/GCM";
400const char*
const TLS_SESSION_CRYPT_KEY_NAME =
"BOTAN TLS SESSION KEY NAME";
401const uint64_t TLS_SESSION_CRYPT_MAGIC = 0x068B5A9D396C0000;
402const size_t TLS_SESSION_CRYPT_MAGIC_LEN = 8;
403const size_t TLS_SESSION_CRYPT_KEY_NAME_LEN = 4;
404const size_t TLS_SESSION_CRYPT_AEAD_NONCE_LEN = 12;
405const size_t TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN = 16;
406const size_t TLS_SESSION_CRYPT_AEAD_TAG_SIZE = 16;
408const size_t TLS_SESSION_CRYPT_HDR_LEN =
409 TLS_SESSION_CRYPT_MAGIC_LEN +
410 TLS_SESSION_CRYPT_KEY_NAME_LEN +
411 TLS_SESSION_CRYPT_AEAD_NONCE_LEN +
412 TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN;
414const size_t TLS_SESSION_CRYPT_OVERHEAD =
415 TLS_SESSION_CRYPT_HDR_LEN + TLS_SESSION_CRYPT_AEAD_TAG_SIZE;
426 std::vector<uint8_t> key_name(hmac->output_length());
427 hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
428 hmac->final(key_name.data());
429 key_name.resize(TLS_SESSION_CRYPT_KEY_NAME_LEN);
431 std::vector<uint8_t> aead_nonce;
432 std::vector<uint8_t> key_seed;
434 rng.
random_vec(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
435 rng.
random_vec(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
437 hmac->update(key_seed);
443 std::vector<uint8_t> buf;
444 buf.reserve(TLS_SESSION_CRYPT_OVERHEAD + bits.size());
445 buf.resize(TLS_SESSION_CRYPT_MAGIC_LEN);
446 store_be(TLS_SESSION_CRYPT_MAGIC, &buf[0]);
454 aead->set_key(aead_key);
455 aead->set_associated_data(buf);
456 aead->start(aead_nonce);
457 aead->finish(bits, 0);
468 const size_t min_session_size = 48 + 4;
469 if(in.size() < TLS_SESSION_CRYPT_OVERHEAD + min_session_size)
473 const uint8_t* magic = in.data();
474 const uint8_t* key_name = magic + TLS_SESSION_CRYPT_MAGIC_LEN;
475 const uint8_t* key_seed = key_name + TLS_SESSION_CRYPT_KEY_NAME_LEN;
476 const uint8_t* aead_nonce = key_seed + TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN;
477 const uint8_t* ctext = aead_nonce + TLS_SESSION_CRYPT_AEAD_NONCE_LEN;
478 const size_t ctext_len = in.size() - TLS_SESSION_CRYPT_HDR_LEN;
487 std::vector<uint8_t> cmp_key_name(hmac->output_length());
488 hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
489 hmac->final(cmp_key_name.data());
491 if(
same_mem(cmp_key_name.data(), key_name, TLS_SESSION_CRYPT_KEY_NAME_LEN) ==
false)
494 hmac->update(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
498 aead->set_key(aead_key);
499 aead->set_associated_data(in.data(), TLS_SESSION_CRYPT_HDR_LEN);
500 aead->start(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
502 aead->finish(buf, 0);
505 catch(std::exception& e)
507 throw Decoding_Error(
"Failed to decrypt serialized TLS session: " +
508 std::string(e.what()));
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_STATE_CHECK(expr)
#define BOTAN_ASSERT_NONNULL(ptr)
#define BOTAN_ARG_CHECK(expr, msg)
static std::unique_ptr< AEAD_Mode > create_or_throw(std::string_view algo, Cipher_Dir direction, std::string_view provider="")
const std::string & value() const
BER_Decoder & decode(bool &out)
BER_Decoder & decode_list(std::vector< T > &out, ASN1_Type type_tag=ASN1_Type::Sequence, ASN1_Class class_tag=ASN1_Class::Universal)
BER_Decoder start_sequence()
BER_Decoder & decode_and_check(const T &expected, std::string_view error_msg)
BER_Decoder & decode_integer_type(T &out)
secure_vector< uint8_t > get_contents()
DER_Encoder & encode_list(const std::vector< T > &values)
DER_Encoder & start_sequence()
DER_Encoder & encode(bool b)
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(std::string_view algo_spec, std::string_view provider="")
void random_vec(std::span< uint8_t > v)
static std::optional< Ciphersuite > by_id(uint16_t suite)
uint8_t major_version() const
uint8_t minor_version() const
bool is_pre_tls_13() const
std::vector< X509_Certificate > m_peer_certs
bool m_extended_master_secret
Protocol_Version version() 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
uint16_t ciphersuite_code() const
Ciphersuite ciphersuite() const
Connection_Side m_connection_side
std::optional< Session_Ticket > ticket() const
decltype(auto) get() const
bool is_opaque_handle() const
Opaque_Session_Handle opaque_handle() const
std::optional< Session_ID > id() 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)
std::string PEM_encode() 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())
secure_vector< uint8_t > extract_master_secret()
std::string encode(const uint8_t der[], size_t length, std::string_view label, size_t width)
Strong< std::vector< uint8_t >, struct Session_Ticket_ > Session_Ticket
holds a TLS 1.2 session ticket for stateless resumption
Strong< std::vector< uint8_t >, struct Opaque_Session_Handle_ > Opaque_Session_Handle
holds an opaque session handle as used in TLS 1.3 that could be either a ticket for stateless resumpt...
constexpr bool is_x25519(const Group_Params group)
constexpr bool is_ecdh(const Group_Params group)
std::string kex_method_to_string(Kex_Algo method)
constexpr bool is_dh(const Group_Params group)
Strong< std::vector< uint8_t >, struct Session_ID_ > Session_ID
holds a TLS 1.2 session ID for stateful resumption
constexpr uint64_t load_be< uint64_t >(const uint8_t in[], size_t off)
constexpr void store_be(uint16_t in, uint8_t out[2])
bool same_mem(const T *p1, const T *p2, size_t n)
std::vector< T, secure_allocator< T > > secure_vector
constexpr T load_be(const uint8_t in[], size_t off)