Coverage Report

Created: 2022-01-14 08:07

/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
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
                 uint16_t srtp_profile) :
33
   m_start_time(std::chrono::system_clock::now()),
34
   m_identifier(session_identifier),
35
   m_session_ticket(ticket),
36
   m_master_secret(master_secret),
37
   m_version(version),
38
   m_ciphersuite(ciphersuite),
39
   m_connection_side(side),
40
   m_srtp_profile(srtp_profile),
41
   m_extended_master_secret(extended_master_secret),
42
   m_encrypt_then_mac(encrypt_then_mac),
43
   m_peer_certs(certs),
44
   m_server_info(server_info)
45
309
   {
46
309
   }
47
48
Session::Session(const std::string& pem)
49
0
   {
50
0
   secure_vector<uint8_t> der = PEM_Code::decode_check_label(pem, "TLS SESSION");
51
52
0
   *this = Session(der.data(), der.size());
53
0
   }
54
55
Session::Session(const uint8_t ber[], size_t ber_len)
56
0
   {
57
0
   uint8_t side_code = 0;
58
59
0
   ASN1_String server_hostname;
60
0
   ASN1_String server_service;
61
0
   size_t server_port;
62
63
0
   ASN1_String srp_identifier_str;
64
65
0
   uint8_t major_version = 0, minor_version = 0;
66
0
   std::vector<uint8_t> peer_cert_bits;
67
68
0
   size_t start_time = 0;
69
0
   size_t srtp_profile = 0;
70
0
   size_t fragment_size = 0;
71
0
   size_t compression_method = 0;
72
0
   uint16_t ciphersuite_code = 0;
73
74
0
   BER_Decoder(ber, ber_len)
75
0
      .start_sequence()
76
0
        .decode_and_check(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION),
77
0
                          "Unknown version in serialized TLS session")
78
0
        .decode_integer_type(start_time)
79
0
        .decode_integer_type(major_version)
80
0
        .decode_integer_type(minor_version)
81
0
        .decode(m_identifier, ASN1_Type::OctetString)
82
0
        .decode(m_session_ticket, ASN1_Type::OctetString)
83
0
        .decode_integer_type(ciphersuite_code)
84
0
        .decode_integer_type(compression_method)
85
0
        .decode_integer_type(side_code)
86
0
        .decode_integer_type(fragment_size)
87
0
        .decode(m_extended_master_secret)
88
0
        .decode(m_encrypt_then_mac)
89
0
        .decode(m_master_secret, ASN1_Type::OctetString)
90
0
        .decode(peer_cert_bits, ASN1_Type::OctetString)
91
0
        .decode(server_hostname)
92
0
        .decode(server_service)
93
0
        .decode(server_port)
94
0
        .decode(srp_identifier_str)
95
0
        .decode(srtp_profile)
96
0
      .end_cons()
97
0
      .verify_end();
98
99
   /*
100
   * Compression is not supported and must be zero
101
   */
102
0
   if(compression_method != 0)
103
0
      {
104
0
      throw Decoding_Error("Serialized TLS session contains non-null compression method");
105
0
      }
106
107
   /*
108
   Fragment size is not supported anymore, but the field is still
109
   set in the session object.
110
   */
111
0
   if(fragment_size != 0)
112
0
      {
113
0
      throw Decoding_Error("Serialized TLS session used maximum fragment length which is "
114
0
                           " no longer supported");
115
0
      }
116
117
0
   if(!Ciphersuite::by_id(ciphersuite_code))
118
0
      {
119
0
      throw Decoding_Error("Serialized TLS session contains unknown cipher suite "
120
0
                           "(" + std::to_string(ciphersuite_code) + ")");
121
0
      }
122
123
0
   m_ciphersuite = ciphersuite_code;
124
0
   m_version = Protocol_Version(major_version, minor_version);
125
0
   m_start_time = std::chrono::system_clock::from_time_t(start_time);
126
0
   m_connection_side = static_cast<Connection_Side>(side_code);
127
0
   m_srtp_profile = static_cast<uint16_t>(srtp_profile);
128
129
0
   m_server_info = Server_Information(server_hostname.value(),
130
0
                                      server_service.value(),
131
0
                                      static_cast<uint16_t>(server_port));
132
133
0
   if(!peer_cert_bits.empty())
134
0
      {
135
0
      DataSource_Memory certs(peer_cert_bits.data(), peer_cert_bits.size());
136
137
0
      while(!certs.end_of_data())
138
0
         m_peer_certs.push_back(X509_Certificate(certs));
139
0
      }
140
0
   }
