Coverage Report

Created: 2022-06-23 06:44

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