Coverage Report

Created: 2023-02-13 06:21

/src/botan/src/lib/tls/tls_session.cpp
Line
Count
Source (jump to first uncovered line)
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/internal/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
#include <botan/tls_messages.h>
19
#include <botan/tls_callbacks.h>
20
21
namespace Botan::TLS {
22
23
Session::Session() :
24
   m_start_time(std::chrono::system_clock::time_point::min()),
25
   m_version(),
26
   m_ciphersuite(0),
27
   m_connection_side(static_cast<Connection_Side>(0)),
28
   m_srtp_profile(0),
29
   m_extended_master_secret(false),
30
   m_encrypt_then_mac(false),
31
   m_early_data_allowed(false),
32
   m_max_early_data_bytes(0),
33
   m_ticket_age_add(0),
34
   m_lifetime_hint(0)
35
22.8k
   {}
36
37
Session::Session(const std::vector<uint8_t>& session_identifier,
38
                 const secure_vector<uint8_t>& master_secret,
39
                 Protocol_Version version,
40
                 uint16_t ciphersuite,
41
                 Connection_Side side,
42
                 bool extended_master_secret,
43
                 bool encrypt_then_mac,
44
                 const std::vector<X509_Certificate>& certs,
45
                 const std::vector<uint8_t>& ticket,
46
                 const Server_Information& server_info,
47
                 uint16_t srtp_profile,
48
                 std::chrono::system_clock::time_point current_timestamp,
49
                 std::chrono::seconds lifetime_hint) :
50
   m_start_time(current_timestamp),
51
   m_identifier(session_identifier),
52
   m_session_ticket(ticket),
53
   m_master_secret(master_secret),
54
   m_version(version),
55
   m_ciphersuite(ciphersuite),
56
   m_connection_side(side),
57
   m_srtp_profile(srtp_profile),
58
   m_extended_master_secret(extended_master_secret),
59
   m_encrypt_then_mac(encrypt_then_mac),
60
   m_peer_certs(certs),
61
   m_server_info(server_info),
62
   m_early_data_allowed(false),
63
   m_max_early_data_bytes(0),
64
   m_ticket_age_add(0),
65
   m_lifetime_hint(lifetime_hint)
66
322
   {
67
322
   BOTAN_ARG_CHECK(version.is_pre_tls_13(),
68
322
                   "Instantiated a TLS 1.2 session object with a TLS version newer than 1.2");
69
322
   }
70
71
#if defined(BOTAN_HAS_TLS_13)
72
73
Session::Session(const std::vector<uint8_t>& session_ticket,
74
                 const secure_vector<uint8_t>& session_psk,
75
                 const std::optional<uint32_t>& max_early_data_bytes,
76
                 uint32_t ticket_age_add,
77
                 std::chrono::seconds lifetime_hint,
78
                 Protocol_Version version,
79
                 uint16_t ciphersuite,
80
                 Connection_Side side,
81
                 const std::vector<X509_Certificate>& peer_certs,
82
                 const Server_Information& server_info,
83
                 std::chrono::system_clock::time_point current_timestamp) :
84
   m_start_time(current_timestamp),
85
86
   // In TLS 1.3 the PSK and Session Resumption concepts were merged and the
87
   // explicit SessionID was retired. Instead an opaque session ticket is used
88
   // to identify sessions during resumption. Hence, we deliberately set the
89
   // legacy m_identifier as "empty".
90
   m_identifier(),
91
   m_session_ticket(session_ticket),
92
   m_master_secret(session_psk),
93
   m_version(version),
94
   m_ciphersuite(ciphersuite),
95
   m_connection_side(side),
96
97
   // TODO: Might become necessary when DTLS 1.3 is being implemented.
98
   m_srtp_profile(0),
99
100
   // RFC 8446 Appendix D
101
   //    Because TLS 1.3 always hashes in the transcript up to the server
102
   //    Finished, implementations which support both TLS 1.3 and earlier
103
   //    versions SHOULD indicate the use of the Extended Master Secret
104
   //    extension in their APIs whenever TLS 1.3 is used.
105
   m_extended_master_secret(true),
106
107
   // TLS 1.3 uses AEADs, so technically encrypt-then-MAC is not applicable.
108
   m_encrypt_then_mac(false),
109
   m_peer_certs(peer_certs),
110
   m_server_info(server_info),
111
   m_early_data_allowed(max_early_data_bytes.has_value()),
112
   m_max_early_data_bytes(max_early_data_bytes.value_or(0)),
113
   m_ticket_age_add(ticket_age_add),
114
   m_lifetime_hint(lifetime_hint)
115
0
   {
116
0
   BOTAN_ARG_CHECK(!version.is_pre_tls_13(),
117
0
                   "Instantiated a TLS 1.3 session object with a TLS version older than 1.3");
118
0
   }
119
120
Session::Session(secure_vector<uint8_t>&& session_psk,
121
                 const std::optional<uint32_t>& max_early_data_bytes,
122
                 std::chrono::seconds lifetime_hint,
123
                 const std::vector<X509_Certificate>& peer_certs,
124
                 const Client_Hello_13& client_hello,
125
                 const Server_Hello_13& server_hello,
126
                 Callbacks& callbacks,
127
                 RandomNumberGenerator& rng) :
128
   m_start_time(callbacks.tls_current_timestamp()),
129
   m_master_secret(std::move(session_psk)),
130
   m_version(server_hello.selected_version()),
131
   m_ciphersuite(server_hello.ciphersuite()),
132
   m_connection_side(Connection_Side::Server),
133
   m_extended_master_secret(true),
134
   m_encrypt_then_mac(true),
135
   m_peer_certs(peer_certs),
136
   m_server_info(client_hello.sni_hostname()),
137
   m_early_data_allowed(max_early_data_bytes.has_value()),
138
   m_max_early_data_bytes(max_early_data_bytes.value_or(0)),
139
   m_ticket_age_add(load_be<uint32_t>(rng.random_vec(4).data(), 0)),
140
   m_lifetime_hint(lifetime_hint)
141
0
   {}
142
143
#endif
144
145
Session::Session(const std::string& pem)
146
0
   {
147
0
   secure_vector<uint8_t> der = PEM_Code::decode_check_label(pem, "TLS SESSION");
148
149
0
   *this = Session(der.data(), der.size());
150
0
   }
151
152
Session::Session(const uint8_t ber[], size_t ber_len)
153
0
   {
154
0
   uint8_t side_code = 0;
155
156
0
   ASN1_String server_hostname;
157
0
   ASN1_String server_service;
158
0
   size_t server_port;
159
160
0
   ASN1_String srp_identifier_str;
161
162
0
   uint8_t major_version = 0, minor_version = 0;
163
0
   std::vector<uint8_t> peer_cert_bits;
164
165
0
   size_t start_time = 0;
166
0
   size_t srtp_profile = 0;
167
0
   size_t fragment_size = 0;
168
0
   size_t compression_method = 0;
169
0
   uint16_t ciphersuite_code = 0;
170
0
   uint64_t lifetime_hint = 0;
171
172
0
   BER_Decoder(ber, ber_len)
173
0
      .start_sequence()
174
0
        .decode_and_check(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION),
175
0
                          "Unknown version in serialized TLS session")
176
0
        .decode_integer_type(start_time)
177
0
        .decode_integer_type(major_version)
178
0
        .decode_integer_type(minor_version)
179
0
        .decode(m_identifier, ASN1_Type::OctetString)
180
0
        .decode(m_session_ticket, ASN1_Type::OctetString)
181
0
        .decode_integer_type(ciphersuite_code)
182
0
        .decode_integer_type(compression_method)
183
0
        .decode_integer_type(side_code)
184
0
        .decode_integer_type(fragment_size)
185
0
        .decode(m_extended_master_secret)
186
0
        .decode(m_encrypt_then_mac)
187
0
        .decode(m_master_secret, ASN1_Type::OctetString)
188
0
        .decode(peer_cert_bits, ASN1_Type::OctetString)
189
0
        .decode(server_hostname)
190
0
        .decode(server_service)
191
0
        .decode(server_port)
192
0
        .decode(srp_identifier_str)
193
0
        .decode(srtp_profile)
194
0
        .decode(m_early_data_allowed)
195
0
        .decode_integer_type(m_max_early_data_bytes)
196
0
        .decode_integer_type(m_ticket_age_add)
197
0
        .decode_integer_type(lifetime_hint)
198
0
      .end_cons()
199
0
      .verify_end();
200
201
   /*
202
   * Compression is not supported and must be zero
203
   */
204
0
   if(compression_method != 0)
205
0
      {
206
0
      throw Decoding_Error("Serialized TLS session contains non-null compression method");
207
0
      }
208
209
   /*
210
   Fragment size is not supported anymore, but the field is still
211
   set in the session object.
212
   */
213
0
   if(fragment_size != 0)
214
0
      {
215
0
      throw Decoding_Error("Serialized TLS session used maximum fragment length which is "
216
0
                           " no longer supported");
217
0
      }
218
219
0
   if(!Ciphersuite::by_id(ciphersuite_code))
220
0
      {
221
0
      throw Decoding_Error("Serialized TLS session contains unknown cipher suite "
222
0
                           "(" + std::to_string(ciphersuite_code) + ")");
223
0
      }
224
225
0
   m_ciphersuite = ciphersuite_code;
226
0
   m_version = Protocol_Version(major_version, minor_version);
227
0
   m_start_time = std::chrono::system_clock::from_time_t(start_time);
228
0
   m_connection_side = static_cast<Connection_Side>(side_code);
229
0
   m_srtp_profile = static_cast<uint16_t>(srtp_profile);
230
231
0
   m_server_info = Server_Information(server_hostname.value(),
232
0
                                      server_service.value(),
233
0
                                      static_cast<uint16_t>(server_port));
234
235
0
   if(!peer_cert_bits.empty())
236
0
      {
237
0
      DataSource_Memory certs(peer_cert_bits.data(), peer_cert_bits.size());
238
239
0
      while(!certs.end_of_data())
240
0
         m_peer_certs.push_back(X509_Certificate(certs));
241
0
      }
242
243
0
   m_lifetime_hint = std::chrono::seconds(lifetime_hint);
244
0
   }
