Coverage Report

Created: 2020-08-01 06:18

/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/loadstor.h>
10
#include <botan/der_enc.h>
11
#include <botan/ber_dec.h>
12
#include <botan/asn1_str.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
505
   {
48
505
   }
49
50
Session::Session(const std::string& pem)
51
0
   {
52
0
   secure_vector<uint8_t> der = PEM_Code::decode_check_label(pem, "TLS SESSION");
53
0
54
0
   *this = Session(der.data(), der.size());
55
0
   }
56
57
Session::Session(const uint8_t ber[], size_t ber_len)
58
0
   {
59
0
   uint8_t side_code = 0;
60
0
61
0
   ASN1_String server_hostname;
62
0
   ASN1_String server_service;
63
0
   size_t server_port;
64
0
65
0
   ASN1_String srp_identifier_str;
66
0
67
0
   uint8_t major_version = 0, minor_version = 0;
68
0
   std::vector<uint8_t> peer_cert_bits;
69
0
70
0
   size_t start_time = 0;
71
0
   size_t srtp_profile = 0;
72
0
   size_t fragment_size = 0;
73
0
   size_t compression_method = 0;
74
0
75
0
   BER_Decoder(ber, ber_len)
76
0
      .start_cons(SEQUENCE)
77
0
        .decode_and_check(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION),
78
0
                          "Unknown version in serialized TLS session")
79
0
        .decode_integer_type(start_time)
80
0
        .decode_integer_type(major_version)
81
0
        .decode_integer_type(minor_version)
82
0
        .decode(m_identifier, OCTET_STRING)
83
0
        .decode(m_session_ticket, OCTET_STRING)
84
0
        .decode_integer_type(m_ciphersuite)
85
0
        .decode_integer_type(compression_method)
86
0
        .decode_integer_type(side_code)
87
0
        .decode_integer_type(fragment_size)
88
0
        .decode(m_extended_master_secret)
89
0
        .decode(m_encrypt_then_mac)
90
0
        .decode(m_master_secret, OCTET_STRING)
91
0
        .decode(peer_cert_bits, OCTET_STRING)
92
0
        .decode(server_hostname)
93
0
        .decode(server_service)
94
0
        .decode(server_port)
95
0
        .decode(srp_identifier_str)
96
0
        .decode(srtp_profile)
97
0
      .end_cons()
98
0
      .verify_end();
99
0
100
0
   /*
101
0
   * Compression is not supported and must be zero
102
0
   */
103
0
   if(compression_method != 0)
104
0
      {
105
0
      throw Decoding_Error("Serialized TLS session contains non-null compression method");
106
0
      }
107
0
108
0
   /*
109
0
   Fragment size is not supported anymore, but the field is still
110
0
   set in the session object.
111
0
   */
112
0
   if(fragment_size != 0)
113
0
      {
114
0
      throw Decoding_Error("Serialized TLS session used maximum fragment length which is "
115
0
                           " no longer supported");
116
0
      }
117
0
118
0
   m_version = Protocol_Version(major_version, minor_version);
119
0
   m_start_time = std::chrono::system_clock::from_time_t(start_time);
120
0
   m_connection_side = static_cast<Connection_Side>(side_code);
121
0
   m_srtp_profile = static_cast<uint16_t>(srtp_profile);
122
0
123
0
   m_server_info = Server_Information(server_hostname.value(),
124
0
                                      server_service.value(),
125
0
                                      static_cast<uint16_t>(server_port));
126
0
127
0
   m_srp_identifier = srp_identifier_str.value();
128
0
129
0
   if(!peer_cert_bits.empty())
130
0
      {
131
0
      DataSource_Memory certs(peer_cert_bits.data(), peer_cert_bits.size());
132
0
133
0
      while(!certs.end_of_data())
134
0
         m_peer_certs.push_back(X509_Certificate(certs));
135
0
      }
136
0
   }
137
138
secure_vector<uint8_t> Session::DER_encode() const
139
278
   {
140
278
   std::vector<uint8_t> peer_cert_bits;
141
278
   for(size_t i = 0; i != m_peer_certs.size(); ++i)
142
0
      peer_cert_bits += m_peer_certs[i].BER_encode();
143
278
144
278
   return DER_Encoder()
145
278
      .start_cons(SEQUENCE)
146
278
         .encode(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION))
147
278
         .encode(static_cast<size_t>(std::chrono::system_clock::to_time_t(m_start_time)))
148
278
         .encode(static_cast<size_t>(m_version.major_version()))
149
278
         .encode(static_cast<size_t>(m_version.minor_version()))
150
278
         .encode(m_identifier, OCTET_STRING)
151
278
         .encode(m_session_ticket, OCTET_STRING)
152
278
         .encode(static_cast<size_t>(m_ciphersuite))
153
278
         .encode(static_cast<size_t>(/*old compression method*/0))
154
278
         .encode(static_cast<size_t>(m_connection_side))
155
278
         .encode(static_cast<size_t>(/*old fragment size*/0))
156
278
         .encode(m_extended_master_secret)
157
278
         .encode(m_encrypt_then_mac)
158
278
         .encode(m_master_secret, OCTET_STRING)
159
278
         .encode(peer_cert_bits, OCTET_STRING)
160
278
         .encode(ASN1_String(m_server_info.hostname(), UTF8_STRING))
161
278
         .encode(ASN1_String(m_server_info.service(), UTF8_STRING))
162
278
         .encode(static_cast<size_t>(m_server_info.port()))
163
278
         .encode(ASN1_String(m_srp_identifier, UTF8_STRING))
164
278
         .encode(static_cast<size_t>(m_srtp_profile))
