Coverage Report

Created: 2023-01-25 06:35

/src/botan/src/lib/tls/tls13/tls_record_layer_13.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* TLS record layer implementation for TLS 1.3
3
* (C) 2022 Jack Lloyd
4
*     2022 Hannes Rantzsch, René Meusel - neXenio GmbH
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
9
#include <botan/tls_version.h>
10
#include <botan/tls_alert.h>
11
#include <botan/tls_exceptn.h>
12
13
#include <botan/internal/tls_record_layer_13.h>
14
#include <botan/internal/tls_cipher_state.h>
15
#include <botan/internal/tls_reader.h>
16
17
namespace Botan::TLS {
18
19
namespace {
20
21
template <typename IteratorT>
22
bool verify_change_cipher_spec(const IteratorT data, const size_t size)
23
0
   {
24
   // RFC 8446 5.
25
   //    An implementation may receive an unencrypted record of type
26
   //    change_cipher_spec consisting of the single byte value 0x01
27
   //    at any time [...]. An implementation which receives any other
28
   //    change_cipher_spec value or which receives a protected
29
   //    change_cipher_spec record MUST abort the handshake [...].
30
0
   const size_t expected_fragment_length = 1;
31
0
   const uint8_t expected_fragment_byte = 0x01;
32
0
   return (size == expected_fragment_length && *data == expected_fragment_byte);
33
0
   }
34
35
Record_Type read_record_type(const uint8_t type_byte)
36
0
   {
37
   // RFC 8446 5.
38
   //    If a TLS implementation receives an unexpected record type,
39
   //    it MUST terminate the connection with an "unexpected_message" alert.
40
0
   if(type_byte != Record_Type::APPLICATION_DATA
41
0
         && type_byte != Record_Type::HANDSHAKE
42
0
         && type_byte != Record_Type::ALERT
43
0
         && type_byte != Record_Type::CHANGE_CIPHER_SPEC)
44
0
      {
45
0
      throw TLS_Exception(Alert::UNEXPECTED_MESSAGE, "TLS record type had unexpected value");
46
0
      }
47
48
0
   return static_cast<Record_Type>(type_byte);
49
0
   }
50
51
/**
52
 * RFC 8446 5.1 `TLSPlaintext` without the `fragment` payload data
53
 */
54
struct TLSPlaintext_Header
55
   {
56
   TLSPlaintext_Header(std::vector<uint8_t> hdr, const bool check_tls13_version)
57
0
      {
58
0
      type            = read_record_type(hdr[0]);
59
0
      legacy_version  = Protocol_Version(make_uint16(hdr[1], hdr[2]));
60
0
      fragment_length = make_uint16(hdr[3], hdr[4]);
61
0
      serialized      = std::move(hdr);
62
63
      // If no full version check is requested, we just verify the practically
64
      // ossified major version number.
65
0
      if(legacy_version.major_version() != 0x03)
66
0
         { throw TLS_Exception(Alert::ILLEGAL_PARAMETER, "Received unexpected record version"); }
67
68
      // RFC 8446 5.1
69
      //    legacy_record_version:  MUST be set to 0x0303 for all records
70
      //                            generated by a TLS 1.3 implementation
71
0
      if(check_tls13_version && legacy_version.version_code() != 0x0303)
72
0
         { throw TLS_Exception(Alert::ILLEGAL_PARAMETER, "Received unexpected record version"); }
73
74
      // RFC 8446 5.1
75
      //    Implementations MUST NOT send zero-length fragments of Handshake
76
      //    types, even if those fragments contain padding.
77
      //
78
      //    Zero-length fragments of Application Data MAY be sent, as they are
79
      //    potentially useful as a traffic analysis countermeasure.
80
0
      if(fragment_length == 0 && type != Record_Type::APPLICATION_DATA)
81
0
         { throw TLS_Exception(Alert::DECODE_ERROR, "empty record received"); }
82
83
0
      if(type == Record_Type::APPLICATION_DATA)
84
0
         {
85
         // RFC 8446 5.2
86
         //    The length [...] is the sum of the lengths of the content and the
87
         //    padding, plus one for the inner content type, plus any expansion
88
         //    added by the AEAD algorithm. The length MUST NOT exceed 2^14 + 256 bytes.
89
         //
90
         // Note: Limits imposed by a "record_size_limit" extension do not come
91
         //       into play here, as those limits are on the plaintext _not_ the
92
         //       encrypted data. Constricted devices must be able to deal with
93
         //       data overhead inflicted by the AEAD.
94
0
         if(fragment_length > MAX_CIPHERTEXT_SIZE_TLS13)
95
0
            { throw TLS_Exception(Alert::RECORD_OVERFLOW, "Received an encrypted record that exceeds maximum size"); }
96
0
         }
97
0
      else
98
0
         {
99
         // RFC 8446 5.1
100
         //    The length MUST NOT exceed 2^14 bytes.  An endpoint that receives a record that
101
         //    exceeds this length MUST terminate the connection with a "record_overflow" alert.
102
         //
103
         // RFC 8449 4.
104
         //    When the "record_size_limit" extension is negotiated, an endpoint
105
         //    MUST NOT generate a protected record with plaintext that is larger
106
         //    than the RecordSizeLimit value it receives from its peer.
107
         // -> Unprotected messages are not subject to this limit. <-
108
0
         if(fragment_length > MAX_PLAINTEXT_SIZE)
109
0
            { throw TLS_Exception(Alert::RECORD_OVERFLOW, "Received a record that exceeds maximum size"); }
110
0
         }
111
0
      }
112
113
   TLSPlaintext_Header(const Record_Type record_type,
114
                       const size_t frgmnt_length,
115
                       const bool use_compatibility_version)
116
      : type(record_type)
117
      , legacy_version(use_compatibility_version ? 0x0301 : 0x0303)  // RFC 8446 5.1
118
      , fragment_length(static_cast<uint16_t>(frgmnt_length))
119
      , serialized(
120
      {
121
      static_cast<uint8_t>(type),
122
      legacy_version.major_version(), legacy_version.minor_version(),
123
      get_byte<0>(fragment_length), get_byte<1>(fragment_length),
124
      })
125
0
      {}
126
127
   Record_Type          type;
128
   Protocol_Version     legacy_version;
129
   uint16_t             fragment_length;
130
   std::vector<uint8_t> serialized;
131
   };
132
133
}  // namespace
134
135
Record_Layer::Record_Layer(Connection_Side side)
136
   : m_side(side)
137
   , m_outgoing_record_size_limit(MAX_PLAINTEXT_SIZE + 1 /* content type byte */)
138
   , m_incoming_record_size_limit(MAX_PLAINTEXT_SIZE + 1 /* content type byte */)
139
140
   // RFC 8446 5.1
141
   //    legacy_record_version: MUST be set to 0x0303 for all records
142
   //       generated by a TLS 1.3 implementation other than an initial
143
   //       ClientHello [...], where it MAY also be 0x0301 for compatibility
144
   //       purposes.
145
   //
146
   // Additionally, older peers might send other values while requesting a
147
   // protocol downgrade. I.e. we need to be able to tolerate/emit legacy
148
   // values until we negotiated a TLS 1.3 compliant connection.
149
   //
150
   // As a client: we may initially emit the compatibility version and
151
   //              accept a wider range of incoming legacy record versions.
152
   // As a server: we start with emitting the specified legacy version of 0x0303
153
   //              but must also allow a wider range of incoming legacy values.
154
   //
155
   // Once TLS 1.3 is negotiateed, the implementations will disable these
156
   // compatibility modes accordingly or a protocol downgrade will transfer
157
   // the marshalling responsibility to our TLS 1.2 implementation.
158
   , m_sending_compat_mode(m_side == Connection_Side::CLIENT)
159
0
   , m_receiving_compat_mode(true) {}
160
161
162
void Record_Layer::copy_data(const uint8_t data[], size_t size)
163
0
   {
164
0
   m_read_buffer.insert(m_read_buffer.end(), data, data+size);
165
0
   }
166
167
void Record_Layer::copy_data(const std::vector<uint8_t>& data_from_peer)
168
0
   {
169
0
   copy_data(data_from_peer.data(), data_from_peer.size());
170
0
   }
171
172
std::vector<uint8_t> Record_Layer::prepare_records(const Record_Type type,
173
      const std::vector<uint8_t>& data,
174
      Cipher_State* cipher_state)
175
0
   {
176
   // RFC 8446 5.
177
   //    Note that [change_cipher_spec records] may appear at a point at the
178
   //    handshake where the implementation is expecting protected records.
179
   //
180
   // RFC 8446 5.
181
   //    An implementation which receives [...] a protected change_cipher_spec
182
   //    record MUST abort the handshake [...].
183
   //
184
   // ... hence, CHANGE_CIPHER_SPEC is never protected, even if a usable cipher
185
   // state was passed to this method.
186
0
   const bool protect = cipher_state != nullptr && type != Record_Type::CHANGE_CIPHER_SPEC;
187
188
   // RFC 8446 5.1
189
0
   BOTAN_ASSERT(protect || type != Record_Type::APPLICATION_DATA,
190
0
                "Application Data records MUST NOT be written to the wire unprotected");
191
192
   // RFC 8446 5.1
193
   //   "MUST NOT sent zero-length fragments of Handshake types"
194
   //   "a record with an Alert type MUST contain exactly one message" [of non-zero length]
195
   //   "Zero-length fragments of Application Data MAY be sent"
196
0
   BOTAN_ASSERT(!data.empty() || type == Record_Type::APPLICATION_DATA,
197
0
                "zero-length fragments of types other than application data are not allowed");
198
199
0
   if(type == Record_Type::CHANGE_CIPHER_SPEC &&
200
0
         !verify_change_cipher_spec(data.cbegin(), data.size()))
201
0
      {
202
0
      throw Invalid_Argument("TLS 1.3 deprecated CHANGE_CIPHER_SPEC");
203
0
      }
204
205
0
   std::vector<uint8_t> output;
206
207
   // RFC 8446 5.2
208
   //    type:  The TLSPlaintext.type value containing the content type of the record.
209
0
   constexpr size_t content_type_tag_length = 1;
210
211
   // RFC 8449 4.
212
   //    When the "record_size_limit" extension is negotiated, an endpoint
213
   //    MUST NOT generate a protected record with plaintext that is larger
214
   //    than the RecordSizeLimit value it receives from its peer.
215
   //    Unprotected messages are not subject to this limit.
216
0
   const size_t max_plaintext_size = (protect)
217
0
      ? m_outgoing_record_size_limit - content_type_tag_length
218
0
      : static_cast<uint16_t>(MAX_PLAINTEXT_SIZE);
219
220
0
   const auto records = std::max((data.size() + max_plaintext_size - 1) / max_plaintext_size, size_t(1));
221
0
   auto output_length = records * TLS_HEADER_SIZE;
222
0
   if(protect)
223
0
      {
224
      // n-1 full records of size max_plaintext_size
225
0
      output_length +=
226
0
         (records - 1) * cipher_state->encrypt_output_length(max_plaintext_size + content_type_tag_length);
227
      // last record with size of remaining data
228
0
      output_length +=
229
0
         cipher_state->encrypt_output_length(data.size() - ((records-1) * max_plaintext_size) + content_type_tag_length);
230
0
      }
231
0
   else
232
0
      {
233
0
      output_length += data.size();
234
0
      }
235
0
   output.reserve(output_length);
236
237
0
   size_t pt_offset = 0;
238
0
   size_t to_process = data.size();
239
240
   // For protected records we need to write at least one encrypted fragment,
241
   // even if the plaintext size is zero. This happens only for Application
242
   // Data types.
243
0
   BOTAN_ASSERT_NOMSG(to_process != 0 || protect);
244
0
   do
245
0
      {
246
0
      const size_t pt_size = std::min<size_t>(to_process, max_plaintext_size);
247
0
      const size_t ct_size = (!protect) ? pt_size : cipher_state->encrypt_output_length(pt_size + content_type_tag_length);
248
0
      const auto   pt_type = (!protect) ? type : Record_Type::APPLICATION_DATA;
249
250
      // RFC 8446 5.1
251
      //    MUST be set to 0x0303 for all records generated by a TLS 1.3
252
      //    implementation other than an initial ClientHello [...], where
253
      //    it MAY also be 0x0301 for compatibility purposes.
254
0
      const auto record_header = TLSPlaintext_Header(pt_type, ct_size, m_sending_compat_mode).serialized;
255
256
0
      output.insert(output.end(), record_header.cbegin(), record_header.cend());
257
258
0
      if(protect)
259
0
         {
260
0
         secure_vector<uint8_t> fragment;
261
0
         fragment.reserve(ct_size);
262
263
         // assemble TLSInnerPlaintext structure
264
0
         fragment.insert(fragment.end(), data.cbegin() + pt_offset, data.cbegin() + pt_offset + pt_size);
265
0
         fragment.push_back(static_cast<uint8_t>(type));
266
         // TODO: zero padding could go here, see RFC 8446 5.4
267
268
0
         cipher_state->encrypt_record_fragment(record_header, fragment);
269
0
         BOTAN_ASSERT_NOMSG(fragment.size() == ct_size);
270
271
0
         output.insert(output.end(), fragment.cbegin(), fragment.cend());
272
0
         }
273
0
      else
274
0
         {
275
0
         output.insert(output.end(), data.cbegin() + pt_offset, data.cbegin() + pt_offset + pt_size);
276
0
         }
277
278
0
      pt_offset += pt_size;
279
0
      to_process -= pt_size;
280
0
      }
281
0
   while(to_process > 0);
282
283
0
   BOTAN_ASSERT_NOMSG(output.size() == output_length);
284
0
   return output;
285
0
   }
286
287
288
Record_Layer::ReadResult<Record> Record_Layer::next_record(Cipher_State* cipher_state)
289
0
   {
290
0
   if(m_read_buffer.size() < TLS_HEADER_SIZE)
291
0
      {
292
0
      return TLS_HEADER_SIZE - m_read_buffer.size();
293
0
      }
294
295
0
   const auto header_begin = m_read_buffer.cbegin();
296
0
   const auto header_end   = header_begin + TLS_HEADER_SIZE;
297
298
   // The first received record(s) are likely a client or server hello. To be able to
299
   // perform protocol downgrades we must be less vigorous with the record's
300
   // legacy version. Hence, `check_tls13_version` is `false` for the first record(s).
301
0
   TLSPlaintext_Header plaintext_header({header_begin, header_end}, !m_receiving_compat_mode);
302
303
   // After the key exchange phase of the handshake is completed and record protection is engaged,
304
   // cipher_state is set. At this point, only protected traffic (and CCS) is allowed.
305
   //
306
   // RFC 8446 2.
307
   //    -  Key Exchange: Establish shared keying material and select the
308
   //       cryptographic parameters.  Everything after this phase is
309
   //       encrypted.
310
   // RFC 8446 5.
311
   //    An implementation may receive an unencrypted [CCS] at any time
312
0
   if(cipher_state != nullptr
313
0
         && plaintext_header.type != APPLICATION_DATA
314
0
         && plaintext_header.type != CHANGE_CIPHER_SPEC
315
0
         && (!cipher_state->must_expect_unprotected_alert_traffic() || plaintext_header.type != ALERT))
316
0
      {
317
0
      throw TLS_Exception(Alert::UNEXPECTED_MESSAGE,
318
0
            "unprotected record received where protected traffic was expected");
319
0
      }
320
321
0
   if(m_read_buffer.size() < TLS_HEADER_SIZE + plaintext_header.fragment_length)
322
0
      {
323
0
      return TLS_HEADER_SIZE + plaintext_header.fragment_length - m_read_buffer.size();
324
0
      }
325
326
0
   const auto fragment_begin = header_end;
327
0
   const auto fragment_end   = fragment_begin + plaintext_header.fragment_length;
328
329
0
   if(plaintext_header.type == Record_Type::CHANGE_CIPHER_SPEC &&
330
0
         !verify_change_cipher_spec(fragment_begin, plaintext_header.fragment_length))
331
0
      {
332
0
      throw TLS_Exception(Alert::UNEXPECTED_MESSAGE,
333
0
                          "malformed change cipher spec record received");
334
0
      }
335
336
0
   Record record(plaintext_header.type, secure_vector<uint8_t>(fragment_begin, fragment_end));
337
0
   m_read_buffer.erase(header_begin, fragment_end);
338
339
0
   if(record.type == Record_Type::APPLICATION_DATA)
340
0
      {
341
0
      if(cipher_state == nullptr)
342
0
         {
343
         // This could also mean a misuse of the interface, i.e. failing to provide a valid
344
         // cipher_state to parse_records when receiving valid (encrypted) Application Data.
345
0
         throw TLS_Exception(Alert::UNEXPECTED_MESSAGE, "premature Application Data received");
346
0
         }
347
348
0
      if(record.fragment.size() < cipher_state->minimum_decryption_input_length())
349
0
         { throw TLS_Exception(Alert::BAD_RECORD_MAC, "incomplete record mac received"); }
350
351
0
      if(cipher_state->decrypt_output_length(record.fragment.size()) > m_incoming_record_size_limit)
352
0
         { throw TLS_Exception(Alert::RECORD_OVERFLOW, "Received an encrypted record that exceeds maximum plaintext size"); }
353
354
0
      record.seq_no = cipher_state->decrypt_record_fragment(plaintext_header.serialized, record.fragment);
355
356
      // Remove record padding (RFC 8446 5.4).
357
0
      const auto end_of_content = std::find_if(record.fragment.crbegin(), record.fragment.crend(), [](auto byte)
358
0
         {
359
0
         return byte != 0x00;
360
0
         });
361
362
0
      if(end_of_content == record.fragment.crend())
363
0
         { throw TLS_Exception(Alert::DECODE_ERROR, "No content type found in encrypted record"); }
364
365
      // hydrate the actual content type from TLSInnerPlaintext
366
0
      record.type = read_record_type(*end_of_content);
367
368
0
      if(record.type == Record_Type::CHANGE_CIPHER_SPEC)
369
0
         {
370
         // RFC 8446 5
371
         //  An implementation [...] which receives a protected change_cipher_spec record MUST
372
         //  abort the handshake with an "unexpected_message" alert.
373
0
         throw TLS_Exception(Alert::UNEXPECTED_MESSAGE, "protected change cipher spec received");
374
0
         }
375
376
      // erase content type and padding
377
0
      record.fragment.erase((end_of_content+1).base(), record.fragment.cend());
378
0
      }
379
380
0
   return record;
381
0
   }
382
383
384
void Record_Layer::set_record_size_limits(const uint16_t outgoing_limit,
385
                                          const uint16_t incoming_limit)
386
0
   {
387
0
   BOTAN_ARG_CHECK(outgoing_limit >= 64, "Invalid outgoing record size limit");
388
0
   BOTAN_ARG_CHECK(incoming_limit >= 64 && incoming_limit <= MAX_PLAINTEXT_SIZE + 1, "Invalid incoming record size limit");
389
390
   // RFC 8449 4.
391
   //    Even if a larger record size limit is provided by a peer, an endpoint
392
   //    MUST NOT send records larger than the protocol-defined limit, unless
393
   //    explicitly allowed by a future TLS version or extension.
394
0
   m_outgoing_record_size_limit = std::min(outgoing_limit, static_cast<uint16_t>(MAX_PLAINTEXT_SIZE + 1));
395
0
   m_incoming_record_size_limit = incoming_limit;
396
0
   }
397
398
}  // namespace Botan::TLS