Coverage Report

Created: 2021-04-07 06: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
430
   {
46
430
   }
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
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(m_ciphersuite)
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
   m_version = Protocol_Version(major_version, minor_version);
117
0
   m_start_time = std::chrono::system_clock::from_time_t(start_time);
118
0
   m_connection_side = static_cast<Connection_Side>(side_code);
119
0
   m_srtp_profile = static_cast<uint16_t>(srtp_profile);
120
121
0
   m_server_info = Server_Information(server_hostname.value(),
122
0
                                      server_service.value(),
123
0
                                      static_cast<uint16_t>(server_port));
124
125
0
   if(!peer_cert_bits.empty())
126
0
      {
127
0
      DataSource_Memory certs(peer_cert_bits.data(), peer_cert_bits.size());
128
129
0
      while(!certs.end_of_data())
130
0
         m_peer_certs.push_back(X509_Certificate(certs));
131
0
      }
132
0
   }
133
134
secure_vector<uint8_t> Session::DER_encode() const
135
269
   {
136
269
   std::vector<uint8_t> peer_cert_bits;
137
269
   for(size_t i = 0; i != m_peer_certs.size(); ++i)
138
0
      peer_cert_bits += m_peer_certs[i].BER_encode();
139
140
269
   return DER_Encoder()
141
269
      .start_sequence()
142
269
         .encode(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION))
143
269
         .encode(static_cast<size_t>(std::chrono::system_clock::to_time_t(m_start_time)))
144
269
         .encode(static_cast<size_t>(m_version.major_version()))
145
269
         .encode(static_cast<size_t>(m_version.minor_version()))
146
269
         .encode(m_identifier, ASN1_Type::OctetString)
147
269
         .encode(m_session_ticket, ASN1_Type::OctetString)
148
269
         .encode(static_cast<size_t>(m_ciphersuite))
149
269
         .encode(static_cast<size_t>(/*old compression method*/0))
150
269
         .encode(static_cast<size_t>(m_connection_side))
151
269
         .encode(static_cast<size_t>(/*old fragment size*/0))
152
269
         .encode(m_extended_master_secret)
153
269
         .encode(m_encrypt_then_mac)
154
269
         .encode(m_master_secret, ASN1_Type::OctetString)
155
269
         .encode(peer_cert_bits, ASN1_Type::OctetString)
156
269
         .encode(ASN1_String(m_server_info.hostname(), ASN1_Type::Utf8String))
157
269
         .encode(ASN1_String(m_server_info.service(), ASN1_Type::Utf8String))
158
269
         .encode(static_cast<size_t>(m_server_info.port()))
159
269
         .encode(ASN1_String("", ASN1_Type::Utf8String)) // old srp identifier
160
269
         .encode(static_cast<size_t>(m_srtp_profile))
161
269
      .end_cons()
162
269
   .get_contents();
163
269
   }
164
165
std::string Session::PEM_encode() const
166
0
   {
167
0
   return PEM_Code::encode(this->DER_encode(), "TLS SESSION");
168
0
   }
169
170
std::chrono::seconds Session::session_age() const
171
0
   {
172
0
   return std::chrono::duration_cast<std::chrono::seconds>(
173
0
      std::chrono::system_clock::now() - m_start_time);
174
0
   }