245
246
secure_vector<uint8_t> Session::DER_encode() const
247
173
   {
248
   // TODO note for anyone making an incompatible change to the
249
   // encodings of TLS sessions. The peer cert list should have been a
250
   // SEQUENCE not a concatenation:
251
252
173
   std::vector<uint8_t> peer_cert_bits;
253
173
   for(const auto& peer_cert : m_peer_certs)
254
0
      peer_cert_bits += peer_cert.BER_encode();
255
256
173
   return DER_Encoder()
257
173
      .start_sequence()
258
173
         .encode(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION))
259
173
         .encode(static_cast<size_t>(std::chrono::system_clock::to_time_t(m_start_time)))
260
173
         .encode(static_cast<size_t>(m_version.major_version()))
261
173
         .encode(static_cast<size_t>(m_version.minor_version()))
262
173
         .encode(m_identifier, ASN1_Type::OctetString)
263
173
         .encode(m_session_ticket, ASN1_Type::OctetString)
264
173
         .encode(static_cast<size_t>(m_ciphersuite))
265
173
         .encode(static_cast<size_t>(/*old compression method*/0))
266
173
         .encode(static_cast<size_t>(m_connection_side))
267
173
         .encode(static_cast<size_t>(/*old fragment size*/0))
268
173
         .encode(m_extended_master_secret)