141
142
secure_vector<uint8_t> Session::DER_encode() const
143
227
   {
144
227
   std::vector<uint8_t> peer_cert_bits;
145
227
   for(size_t i = 0; i != m_peer_certs.size(); ++i)
146
0
      peer_cert_bits += m_peer_certs[i].BER_encode();
147
148
227
   return DER_Encoder()
149
227
      .start_sequence()
150
227
         .encode(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION))
151
227
         .encode(static_cast<size_t>(std::chrono::system_clock::to_time_t(m_start_time)))
152
227
         .encode(static_cast<size_t>(m_version.major_version()))
153
227
         .encode(static_cast<size_t>(m_version.minor_version()))
154
227
         .encode(m_identifier, ASN1_Type::OctetString)
155
227
         .encode(m_session_ticket, ASN1_Type::OctetString)
156
227
         .encode(static_cast<size_t>(m_ciphersuite))
157
227
         .encode(static_cast<size_t>(/*old compression method*/0))
158
227
         .encode(static_cast<size_t>(m_connection_side))
159
227
         .encode(static_cast<size_t>(/*old fragment size*/0))
160
227
         .encode(m_extended_master_secret)
161
227
         .encode(m_encrypt_then_mac)
162
227
         .encode(m_master_secret, ASN1_Type::OctetString)
163
227
         .encode(peer_cert_bits, ASN1_Type::OctetString)
164
227
         .encode(ASN1_String(m_server_info.hostname(), ASN1_Type::Utf8String))
165
227
         .encode(ASN1_String(m_server_info.service(), ASN1_Type::Utf8String))
166
227
         .encode(static_cast<size_t>(m_server_info.port()))
167
227
         .encode(ASN1_String("", ASN1_Type::Utf8String)) // old srp identifier
168
227
         .encode(static_cast<size_t>(m_srtp_profile))
169
227
      .end_cons()
170
227
   .get_contents();
171
227
   }
172
173
std::string Session::PEM_encode() const
174
0
   {
175
0
   return PEM_Code::encode(this->DER_encode(), "TLS SESSION");
176
0
   }
177
178
Ciphersuite Session::ciphersuite() const
179
0
   {
180
0
   auto suite = Ciphersuite::by_id(m_ciphersuite);
181
0
   if (!suite.has_value())
182
0
      {
183
0
      throw Decoding_Error("Failed to find cipher suite for ID " +
184
0
                           std::to_string(m_ciphersuite));
185
0
      }
186
0
   return suite.value();
187
0
   }
188
189
std::chrono::seconds Session::session_age() const
190
0
   {
191
0
   return std::chrono::duration_cast<std::chrono::seconds>(
192
0
      std::chrono::system_clock::now() - m_start_time);
193
0
   }
