Botan  2.18.1
Crypto and TLS for C++11
tls_session.cpp
Go to the documentation of this file.
1 /*
2 * TLS Session State
3 * (C) 2011-2012,2015,2019 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
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>
13 #include <botan/pem.h>
14 #include <botan/aead.h>
15 #include <botan/mac.h>
16 #include <botan/rng.h>
17 
18 namespace Botan {
19 
20 namespace TLS {
21 
22 Session::Session(const std::vector<uint8_t>& session_identifier,
23  const secure_vector<uint8_t>& master_secret,
24  Protocol_Version version,
25  uint16_t ciphersuite,
26  Connection_Side side,
27  bool extended_master_secret,
28  bool encrypt_then_mac,
29  const std::vector<X509_Certificate>& certs,
30  const std::vector<uint8_t>& ticket,
31  const Server_Information& server_info,
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),
38  m_version(version),
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),
44  m_peer_certs(certs),
45  m_server_info(server_info),
46  m_srp_identifier(srp_identifier)
47  {
48  }
49 
50 Session::Session(const std::string& pem)
51  {
52  secure_vector<uint8_t> der = PEM_Code::decode_check_label(pem, "TLS SESSION");
53 
54  *this = Session(der.data(), der.size());
55  }
56 
57 Session::Session(const uint8_t ber[], size_t ber_len)
58  {
59  uint8_t side_code = 0;
60 
61  ASN1_String server_hostname;
62  ASN1_String server_service;
63  size_t server_port;
64 
65  ASN1_String srp_identifier_str;
66 
67  uint8_t major_version = 0, minor_version = 0;
68  std::vector<uint8_t> peer_cert_bits;
69 
70  size_t start_time = 0;
71  size_t srtp_profile = 0;
72  size_t fragment_size = 0;
73  size_t compression_method = 0;
74 
75  BER_Decoder(ber, ber_len)
77  .decode_and_check(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION),
78  "Unknown version in serialized TLS session")
80  .decode_integer_type(major_version)
81  .decode_integer_type(minor_version)
82  .decode(m_identifier, OCTET_STRING)
83  .decode(m_session_ticket, OCTET_STRING)
84  .decode_integer_type(m_ciphersuite)
85  .decode_integer_type(compression_method)
86  .decode_integer_type(side_code)
87  .decode_integer_type(fragment_size)
88  .decode(m_extended_master_secret)
89  .decode(m_encrypt_then_mac)
90  .decode(m_master_secret, OCTET_STRING)
91  .decode(peer_cert_bits, OCTET_STRING)
92  .decode(server_hostname)
93  .decode(server_service)
94  .decode(server_port)
95  .decode(srp_identifier_str)
96  .decode(srtp_profile)
97  .end_cons()
98  .verify_end();
99 
100  /*
101  * Compression is not supported and must be zero
102  */
103  if(compression_method != 0)
104  {
105  throw Decoding_Error("Serialized TLS session contains non-null compression method");
106  }
107 
108  /*
109  Fragment size is not supported anymore, but the field is still
110  set in the session object.
111  */
112  if(fragment_size != 0)
113  {
114  throw Decoding_Error("Serialized TLS session used maximum fragment length which is "
115  " no longer supported");
116  }
117 
118  m_version = Protocol_Version(major_version, minor_version);
119  m_start_time = std::chrono::system_clock::from_time_t(start_time);
120  m_connection_side = static_cast<Connection_Side>(side_code);
121  m_srtp_profile = static_cast<uint16_t>(srtp_profile);
122 
123  m_server_info = Server_Information(server_hostname.value(),
124  server_service.value(),
125  static_cast<uint16_t>(server_port));
126 
127  m_srp_identifier = srp_identifier_str.value();
128 
129  if(!peer_cert_bits.empty())
130  {
131  DataSource_Memory certs(peer_cert_bits.data(), peer_cert_bits.size());
132 
133  while(!certs.end_of_data())
134  m_peer_certs.push_back(X509_Certificate(certs));
135  }
136  }
137 
139  {
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();
143 
144  return DER_Encoder()
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)))
148  .encode(static_cast<size_t>(m_version.major_version()))
149  .encode(static_cast<size_t>(m_version.minor_version()))
150  .encode(m_identifier, OCTET_STRING)
151  .encode(m_session_ticket, OCTET_STRING)
152  .encode(static_cast<size_t>(m_ciphersuite))
153  .encode(static_cast<size_t>(/*old compression method*/0))
154  .encode(static_cast<size_t>(m_connection_side))
155  .encode(static_cast<size_t>(/*old fragment size*/0))
156  .encode(m_extended_master_secret)
157  .encode(m_encrypt_then_mac)
158  .encode(m_master_secret, OCTET_STRING)
159  .encode(peer_cert_bits, OCTET_STRING)
160  .encode(ASN1_String(m_server_info.hostname(), UTF8_STRING))
161  .encode(ASN1_String(m_server_info.service(), UTF8_STRING))
162  .encode(static_cast<size_t>(m_server_info.port()))
163  .encode(ASN1_String(m_srp_identifier, UTF8_STRING))
164  .encode(static_cast<size_t>(m_srtp_profile))
165  .end_cons()
166  .get_contents();
167  }
168 
169 std::string Session::PEM_encode() const
170  {
171  return PEM_Code::encode(this->DER_encode(), "TLS SESSION");
172  }
173 
174 std::chrono::seconds Session::session_age() const
175  {
176  return std::chrono::duration_cast<std::chrono::seconds>(
177  std::chrono::system_clock::now() - m_start_time);
178  }
179 
180 namespace {
181 
182 // The output length of the HMAC must be a valid keylength for the AEAD
183 const char* TLS_SESSION_CRYPT_HMAC = "HMAC(SHA-512-256)";
184 // SIV would be better, but we can't assume it is available
185 const char* TLS_SESSION_CRYPT_AEAD = "AES-256/GCM";
186 const char* TLS_SESSION_CRYPT_KEY_NAME = "BOTAN TLS SESSION KEY NAME";
187 const uint64_t TLS_SESSION_CRYPT_MAGIC = 0x068B5A9D396C0000;
188 const size_t TLS_SESSION_CRYPT_MAGIC_LEN = 8;
189 const size_t TLS_SESSION_CRYPT_KEY_NAME_LEN = 4;
190 const size_t TLS_SESSION_CRYPT_AEAD_NONCE_LEN = 12;
191 const size_t TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN = 16;
192 const size_t TLS_SESSION_CRYPT_AEAD_TAG_SIZE = 16;
193 
194 const 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;
199 
200 const size_t TLS_SESSION_CRYPT_OVERHEAD =
201  TLS_SESSION_CRYPT_HDR_LEN + TLS_SESSION_CRYPT_AEAD_TAG_SIZE;
202 
203 }
204 
205 std::vector<uint8_t>
207  {
208  auto hmac = MessageAuthenticationCode::create_or_throw(TLS_SESSION_CRYPT_HMAC);
209  hmac->set_key(key);
210 
211  // First derive the "key name"
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);
216 
217  std::vector<uint8_t> aead_nonce;
218  std::vector<uint8_t> key_seed;
219 
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);
222 
223  hmac->update(key_seed);
224  const secure_vector<uint8_t> aead_key = hmac->final();
225 
226  secure_vector<uint8_t> bits = this->DER_encode();
227 
228  // create the header
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]);
233  buf += key_name;
234  buf += key_seed;
235  buf += aead_nonce;
236 
237  std::unique_ptr<AEAD_Mode> aead = AEAD_Mode::create_or_throw(TLS_SESSION_CRYPT_AEAD, ENCRYPTION);
238  BOTAN_ASSERT_NOMSG(aead->valid_nonce_length(TLS_SESSION_CRYPT_AEAD_NONCE_LEN));
239  BOTAN_ASSERT_NOMSG(aead->tag_size() == TLS_SESSION_CRYPT_AEAD_TAG_SIZE);
240  aead->set_key(aead_key);
241  aead->set_associated_data_vec(buf);
242  aead->start(aead_nonce);
243  aead->finish(bits, 0);
244 
245  // append the ciphertext
246  buf += bits;
247  return buf;
248  }
249 
250 Session Session::decrypt(const uint8_t in[], size_t in_len, const SymmetricKey& key)
251  {
252  try
253  {
254  const size_t min_session_size = 48 + 4; // serious under-estimate
255  if(in_len < TLS_SESSION_CRYPT_OVERHEAD + min_session_size)
256  throw Decoding_Error("Encrypted session too short to be valid");
257 
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; // includes the tag
264 
265  if(load_be<uint64_t>(magic, 0) != TLS_SESSION_CRYPT_MAGIC)
266  throw Decoding_Error("Missing expected magic numbers");
267 
268  auto hmac = MessageAuthenticationCode::create_or_throw(TLS_SESSION_CRYPT_HMAC);
269  hmac->set_key(key);
270 
271  // First derive and check the "key name"
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());
275 
276  if(same_mem(cmp_key_name.data(), key_name, TLS_SESSION_CRYPT_KEY_NAME_LEN) == false)
277  throw Decoding_Error("Wrong key name for encrypted session");
278 
279  hmac->update(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
280  const secure_vector<uint8_t> aead_key = hmac->final();
281 
282  auto aead = AEAD_Mode::create_or_throw(TLS_SESSION_CRYPT_AEAD, DECRYPTION);
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);
286  secure_vector<uint8_t> buf(ctext, ctext + ctext_len);
287  aead->finish(buf, 0);
288  return Session(buf.data(), buf.size());
289  }
290  catch(std::exception& e)
291  {
292  throw Decoding_Error("Failed to decrypt serialized TLS session: " +
293  std::string(e.what()));
294  }
295  }
296 
297 }
298 
299 }
static Session decrypt(const uint8_t ctext[], size_t ctext_size, const SymmetricKey &key)
secure_vector< uint8_t > random_vec(size_t bytes)
Definition: rng.h:143
bool same_mem(const T *p1, const T *p2, size_t n)
Definition: mem_ops.h:217
BER_Decoder & decode_integer_type(T &out)
Definition: ber_dec.h:242
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:438
uint8_t minor_version() const
Definition: tls_version.h:84
BER_Decoder & decode_and_check(const T &expected, const std::string &error_msg)
Definition: ber_dec.h:277
std::chrono::system_clock::time_point start_time() const
Definition: tls_session.h:168
secure_vector< uint8_t > get_contents()
Definition: der_enc.cpp:152
Definition: bigint.h:1143
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:68
std::string hostname() const
DER_Encoder & end_cons()
Definition: der_enc.cpp:191
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:170
uint64_t load_be< uint64_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:217
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:285
secure_vector< uint8_t > decode_check_label(DataSource &source, const std::string &label_want)
Definition: pem.cpp:54
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:43
BER_Decoder & end_cons()
Definition: ber_dec.cpp:300
std::vector< uint8_t > encrypt(const SymmetricKey &key, RandomNumberGenerator &rng) const
std::string PEM_encode() const
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.cpp:290
Definition: alg_id.cpp:13
secure_vector< uint8_t > BER_encode(const Private_Key &key)
Definition: pkcs8.cpp:139
secure_vector< uint8_t > DER_encode() const
std::chrono::seconds session_age() const
const std::string & value() const
Definition: asn1_obj.h:400
BER_Decoder & verify_end()
Definition: ber_dec.cpp:208
uint8_t major_version() const
Definition: tls_version.h:79
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:181
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: mac.cpp:141
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
static std::unique_ptr< AEAD_Mode > create_or_throw(const std::string &algo, Cipher_Dir direction, const std::string &provider="")
Definition: aead.cpp:50