8#include <botan/tls_session.h>
9#include <botan/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>
27 bool extended_master_secret,
28 bool encrypt_then_mac,
29 const std::vector<X509_Certificate>& certs,
30 const std::vector<uint8_t>& ticket,
32 const std::string& srp_identifier,
33 uint16_t srtp_profile) :
34 m_start_time(
std::chrono::system_clock::now()),
35 m_identifier(session_identifier),
36 m_session_ticket(ticket),
37 m_master_secret(master_secret),
39 m_ciphersuite(ciphersuite),
40 m_connection_side(side),
41 m_srtp_profile(srtp_profile),
42 m_extended_master_secret(extended_master_secret),
43 m_encrypt_then_mac(encrypt_then_mac),
45 m_server_info(server_info),
46 m_srp_identifier(srp_identifier)
54 *
this =
Session(der.data(), der.size());
59 uint8_t side_code = 0;
67 uint8_t major_version = 0, minor_version = 0;
68 std::vector<uint8_t> peer_cert_bits;
71 size_t srtp_profile = 0;
72 size_t fragment_size = 0;
73 size_t compression_method = 0;
78 "Unknown version in serialized TLS session")
88 .
decode(m_extended_master_secret)
89 .
decode(m_encrypt_then_mac)
95 .
decode(srp_identifier_str)
103 if(compression_method != 0)
105 throw Decoding_Error(
"Serialized TLS session contains non-null compression method");
112 if(fragment_size != 0)
114 throw Decoding_Error(
"Serialized TLS session used maximum fragment length which is "
115 " no longer supported");
119 m_start_time = std::chrono::system_clock::from_time_t(
start_time);
121 m_srtp_profile =
static_cast<uint16_t
>(srtp_profile);
124 server_service.
value(),
125 static_cast<uint16_t
>(server_port));
127 m_srp_identifier = srp_identifier_str.
value();
129 if(!peer_cert_bits.empty())
140 std::vector<uint8_t> peer_cert_bits;
141 for(
size_t i = 0; i != m_peer_certs.size(); ++i)
142 peer_cert_bits += m_peer_certs[i].
BER_encode();
146 .
encode(
static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION))
147 .
encode(
static_cast<size_t>(std::chrono::system_clock::to_time_t(m_start_time)))
152 .
encode(
static_cast<size_t>(m_ciphersuite))
153 .
encode(
static_cast<size_t>(0))
154 .
encode(
static_cast<size_t>(m_connection_side))
155 .
encode(
static_cast<size_t>(0))
156 .
encode(m_extended_master_secret)
157 .
encode(m_encrypt_then_mac)
162 .
encode(
static_cast<size_t>(m_server_info.
port()))
164 .
encode(
static_cast<size_t>(m_srtp_profile))
176 return std::chrono::duration_cast<std::chrono::seconds>(
177 std::chrono::system_clock::now() - m_start_time);
183const char* TLS_SESSION_CRYPT_HMAC =
"HMAC(SHA-512-256)";
185const char* TLS_SESSION_CRYPT_AEAD =
"AES-256/GCM";
186const char* TLS_SESSION_CRYPT_KEY_NAME =
"BOTAN TLS SESSION KEY NAME";
187const uint64_t TLS_SESSION_CRYPT_MAGIC = 0x068B5A9D396C0000;
188const size_t TLS_SESSION_CRYPT_MAGIC_LEN = 8;
189const size_t TLS_SESSION_CRYPT_KEY_NAME_LEN = 4;
190const size_t TLS_SESSION_CRYPT_AEAD_NONCE_LEN = 12;
191const size_t TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN = 16;
192const size_t TLS_SESSION_CRYPT_AEAD_TAG_SIZE = 16;
194const size_t TLS_SESSION_CRYPT_HDR_LEN =
195 TLS_SESSION_CRYPT_MAGIC_LEN +
196 TLS_SESSION_CRYPT_KEY_NAME_LEN +
197 TLS_SESSION_CRYPT_AEAD_NONCE_LEN +
198 TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN;
200const size_t TLS_SESSION_CRYPT_OVERHEAD =
201 TLS_SESSION_CRYPT_HDR_LEN + TLS_SESSION_CRYPT_AEAD_TAG_SIZE;
212 std::vector<uint8_t> key_name(hmac->output_length());
213 hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
214 hmac->final(key_name.data());
215 key_name.resize(TLS_SESSION_CRYPT_KEY_NAME_LEN);
217 std::vector<uint8_t> aead_nonce;
218 std::vector<uint8_t> key_seed;
220 rng.
random_vec(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
221 rng.
random_vec(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
223 hmac->update(key_seed);
229 std::vector<uint8_t> buf;
230 buf.reserve(TLS_SESSION_CRYPT_OVERHEAD + bits.size());
231 buf.resize(TLS_SESSION_CRYPT_MAGIC_LEN);
232 store_be(TLS_SESSION_CRYPT_MAGIC, &buf[0]);
240 aead->set_key(aead_key);
241 aead->set_associated_data_vec(buf);
242 aead->start(aead_nonce);
243 aead->finish(bits, 0);
254 const size_t min_session_size = 48 + 4;
255 if(in_len < TLS_SESSION_CRYPT_OVERHEAD + min_session_size)
258 const uint8_t* magic = &in[0];
259 const uint8_t* key_name = magic + TLS_SESSION_CRYPT_MAGIC_LEN;
260 const uint8_t* key_seed = key_name + TLS_SESSION_CRYPT_KEY_NAME_LEN;
261 const uint8_t* aead_nonce = key_seed + TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN;
262 const uint8_t* ctext = aead_nonce + TLS_SESSION_CRYPT_AEAD_NONCE_LEN;
263 const size_t ctext_len = in_len - TLS_SESSION_CRYPT_HDR_LEN;
272 std::vector<uint8_t> cmp_key_name(hmac->output_length());
273 hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
274 hmac->final(cmp_key_name.data());
276 if(
same_mem(cmp_key_name.data(), key_name, TLS_SESSION_CRYPT_KEY_NAME_LEN) ==
false)
279 hmac->update(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
283 aead->set_key(aead_key);
284 aead->set_associated_data(in, TLS_SESSION_CRYPT_HDR_LEN);
285 aead->start(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
287 aead->finish(buf, 0);
288 return Session(buf.data(), buf.size());
290 catch(std::exception& e)
292 throw Decoding_Error(
"Failed to decrypt serialized TLS session: " +
293 std::string(e.what()));
#define BOTAN_ASSERT_NOMSG(expr)
static std::unique_ptr< AEAD_Mode > create_or_throw(const std::string &algo, Cipher_Dir direction, const std::string &provider="")
const std::string & value() const
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
BER_Decoder & decode(bool &out)
BER_Decoder & decode_and_check(const T &expected, const std::string &error_msg)
BER_Decoder & verify_end()
BER_Decoder & decode_integer_type(T &out)
secure_vector< uint8_t > get_contents()
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
DER_Encoder & encode(bool b)
bool end_of_data() const override
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(const std::string &algo_spec, const std::string &provider="")
secure_vector< uint8_t > random_vec(size_t bytes)
uint8_t major_version() const
uint8_t minor_version() const
secure_vector< uint8_t > DER_encode() const
std::vector< uint8_t > encrypt(const SymmetricKey &key, RandomNumberGenerator &rng) const
std::string PEM_encode() const
std::chrono::system_clock::time_point start_time() const
std::chrono::seconds session_age() const
static Session decrypt(const uint8_t ctext[], size_t ctext_size, const SymmetricKey &key)
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
secure_vector< uint8_t > decode_check_label(DataSource &source, const std::string &label_want)
secure_vector< uint8_t > BER_encode(const Private_Key &key)
void store_be(uint16_t in, uint8_t out[2])
uint64_t load_be< uint64_t >(const uint8_t in[], size_t off)
bool same_mem(const T *p1, const T *p2, size_t n)
std::vector< T, secure_allocator< T > > secure_vector