194
195
namespace {
196
197
// The output length of the HMAC must be a valid keylength for the AEAD
198
const char* TLS_SESSION_CRYPT_HMAC = "HMAC(SHA-512-256)";
199
// SIV would be better, but we can't assume it is available
200
const char* TLS_SESSION_CRYPT_AEAD = "AES-256/GCM";
201
const char* TLS_SESSION_CRYPT_KEY_NAME = "BOTAN TLS SESSION KEY NAME";
202
const uint64_t TLS_SESSION_CRYPT_MAGIC = 0x068B5A9D396C0000;
203
const size_t TLS_SESSION_CRYPT_MAGIC_LEN = 8;
204
const size_t TLS_SESSION_CRYPT_KEY_NAME_LEN = 4;
205
const size_t TLS_SESSION_CRYPT_AEAD_NONCE_LEN = 12;
206
const size_t TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN = 16;
207
const size_t TLS_SESSION_CRYPT_AEAD_TAG_SIZE = 16;
208
209
const size_t TLS_SESSION_CRYPT_HDR_LEN =
210
   TLS_SESSION_CRYPT_MAGIC_LEN +
211
   TLS_SESSION_CRYPT_KEY_NAME_LEN +
212
   TLS_SESSION_CRYPT_AEAD_NONCE_LEN +
213
   TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN;
214
215
const size_t TLS_SESSION_CRYPT_OVERHEAD =
216
   TLS_SESSION_CRYPT_HDR_LEN + TLS_SESSION_CRYPT_AEAD_TAG_SIZE;
217
218
}
219
220
std::vector<uint8_t>
221
Session::encrypt(const SymmetricKey& key, RandomNumberGenerator& rng) const
222
227
   {
223
227
   auto hmac = MessageAuthenticationCode::create_or_throw(TLS_SESSION_CRYPT_HMAC);
224
227
   hmac->set_key(key);
225
226
   // First derive the "key name"
227
227
   std::vector<uint8_t> key_name(hmac->output_length());
228
227
   hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
229
227
   hmac->final(key_name.data());
230
227
   key_name.resize(TLS_SESSION_CRYPT_KEY_NAME_LEN);
231
232
227
   std::vector<uint8_t> aead_nonce;
233
227
   std::vector<uint8_t> key_seed;
234
235
227
   rng.random_vec(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
236
227
   rng.random_vec(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
237
238
227
   hmac->update(key_seed);
239
227
   const secure_vector<uint8_t> aead_key = hmac->final();
240
241
227
   secure_vector<uint8_t> bits = this->DER_encode();
242
243
   // create the header
244
227
   std::vector<uint8_t> buf;
245
227
   buf.reserve(TLS_SESSION_CRYPT_OVERHEAD + bits.size());
246
227
   buf.resize(TLS_SESSION_CRYPT_MAGIC_LEN);
247
227
   store_be(TLS_SESSION_CRYPT_MAGIC, &buf[0]);
248
227
   buf += key_name;
249
227
   buf += key_seed;
250
227
   buf += aead_nonce;
251
252
227
   std::unique_ptr<AEAD_Mode> aead = AEAD_Mode::create_or_throw(TLS_SESSION_CRYPT_AEAD, ENCRYPTION);
253
227
   BOTAN_ASSERT_NOMSG(aead->valid_nonce_length(TLS_SESSION_CRYPT_AEAD_NONCE_LEN));
254
227
   BOTAN_ASSERT_NOMSG(aead->tag_size() == TLS_SESSION_CRYPT_AEAD_TAG_SIZE);
255
227
   aead->set_key(aead_key);
256
227
   aead->set_associated_data_vec(buf);
257
227
   aead->start(aead_nonce);
258
227
   aead->finish(bits, 0);
259
260
   // append the ciphertext
261
227
   buf += bits;
262
227
   return buf;
263
227
   }
264
265
Session Session::decrypt(const uint8_t in[], size_t in_len, const SymmetricKey& key)
266
5.44k
   {
267
5.44k
   try
268
5.44k
      {
269
5.44k
      const size_t min_session_size = 48 + 4; // serious under-estimate
270
5.44k
      if(in_len < TLS_SESSION_CRYPT_OVERHEAD + min_session_size)
271
5.38k
         throw Decoding_Error("Encrypted session too short to be valid");
272
273
63
      const uint8_t* magic = &in[0];
274
63
      const uint8_t* key_name = magic + TLS_SESSION_CRYPT_MAGIC_LEN;
275
63
      const uint8_t* key_seed = key_name + TLS_SESSION_CRYPT_KEY_NAME_LEN;
276
63
      const uint8_t* aead_nonce = key_seed + TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN;
277
63
      const uint8_t* ctext = aead_nonce + TLS_SESSION_CRYPT_AEAD_NONCE_LEN;
278
63
      const size_t ctext_len = in_len - TLS_SESSION_CRYPT_HDR_LEN; // includes the tag
279
280
63
      if(load_be<uint64_t>(magic, 0) != TLS_SESSION_CRYPT_MAGIC)
281
63
         throw Decoding_Error("Missing expected magic numbers");
282
283
0
      auto hmac = MessageAuthenticationCode::create_or_throw(TLS_SESSION_CRYPT_HMAC);
284
0
      hmac->set_key(key);
285
286
      // First derive and check the "key name"
287
0
      std::vector<uint8_t> cmp_key_name(hmac->output_length());
288
0
      hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
289
0
      hmac->final(cmp_key_name.data());
290
291
0
      if(same_mem(cmp_key_name.data(), key_name, TLS_SESSION_CRYPT_KEY_NAME_LEN) == false)
292
0
         throw Decoding_Error("Wrong key name for encrypted session");
293
294
0
      hmac->update(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
295
0
      const secure_vector<uint8_t> aead_key = hmac->final();
296
297
0
      auto aead = AEAD_Mode::create_or_throw(TLS_SESSION_CRYPT_AEAD, DECRYPTION);
298
0
      aead->set_key(aead_key);
299
0
      aead->set_associated_data(in, TLS_SESSION_CRYPT_HDR_LEN);
300
0
      aead->start(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
301
0
      secure_vector<uint8_t> buf(ctext, ctext + ctext_len);
302
0
      aead->finish(buf, 0);
303
0
      return Session(buf.data(), buf.size());
304
0
      }
305
5.44k
   catch(std::exception& e)
306
5.44k
      {
307
5.44k
      throw Decoding_Error("Failed to decrypt serialized TLS session: " +
308
5.44k
                           std::string(e.what()));
309
5.44k
      }
310
5.44k
   }
311
312
}
313
314
}