269
173
         .encode(m_encrypt_then_mac)
270
173
         .encode(m_master_secret, ASN1_Type::OctetString)
271
173
         .encode(peer_cert_bits, ASN1_Type::OctetString)
272
173
         .encode(ASN1_String(m_server_info.hostname(), ASN1_Type::Utf8String))
273
173
         .encode(ASN1_String(m_server_info.service(), ASN1_Type::Utf8String))
274
173
         .encode(static_cast<size_t>(m_server_info.port()))
275
173
         .encode(ASN1_String("", ASN1_Type::Utf8String)) // old srp identifier
276
173
         .encode(static_cast<size_t>(m_srtp_profile))
277
278
         // the fields below were introduced for TLS 1.3 session tickets
279
173
         .encode(m_early_data_allowed)
280
173
         .encode(static_cast<size_t>(m_max_early_data_bytes))
281
173
         .encode(static_cast<size_t>(m_ticket_age_add))
282
173
         .encode(static_cast<size_t>(m_lifetime_hint.count()))
283
173
      .end_cons()
284
173
   .get_contents();
285
173
   }
286
287
std::string Session::PEM_encode() const
288
0
   {
289
0
   return PEM_Code::encode(this->DER_encode(), "TLS SESSION");
290
0
   }
291
292
Ciphersuite Session::ciphersuite() const
293
0
   {
294
0
   auto suite = Ciphersuite::by_id(m_ciphersuite);
295
0
   if (!suite.has_value())
296
0
      {
297
0
      throw Decoding_Error("Failed to find cipher suite for ID " +
298
0
                           std::to_string(m_ciphersuite));
299
0
      }
300
0
   return suite.value();
301
0
   }