175
176
namespace {
177
178
// The output length of the HMAC must be a valid keylength for the AEAD
179
const char* TLS_SESSION_CRYPT_HMAC = "HMAC(SHA-512-256)";
180
// SIV would be better, but we can't assume it is available
181
const char* TLS_SESSION_CRYPT_AEAD = "AES-256/GCM";
182
const char* TLS_SESSION_CRYPT_KEY_NAME = "BOTAN TLS SESSION KEY NAME";
183
const uint64_t TLS_SESSION_CRYPT_MAGIC = 0x068B5A9D396C0000;
184
const size_t TLS_SESSION_CRYPT_MAGIC_LEN = 8;
185
const size_t TLS_SESSION_CRYPT_KEY_NAME_LEN = 4;
186
const size_t TLS_SESSION_CRYPT_AEAD_NONCE_LEN = 12;
187
const size_t TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN = 16;
188
const size_t TLS_SESSION_CRYPT_AEAD_TAG_SIZE = 16;
189
190
const size_t TLS_SESSION_CRYPT_HDR_LEN =
191
   TLS_SESSION_CRYPT_MAGIC_LEN +
192
   TLS_SESSION_CRYPT_KEY_NAME_LEN +
193
   TLS_SESSION_CRYPT_AEAD_NONCE_LEN +
194
   TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN;
195
196
const size_t TLS_SESSION_CRYPT_OVERHEAD =
197
   TLS_SESSION_CRYPT_HDR_LEN + TLS_SESSION_CRYPT_AEAD_TAG_SIZE;
198
199
}
200
201
std::vector<uint8_t>
202
Session::encrypt(const SymmetricKey& key, RandomNumberGenerator& rng) const
203
269
   {
204
269
   auto hmac = MessageAuthenticationCode::create_or_throw(TLS_SESSION_CRYPT_HMAC);
205
269
   hmac->set_key(key);
206
207
   // First derive the "key name"
208
269
   std::vector<uint8_t> key_name(hmac->output_length());
209
269
   hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
210
269
   hmac->final(key_name.data());
211
269
   key_name.resize(TLS_SESSION_CRYPT_KEY_NAME_LEN);
212
213
269
   std::vector<uint8_t> aead_nonce;
214
269
   std::vector<uint8_t> key_seed;
215
216
269
   rng.random_vec(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
217
269
   rng.random_vec(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
218
219
269
   hmac->update(key_seed);
220
269
   const secure_vector<uint8_t> aead_key = hmac->final();
221
222
269
   secure_vector<uint8_t> bits = this->DER_encode();
223
224
   // create the header
225
269
   std::vector<uint8_t> buf;
226
269
   buf.reserve(TLS_SESSION_CRYPT_OVERHEAD + bits.size());
227
269
   buf.resize(TLS_SESSION_CRYPT_MAGIC_LEN);
228
269
   store_be(TLS_SESSION_CRYPT_MAGIC, &buf[0]);
229
269
   buf += key_name;
230
269
   buf += key_seed;
231
269
   buf += aead_nonce;
232
233
269
   std::unique_ptr<AEAD_Mode> aead = AEAD_Mode::create_or_throw(TLS_SESSION_CRYPT_AEAD, ENCRYPTION);
234
269
   BOTAN_ASSERT_NOMSG(aead->valid_nonce_length(TLS_SESSION_CRYPT_AEAD_NONCE_LEN));
235
269
   BOTAN_ASSERT_NOMSG(aead->tag_size() == TLS_SESSION_CRYPT_AEAD_TAG_SIZE);
236
269
   aead->set_key(aead_key);
237
269
   aead->set_associated_data_vec(buf);
238
269
   aead->start(aead_nonce);
239
269
   aead->finish(bits, 0);
240
241
   // append the ciphertext
242
269
   buf += bits;
243
269
   return buf;
244
269
   }
245
246
Session Session::decrypt(const uint8_t in[], size_t in_len, const SymmetricKey& key)
247
2.57k
   {
248
2.57k
   try
249
2.57k
      {
250
2.57k
      const size_t min_session_size = 48 + 4; // serious under-estimate
251
2.57k
      if(in_len < TLS_SESSION_CRYPT_OVERHEAD + min_session_size)
252
2.49k
         throw Decoding_Error("Encrypted session too short to be valid");
253
254
78
      const uint8_t* magic = &in[0];
255
78
      const uint8_t* key_name = magic + TLS_SESSION_CRYPT_MAGIC_LEN;
256
78
      const uint8_t* key_seed = key_name + TLS_SESSION_CRYPT_KEY_NAME_LEN;
257
78
      const uint8_t* aead_nonce = key_seed + TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN;
258
78
      const uint8_t* ctext = aead_nonce + TLS_SESSION_CRYPT_AEAD_NONCE_LEN;
259
78
      const size_t ctext_len = in_len - TLS_SESSION_CRYPT_HDR_LEN; // includes the tag
260
261
78
      if(load_be<uint64_t>(magic, 0) != TLS_SESSION_CRYPT_MAGIC)
262
77
         throw Decoding_Error("Missing expected magic numbers");
263
264
1
      auto hmac = MessageAuthenticationCode::create_or_throw(TLS_SESSION_CRYPT_HMAC);
265
1
      hmac->set_key(key);
266
267
      // First derive and check the "key name"
268
1
      std::vector<uint8_t> cmp_key_name(hmac->output_length());
269
1
      hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
270
1
      hmac->final(cmp_key_name.data());
271
272
1
      if(same_mem(cmp_key_name.data(), key_name, TLS_SESSION_CRYPT_KEY_NAME_LEN) == false)
273
1
         throw Decoding_Error("Wrong key name for encrypted session");
274
275
0
      hmac->update(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
276
0
      const secure_vector<uint8_t> aead_key = hmac->final();
277
278
0
      auto aead = AEAD_Mode::create_or_throw(TLS_SESSION_CRYPT_AEAD, DECRYPTION);
279
0
      aead->set_key(aead_key);
280
0
      aead->set_associated_data(in, TLS_SESSION_CRYPT_HDR_LEN);
281
0
      aead->start(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
282
0
      secure_vector<uint8_t> buf(ctext, ctext + ctext_len);
283
0
      aead->finish(buf, 0);
284
0
      return Session(buf.data(), buf.size());
285
0
      }
286
2.57k
   catch(std::exception& e)
287
2.57k
      {
288
2.57k
      throw Decoding_Error("Failed to decrypt serialized TLS session: " +
289
2.57k
                           std::string(e.what()));
290
2.57k
      }
291
2.57k
   }
292
293
}
294
295
}