165
278
      .end_cons()
166
278
   .get_contents();
167
278
   }
168
169
std::string Session::PEM_encode() const
170
0
   {
171
0
   return PEM_Code::encode(this->DER_encode(), "TLS SESSION");
172
0
   }
173
174
std::chrono::seconds Session::session_age() const
175
0
   {
176
0
   return std::chrono::duration_cast<std::chrono::seconds>(
177
0
      std::chrono::system_clock::now() - m_start_time);
178
0
   }
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>
206
Session::encrypt(const SymmetricKey& key, RandomNumberGenerator& rng) const
207
278
   {
208
278
   auto hmac = MessageAuthenticationCode::create_or_throw(TLS_SESSION_CRYPT_HMAC);
209
278
   hmac->set_key(key);
210
278
211
278
   // First derive the "key name"
212
278
   std::vector<uint8_t> key_name(hmac->output_length());
213
278
   hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
214
278
   hmac->final(key_name.data());
215
278
   key_name.resize(TLS_SESSION_CRYPT_KEY_NAME_LEN);
216
278
217
278
   std::vector<uint8_t> aead_nonce;
218
278
   std::vector<uint8_t> key_seed;
219
278
220
278
   rng.random_vec(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
221
278
   rng.random_vec(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
222
278
223
278
   hmac->update(key_seed);
224
278
   const secure_vector<uint8_t> aead_key = hmac->final();
225
278
226
278
   secure_vector<uint8_t> bits = this->DER_encode();
227
278
228
278
   // create the header
229
278
   std::vector<uint8_t> buf;
230
278
   buf.reserve(TLS_SESSION_CRYPT_OVERHEAD + bits.size());
231
278
   buf.resize(TLS_SESSION_CRYPT_MAGIC_LEN);
232
278
   store_be(TLS_SESSION_CRYPT_MAGIC, &buf[0]);
233
278
   buf += key_name;
234
278
   buf += key_seed;
235
278
   buf += aead_nonce;
236
278
237
278
   std::unique_ptr<AEAD_Mode> aead = AEAD_Mode::create_or_throw(TLS_SESSION_CRYPT_AEAD, ENCRYPTION);
238
278
   BOTAN_ASSERT_NOMSG(aead->valid_nonce_length(TLS_SESSION_CRYPT_AEAD_NONCE_LEN));
239
278
   BOTAN_ASSERT_NOMSG(aead->tag_size() == TLS_SESSION_CRYPT_AEAD_TAG_SIZE);
240
278
   aead->set_key(aead_key);
241
278
   aead->set_associated_data_vec(buf);
242
278
   aead->start(aead_nonce);
243
278
   aead->finish(bits, 0);
244
278
245
278
   // append the ciphertext
246
278
   buf += bits;
247
278
   return buf;
248
278
   }
249
250
Session Session::decrypt(const uint8_t in[], size_t in_len, const SymmetricKey& key)
251
1.03k
   {
252
1.03k
   try
253
1.03k
      {
254
1.03k
      const size_t min_session_size = 48 + 4; // serious under-estimate
255
1.03k
      if(in_len < TLS_SESSION_CRYPT_OVERHEAD + min_session_size)
256
974
         throw Decoding_Error("Encrypted session too short to be valid");
257
59
258
59
      const uint8_t* magic = &in[0];
259
59
      const uint8_t* key_name = magic + TLS_SESSION_CRYPT_MAGIC_LEN;
260
59
      const uint8_t* key_seed = key_name + TLS_SESSION_CRYPT_KEY_NAME_LEN;
261
59
      const uint8_t* aead_nonce = key_seed + TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN;
262
59
      const uint8_t* ctext = aead_nonce + TLS_SESSION_CRYPT_AEAD_NONCE_LEN;
263
59
      const size_t ctext_len = in_len - TLS_SESSION_CRYPT_HDR_LEN; // includes the tag
264
59
265
59
      if(load_be<uint64_t>(magic, 0) != TLS_SESSION_CRYPT_MAGIC)
266
58
         throw Decoding_Error("Missing expected magic numbers");
267
1
268
1
      auto hmac = MessageAuthenticationCode::create_or_throw(TLS_SESSION_CRYPT_HMAC);
269
1
      hmac->set_key(key);
270
1
271
1
      // First derive and check the "key name"
272
1
      std::vector<uint8_t> cmp_key_name(hmac->output_length());
273
1
      hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
274
1
      hmac->final(cmp_key_name.data());
275
1
276
1
      if(same_mem(cmp_key_name.data(), key_name, TLS_SESSION_CRYPT_KEY_NAME_LEN) == false)
277
1
         throw Decoding_Error("Wrong key name for encrypted session");
278
0
279
0
      hmac->update(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
280
0
      const secure_vector<uint8_t> aead_key = hmac->final();
281
0
282
0
      auto aead = AEAD_Mode::create_or_throw(TLS_SESSION_CRYPT_AEAD, DECRYPTION);
283
0
      aead->set_key(aead_key);
284
0
      aead->set_associated_data(in, TLS_SESSION_CRYPT_HDR_LEN);
285
0
      aead->start(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
286
0
      secure_vector<uint8_t> buf(ctext, ctext + ctext_len);
287
0
      aead->finish(buf, 0);
288
0
      return Session(buf.data(), buf.size());
289
0
      }
290
1.03k
   catch(std::exception& e)
291
1.03k
      {
292
1.03k
      throw Decoding_Error("Failed to decrypt serialized TLS session: " +
293
1.03k
                           std::string(e.what()));
294
1.03k
      }
295
1.03k
   }
296
297
}
298
299
}