302
303
const std::vector<uint8_t>& Session::session_id() const
304
0
   {
305
0
   if(m_version.is_pre_tls_13())
306
0
      return m_identifier;
307
308
   // RFC 8446 4.6.1
309
   //    ticket:  The value of the ticket to be used as the PSK identity.  The
310
   //             ticket itself is an opaque label.  It MAY be either a database
311
   //             lookup key or a self-encrypted and self-authenticated value.
312
0
   BOTAN_ASSERT_NOMSG(m_identifier.empty());
313
0
   return m_session_ticket;
314
0
   }
315
316
namespace {
317
318
// The output length of the HMAC must be a valid keylength for the AEAD
319
const char* const TLS_SESSION_CRYPT_HMAC = "HMAC(SHA-512-256)";
320
// SIV would be better, but we can't assume it is available
321
const char* const TLS_SESSION_CRYPT_AEAD = "AES-256/GCM";
322
const char* const TLS_SESSION_CRYPT_KEY_NAME = "BOTAN TLS SESSION KEY NAME";
323
const uint64_t TLS_SESSION_CRYPT_MAGIC = 0x068B5A9D396C0000;
324
const size_t TLS_SESSION_CRYPT_MAGIC_LEN = 8;
325
const size_t TLS_SESSION_CRYPT_KEY_NAME_LEN = 4;
326
const size_t TLS_SESSION_CRYPT_AEAD_NONCE_LEN = 12;
327
const size_t TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN = 16;
328
const size_t TLS_SESSION_CRYPT_AEAD_TAG_SIZE = 16;
329
330
const size_t TLS_SESSION_CRYPT_HDR_LEN =
331
   TLS_SESSION_CRYPT_MAGIC_LEN +
332
   TLS_SESSION_CRYPT_KEY_NAME_LEN +
333
   TLS_SESSION_CRYPT_AEAD_NONCE_LEN +
334
   TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN;
335
336
const size_t TLS_SESSION_CRYPT_OVERHEAD =
337
   TLS_SESSION_CRYPT_HDR_LEN + TLS_SESSION_CRYPT_AEAD_TAG_SIZE;
338
339
}
340
341
std::vector<uint8_t>
342
Session::encrypt(const SymmetricKey& key, RandomNumberGenerator& rng) const
343
173
   {
344
173
   auto hmac = MessageAuthenticationCode::create_or_throw(TLS_SESSION_CRYPT_HMAC);
345
173
   hmac->set_key(key);
346
347
   // First derive the "key name"
348
173
   std::vector<uint8_t> key_name(hmac->output_length());
349
173
   hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
350
173
   hmac->final(key_name.data());
351
173
   key_name.resize(TLS_SESSION_CRYPT_KEY_NAME_LEN);
352
353
173
   std::vector<uint8_t> aead_nonce;
354
173
   std::vector<uint8_t> key_seed;
355
356
173
   rng.random_vec(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
357
173
   rng.random_vec(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
358
359
173
   hmac->update(key_seed);
360
173
   const secure_vector<uint8_t> aead_key = hmac->final();
361
362
173
   secure_vector<uint8_t> bits = this->DER_encode();
363
364
   // create the header
365
173
   std::vector<uint8_t> buf;
366
173
   buf.reserve(TLS_SESSION_CRYPT_OVERHEAD + bits.size());
367
173
   buf.resize(TLS_SESSION_CRYPT_MAGIC_LEN);
368
173
   store_be(TLS_SESSION_CRYPT_MAGIC, &buf[0]);
369
173
   buf += key_name;
370
173
   buf += key_seed;
371
173
   buf += aead_nonce;
372
373
173
   std::unique_ptr<AEAD_Mode> aead = AEAD_Mode::create_or_throw(TLS_SESSION_CRYPT_AEAD, Cipher_Dir::Encryption);
374
173
   BOTAN_ASSERT_NOMSG(aead->valid_nonce_length(TLS_SESSION_CRYPT_AEAD_NONCE_LEN));
375
173
   BOTAN_ASSERT_NOMSG(aead->tag_size() == TLS_SESSION_CRYPT_AEAD_TAG_SIZE);
376
173
   aead->set_key(aead_key);
377
173
   aead->set_associated_data_vec(buf);
378
173
   aead->start(aead_nonce);
379
173
   aead->finish(bits, 0);
380
381
   // append the ciphertext
382
173
   buf += bits;
383
173
   return buf;
384
173
   }
385
386
Session Session::decrypt(const uint8_t in[], size_t in_len, const SymmetricKey& key)
387
4.27k
   {
388
4.27k
   try
389
4.27k
      {
390
4.27k
      const size_t min_session_size = 48 + 4; // serious under-estimate
391
4.27k
      if(in_len < TLS_SESSION_CRYPT_OVERHEAD + min_session_size)
392
3.96k
         throw Decoding_Error("Encrypted session too short to be valid");
393
394
308
      const uint8_t* magic = &in[0];
395
308
      const uint8_t* key_name = magic + TLS_SESSION_CRYPT_MAGIC_LEN;
396
308
      const uint8_t* key_seed = key_name + TLS_SESSION_CRYPT_KEY_NAME_LEN;
397
308
      const uint8_t* aead_nonce = key_seed + TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN;
398
308
      const uint8_t* ctext = aead_nonce + TLS_SESSION_CRYPT_AEAD_NONCE_LEN;
399
308
      const size_t ctext_len = in_len - TLS_SESSION_CRYPT_HDR_LEN; // includes the tag
400
401
308
      if(load_be<uint64_t>(magic, 0) != TLS_SESSION_CRYPT_MAGIC)
402
304
         throw Decoding_Error("Missing expected magic numbers");
403
404
4
      auto hmac = MessageAuthenticationCode::create_or_throw(TLS_SESSION_CRYPT_HMAC);
405
4
      hmac->set_key(key);
406
407
      // First derive and check the "key name"
408
4
      std::vector<uint8_t> cmp_key_name(hmac->output_length());
409
4
      hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
410
4
      hmac->final(cmp_key_name.data());
411
412
4
      if(same_mem(cmp_key_name.data(), key_name, TLS_SESSION_CRYPT_KEY_NAME_LEN) == false)
413
4
         throw Decoding_Error("Wrong key name for encrypted session");
414
415
0
      hmac->update(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
416
0
      const secure_vector<uint8_t> aead_key = hmac->final();
417
418
0
      auto aead = AEAD_Mode::create_or_throw(TLS_SESSION_CRYPT_AEAD, Cipher_Dir::Decryption);
419
0
      aead->set_key(aead_key);
420
0
      aead->set_associated_data(in, TLS_SESSION_CRYPT_HDR_LEN);
421
0
      aead->start(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
422
0
      secure_vector<uint8_t> buf(ctext, ctext + ctext_len);
423
0
      aead->finish(buf, 0);
424
0
      return Session(buf.data(), buf.size());
425
4
      }
426
4.27k
   catch(std::exception& e)
427
4.27k
      {
428
4.27k
      throw Decoding_Error("Failed to decrypt serialized TLS session: " +
429
4.27k
                           std::string(e.what()));
430
4.27k
      }
431
4.27k
   }
432
433
}