• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 19012754211

02 Nov 2025 01:10PM UTC coverage: 90.677% (+0.006%) from 90.671%
19012754211

push

github

web-flow
Merge pull request #5137 from randombit/jack/clang-tidy-includes

Remove various unused includes flagged by clang-tidy misc-include-cleaner

100457 of 110786 relevant lines covered (90.68%)

12189873.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.09
/src/lib/tls/tls12/tls_record.cpp
1
/*
2
* TLS Record Handling
3
* (C) 2012,2013,2014,2015,2016,2019 Jack Lloyd
4
*     2016 Juraj Somorovsky
5
*     2016 Matthias Gierlings
6
*
7
* Botan is released under the Simplified BSD License (see license.txt)
8
*/
9

10
#include <botan/internal/tls_record.h>
11

12
#include <botan/rng.h>
13
#include <botan/tls_ciphersuite.h>
14
#include <botan/tls_exceptn.h>
15
#include <botan/internal/fmt.h>
16
#include <botan/internal/loadstor.h>
17
#include <botan/internal/tls_seq_numbers.h>
18
#include <botan/internal/tls_session_key.h>
19

20
#if defined(BOTAN_HAS_TLS_CBC)
21
   #include <botan/internal/tls_cbc.h>
22
#endif
23

24
#if defined(BOTAN_HAS_TLS_NULL)
25
   #include <botan/internal/tls_null.h>
26
#endif
27

28
namespace Botan::TLS {
29

30
Connection_Cipher_State::Connection_Cipher_State(Protocol_Version version,
3,658✔
31
                                                 Connection_Side side,
32
                                                 bool our_side,
33
                                                 const Ciphersuite& suite,
34
                                                 const Session_Keys& keys,
35
                                                 bool uses_encrypt_then_mac) {
3,658✔
36
   // NOLINTBEGIN(*-prefer-member-initializer)
37
   m_nonce_format = suite.nonce_format();
3,658✔
38
   m_nonce_bytes_from_record = suite.nonce_bytes_from_record(version);
3,658✔
39
   m_nonce_bytes_from_handshake = suite.nonce_bytes_from_handshake();
3,658✔
40

41
   const secure_vector<uint8_t>& aead_key = keys.aead_key(side);
3,658✔
42
   m_nonce = keys.nonce(side);
3,658✔
43
   // NOLINTEND(*-prefer-member-initializer)
44

45
   BOTAN_ASSERT_NOMSG(m_nonce.size() == m_nonce_bytes_from_handshake);
3,658✔
46

47
   if(nonce_format() == Nonce_Format::CBC_MODE) {
3,658✔
48
#if defined(BOTAN_HAS_TLS_CBC)
49
      // legacy CBC+HMAC mode
50
      auto mac = MessageAuthenticationCode::create_or_throw(fmt("HMAC({})", suite.mac_algo()));
1,120✔
51
      auto cipher = BlockCipher::create_or_throw(suite.cipher_algo());
560✔
52

53
      if(our_side) {
560✔
54
         m_aead = std::make_unique<TLS_CBC_HMAC_AEAD_Encryption>(std::move(cipher),
283✔
55
                                                                 std::move(mac),
56
                                                                 suite.cipher_keylen(),
283✔
57
                                                                 suite.mac_keylen(),
566✔
58
                                                                 version,
59
                                                                 uses_encrypt_then_mac);
283✔
60
      } else {
61
         m_aead = std::make_unique<TLS_CBC_HMAC_AEAD_Decryption>(std::move(cipher),
277✔
62
                                                                 std::move(mac),
63
                                                                 suite.cipher_keylen(),
277✔
64
                                                                 suite.mac_keylen(),
554✔
65
                                                                 version,
66
                                                                 uses_encrypt_then_mac);
277✔
67
      }
68

69
#else
70
      BOTAN_UNUSED(uses_encrypt_then_mac);
71
      throw Internal_Error("Negotiated disabled TLS CBC+HMAC ciphersuite");
72
#endif
73
   } else if(nonce_format() == Nonce_Format::NULL_CIPHER) {
3,658✔
74
#if defined(BOTAN_HAS_TLS_NULL)
75
      auto mac = MessageAuthenticationCode::create_or_throw(fmt("HMAC({})", suite.mac_algo()));
32✔
76

77
      if(our_side) {
16✔
78
         m_aead = std::make_unique<TLS_NULL_HMAC_AEAD_Encryption>(std::move(mac), suite.mac_keylen());
8✔
79
      } else {
80
         m_aead = std::make_unique<TLS_NULL_HMAC_AEAD_Decryption>(std::move(mac), suite.mac_keylen());
8✔
81
      }
82
#else
83
      throw Internal_Error("Negotiated disabled TLS NULL ciphersuite");
84
#endif
85
   } else {
16✔
86
      m_aead =
3,082✔
87
         AEAD_Mode::create_or_throw(suite.cipher_algo(), our_side ? Cipher_Dir::Encryption : Cipher_Dir::Decryption);
6,164✔
88
   }
89

90
   m_aead->set_key(aead_key);
3,658✔
91
}
3,658✔
92

93
std::vector<uint8_t> Connection_Cipher_State::aead_nonce(uint64_t seq, RandomNumberGenerator& rng) {
6,291✔
94
   switch(m_nonce_format) {
6,291✔
95
      case Nonce_Format::NULL_CIPHER: {
33✔
96
         return std::vector<uint8_t>{};
33✔
97
      }
98
      case Nonce_Format::CBC_MODE: {
1,023✔
99
         if(!m_nonce.empty()) {
1,023✔
100
            std::vector<uint8_t> nonce;
283✔
101
            nonce.swap(m_nonce);
283✔
102
            return nonce;
283✔
103
         }
283✔
104
         std::vector<uint8_t> nonce(nonce_bytes_from_record());
740✔
105
         rng.randomize(nonce.data(), nonce.size());
740✔
106
         return nonce;
740✔
107
      }
740✔
108
      case Nonce_Format::AEAD_XOR_12: {
3,648✔
109
         std::vector<uint8_t> nonce(12);
3,648✔
110
         store_be(seq, nonce.data() + 4);
3,648✔
111
         xor_buf(nonce, m_nonce.data(), m_nonce.size());
3,648✔
112
         return nonce;
3,648✔
113
      }
3,648✔
114
      case Nonce_Format::AEAD_IMPLICIT_4: {
1,587✔
115
         BOTAN_ASSERT_NOMSG(m_nonce.size() == 4);
1,587✔
116
         std::vector<uint8_t> nonce(12);
1,587✔
117
         copy_mem(&nonce[0], m_nonce.data(), 4);  // NOLINT(*container-data-pointer)
1,587✔
118
         store_be(seq, &nonce[nonce_bytes_from_handshake()]);
1,587✔
119
         return nonce;
1,587✔
120
      }
1,587✔
121
   }
122

123
   throw Invalid_State("Unknown nonce format specified");
×
124
}
125

126
std::vector<uint8_t> Connection_Cipher_State::aead_nonce(const uint8_t record[], size_t record_len, uint64_t seq) {
12,113✔
127
   switch(m_nonce_format) {
12,113✔
128
      case Nonce_Format::NULL_CIPHER: {
33✔
129
         return std::vector<uint8_t>{};
33✔
130
      }
131
      case Nonce_Format::CBC_MODE: {
1,046✔
132
         if(nonce_bytes_from_record() == 0 && !m_nonce.empty()) {
1,046✔
133
            std::vector<uint8_t> nonce;
×
134
            nonce.swap(m_nonce);
×
135
            return nonce;
×
136
         }
×
137
         if(record_len < nonce_bytes_from_record()) {
1,046✔
138
            throw Decoding_Error("Invalid CBC packet too short to be valid");
×
139
         }
140
         std::vector<uint8_t> nonce(record, record + nonce_bytes_from_record());
1,046✔
141
         return nonce;
1,046✔
142
      }
1,046✔
143
      case Nonce_Format::AEAD_XOR_12: {
9,335✔
144
         std::vector<uint8_t> nonce(12);
9,335✔
145
         store_be(seq, nonce.data() + 4);
9,335✔
146
         xor_buf(nonce, m_nonce.data(), m_nonce.size());
9,335✔
147
         return nonce;
9,335✔
148
      }
9,335✔
149
      case Nonce_Format::AEAD_IMPLICIT_4: {
1,699✔
150
         BOTAN_ASSERT_NOMSG(m_nonce.size() == 4);
1,699✔
151
         if(record_len < nonce_bytes_from_record()) {
1,699✔
152
            throw Decoding_Error("Invalid AEAD packet too short to be valid");
×
153
         }
154
         std::vector<uint8_t> nonce(12);
1,699✔
155
         copy_mem(&nonce[0], m_nonce.data(), 4);  // NOLINT(*container-data-pointer)
1,699✔
156
         copy_mem(&nonce[nonce_bytes_from_handshake()], record, nonce_bytes_from_record());
1,699✔
157
         return nonce;
1,699✔
158
      }
1,699✔
159
   }
160

161
   throw Invalid_State("Unknown nonce format specified");
×
162
}
163

164
std::vector<uint8_t> Connection_Cipher_State::format_ad(uint64_t msg_sequence,
18,400✔
165
                                                        Record_Type msg_type,
166
                                                        Protocol_Version version,
167
                                                        uint16_t msg_length) {
168
   std::vector<uint8_t> ad(13);
18,400✔
169

170
   store_be(msg_sequence, &ad[0]);  // NOLINT(*container-data-pointer)
18,400✔
171
   ad[8] = static_cast<uint8_t>(msg_type);
18,400✔
172
   ad[9] = version.major_version();
18,400✔
173
   ad[10] = version.minor_version();
18,400✔
174
   ad[11] = get_byte<0>(msg_length);
18,400✔
175
   ad[12] = get_byte<1>(msg_length);
18,400✔
176

177
   return ad;
18,400✔
178
}
179

180
namespace {
181

182
inline void append_u16_len(secure_vector<uint8_t>& output, size_t len_field) {
19,114✔
183
   const uint16_t len16 = static_cast<uint16_t>(len_field);
19,114✔
184
   BOTAN_ASSERT_EQUAL(len_field, len16, "No truncation");
19,114✔
185
   output.push_back(get_byte<0>(len16));
19,114✔
186
   output.push_back(get_byte<1>(len16));
19,114✔
187
}
19,114✔
188

189
void write_record_header(secure_vector<uint8_t>& output,
19,114✔
190
                         Record_Type record_type,
191
                         Protocol_Version version,
192
                         uint64_t record_sequence) {
193
   output.clear();
19,114✔
194

195
   output.push_back(static_cast<uint8_t>(record_type));
19,114✔
196
   output.push_back(version.major_version());
19,114✔
197
   output.push_back(version.minor_version());
19,114✔
198

199
   if(version.is_datagram_protocol()) {
19,114✔
200
      for(size_t i = 0; i != 8; ++i) {
65,529✔
201
         output.push_back(get_byte_var(i, record_sequence));
58,248✔
202
      }
203
   }
204
}
19,114✔
205

206
}  // namespace
207

208
void write_unencrypted_record(secure_vector<uint8_t>& output,
12,823✔
209
                              Record_Type record_type,
210
                              Protocol_Version version,
211
                              uint64_t record_sequence,
212
                              const uint8_t* message,
213
                              size_t message_len) {
214
   if(record_type == Record_Type::ApplicationData) {
12,823✔
215
      throw Internal_Error("Writing an unencrypted TLS application data record");
×
216
   }
217
   write_record_header(output, record_type, version, record_sequence);
12,823✔
218
   append_u16_len(output, message_len);
12,823✔
219
   output.insert(output.end(), message, message + message_len);
12,823✔
220
}
12,823✔
221

222
void write_record(secure_vector<uint8_t>& output,
6,291✔
223
                  Record_Type record_type,
224
                  Protocol_Version version,
225
                  uint64_t record_sequence,
226
                  const uint8_t* message,
227
                  size_t message_len,
228
                  Connection_Cipher_State& cs,
229
                  RandomNumberGenerator& rng) {
230
   write_record_header(output, record_type, version, record_sequence);
6,291✔
231

232
   AEAD_Mode& aead = cs.aead();
6,291✔
233
   std::vector<uint8_t> aad = cs.format_ad(record_sequence, record_type, version, static_cast<uint16_t>(message_len));
6,291✔
234

235
   const size_t ctext_size = aead.output_length(message_len);
6,291✔
236

237
   const size_t rec_size = ctext_size + cs.nonce_bytes_from_record();
6,291✔
238

239
   aead.set_associated_data(aad);
6,291✔
240

241
   const std::vector<uint8_t> nonce = cs.aead_nonce(record_sequence, rng);
6,291✔
242

243
   append_u16_len(output, rec_size);
6,291✔
244

245
   if(cs.nonce_bytes_from_record() > 0) {
6,291✔
246
      if(cs.nonce_format() == Nonce_Format::CBC_MODE) {
2,610✔
247
         output += nonce;
1,023✔
248
      } else {
249
         output += std::make_pair(&nonce[cs.nonce_bytes_from_handshake()], cs.nonce_bytes_from_record());
1,587✔
250
      }
251
   }
252

253
   const size_t header_size = output.size();
6,291✔
254
   output += std::make_pair(message, message_len);
6,291✔
255

256
   aead.start(nonce);
6,291✔
257
   aead.finish(output, header_size);
6,291✔
258

259
   BOTAN_ASSERT(output.size() < MAX_CIPHERTEXT_SIZE, "Produced ciphertext larger than protocol allows");
6,291✔
260
}
12,582✔
261

262
namespace {
263

264
size_t fill_buffer_to(
767,914✔
265
   secure_vector<uint8_t>& readbuf, const uint8_t*& input, size_t& input_size, size_t& input_consumed, size_t desired) {
266
   if(readbuf.size() >= desired) {
767,914✔
267
      return 0;  // already have it
268
   }
269

270
   const size_t taken = std::min(input_size, desired - readbuf.size());
767,913✔
271

272
   readbuf.insert(readbuf.end(), input, input + taken);
767,913✔
273
   input_consumed += taken;
767,913✔
274
   input_size -= taken;
767,913✔
275
   input += taken;
767,913✔
276

277
   return (desired - readbuf.size());  // how many bytes do we still need?
767,913✔
278
}
279

280
void decrypt_record(secure_vector<uint8_t>& output,
12,113✔
281
                    uint8_t record_contents[],
282
                    size_t record_len,
283
                    uint64_t record_sequence,
284
                    Protocol_Version record_version,
285
                    Record_Type record_type,
286
                    Connection_Cipher_State& cs) {
287
   AEAD_Mode& aead = cs.aead();
12,113✔
288

289
   const std::vector<uint8_t> nonce = cs.aead_nonce(record_contents, record_len, record_sequence);
12,113✔
290
   const uint8_t* msg = &record_contents[cs.nonce_bytes_from_record()];
12,113✔
291
   const size_t msg_length = record_len - cs.nonce_bytes_from_record();
12,113✔
292

293
   /*
294
   * This early rejection is based just on public information (length of the
295
   * encrypted packet) and so does not leak any information. We used to use
296
   * decode_error here which really is more appropriate, but that confuses some
297
   * tools which are attempting automated detection of padding oracles,
298
   * including older versions of TLS-Attacker.
299
   */
300
   if(msg_length < aead.minimum_final_size()) {
12,113✔
301
      throw TLS_Exception(Alert::BadRecordMac, "AEAD packet is shorter than the tag");
4✔
302
   }
303

304
   const size_t ptext_size = aead.output_length(msg_length);
12,109✔
305

306
   aead.set_associated_data(
12,109✔
307
      cs.format_ad(record_sequence, record_type, record_version, static_cast<uint16_t>(ptext_size)));
12,176✔
308

309
   aead.start(nonce);
12,109✔
310

311
   output.assign(msg, msg + msg_length);
12,109✔
312
   aead.finish(output, 0);
12,109✔
313
}
12,046✔
314

315
Record_Header read_tls_record(secure_vector<uint8_t>& readbuf,
114,094✔
316
                              const uint8_t input[],
317
                              size_t input_len,
318
                              size_t& consumed,
319
                              secure_vector<uint8_t>& recbuf,
320
                              Connection_Sequence_Numbers* sequence_numbers,
321
                              const get_cipherstate_fn& get_cipherstate) {
322
   if(readbuf.size() < TLS_HEADER_SIZE) {
114,094✔
323
      // header incomplete
324
      if(size_t needed = fill_buffer_to(readbuf, input, input_len, consumed, TLS_HEADER_SIZE)) {
114,094✔
325
         return Record_Header(needed);
3✔
326
      }
327

328
      BOTAN_ASSERT_EQUAL(readbuf.size(), TLS_HEADER_SIZE, "Have an entire header");
114,091✔
329
   }
330

331
   /*
332
   Verify that the record type and record version are within some expected
333
   range, so we can quickly reject totally invalid packets.
334

335
   The version check is a little hacky but given how TLS 1.3 versioning works
336
   this is probably safe
337

338
   - The first byte is the record version which in TLS 1.2 is always in [20..23)
339
   - The second byte is the TLS major version which is effectively fossilized at 3
340
   - The third byte is the TLS minor version which (due to TLS 1.3 versioning changes)
341
     will never be more than 3 (signifying TLS 1.2)
342
   */
343
   const bool bad_record_type = readbuf[0] < 20 || readbuf[0] > 23;
114,091✔
344
   const bool bad_record_version = readbuf[1] != 3 || readbuf[2] >= 4;
114,091✔
345

346
   if(bad_record_type || bad_record_version) {
114,091✔
347
      // We know we read up to at least the 5 byte TLS header
348
      const std::string first5 = std::string(reinterpret_cast<const char*>(readbuf.data()), 5);
629✔
349

350
      if(first5 == "GET /" || first5 == "PUT /" || first5 == "POST " || first5 == "HEAD ") {
629✔
351
         throw TLS_Exception(Alert::ProtocolVersion, "Client sent plaintext HTTP request instead of TLS handshake");
2✔
352
      }
353

354
      if(first5 == "CONNE") {
627✔
355
         throw TLS_Exception(Alert::ProtocolVersion,
1✔
356
                             "Client sent plaintext HTTP proxy CONNECT request instead of TLS handshake");
1✔
357
      }
358

359
      if(bad_record_type) {
626✔
360
         // RFC 5246 Section 6.
361
         //   If a TLS implementation receives an unexpected record type, it MUST
362
         //   send an unexpected_message alert.
363
         throw TLS_Exception(Alert::UnexpectedMessage, "TLS record type had unexpected value");
33✔
364
      }
365
      throw TLS_Exception(Alert::ProtocolVersion, "TLS record version had unexpected value");
593✔
366
   }
629✔
367

368
   const Protocol_Version version(readbuf[1], readbuf[2]);
113,462✔
369

370
   if(version.is_datagram_protocol()) {
113,462✔
371
      throw TLS_Exception(Alert::ProtocolVersion, "Expected TLS but got a record with DTLS version");
×
372
   }
373

374
   const size_t record_size = make_uint16(readbuf[TLS_HEADER_SIZE - 2], readbuf[TLS_HEADER_SIZE - 1]);
113,462✔
375

376
   if(record_size > MAX_CIPHERTEXT_SIZE) {
113,462✔
377
      throw TLS_Exception(Alert::RecordOverflow, "Received a record that exceeds maximum size");
2✔
378
   }
379

380
   if(record_size == 0) {
113,460✔
381
      throw TLS_Exception(Alert::DecodeError, "Received a completely empty record");
10✔
382
   }
383

384
   if(size_t needed = fill_buffer_to(readbuf, input, input_len, consumed, TLS_HEADER_SIZE + record_size)) {
113,450✔
385
      return Record_Header(needed);
17✔
386
   }
387

388
   BOTAN_ASSERT_EQUAL(static_cast<size_t>(TLS_HEADER_SIZE) + record_size, readbuf.size(), "Have the full record");
113,433✔
389

390
   const Record_Type type = static_cast<Record_Type>(readbuf[0]);
113,433✔
391

392
   uint16_t epoch = 0;
113,433✔
393

394
   uint64_t sequence = 0;
113,433✔
395
   if(sequence_numbers != nullptr) {
113,433✔
396
      sequence = sequence_numbers->next_read_sequence();
112,833✔
397
      epoch = sequence_numbers->current_read_epoch();
112,833✔
398
   } else {
399
      // server initial handshake case
400
      epoch = 0;
401
   }
402

403
   if(epoch == 0) {
112,833✔
404
      // Unencrypted initial handshake
405
      recbuf.assign(readbuf.begin() + TLS_HEADER_SIZE, readbuf.begin() + TLS_HEADER_SIZE + record_size);
105,581✔
406
      readbuf.clear();
105,581✔
407
      return Record_Header(sequence, version, type);
105,581✔
408
   }
409

410
   // Otherwise, decrypt, check MAC, return plaintext
411
   auto cs = get_cipherstate(epoch);
7,852✔
412

413
   BOTAN_ASSERT(cs, "Have cipherstate for this epoch");
7,852✔
414

415
   decrypt_record(recbuf, &readbuf[TLS_HEADER_SIZE], record_size, sequence, version, type, *cs);
7,852✔
416

417
   if(sequence_numbers != nullptr) {
7,808✔
418
      sequence_numbers->read_accept(sequence);
7,808✔
419
   }
420

421
   readbuf.clear();
7,808✔
422
   return Record_Header(sequence, version, type);
7,808✔
423
}
7,808✔
424

425
Record_Header read_dtls_record(secure_vector<uint8_t>& readbuf,
270,197✔
426
                               const uint8_t input[],
427
                               size_t input_len,
428
                               size_t& consumed,
429
                               secure_vector<uint8_t>& recbuf,
430
                               Connection_Sequence_Numbers* sequence_numbers,
431
                               const get_cipherstate_fn& get_cipherstate,
432
                               bool allow_epoch0_restart) {
433
   if(readbuf.size() < DTLS_HEADER_SIZE) {
270,197✔
434
      // header incomplete
435
      if(fill_buffer_to(readbuf, input, input_len, consumed, DTLS_HEADER_SIZE) != 0) {
270,197✔
436
         readbuf.clear();
10✔
437
         return Record_Header(0);
10✔
438
      }
439

440
      BOTAN_ASSERT_EQUAL(readbuf.size(), DTLS_HEADER_SIZE, "Have an entire header");
270,187✔
441
   }
442

443
   const Protocol_Version version(readbuf[1], readbuf[2]);
270,187✔
444

445
   if(version.is_datagram_protocol() == false) {
270,187✔
446
      readbuf.clear();
13✔
447
      return Record_Header(0);
13✔
448
   }
449

450
   const size_t record_size = make_uint16(readbuf[DTLS_HEADER_SIZE - 2], readbuf[DTLS_HEADER_SIZE - 1]);
270,174✔
451

452
   if(record_size > MAX_CIPHERTEXT_SIZE) {
270,174✔
453
      // Too large to be valid, ignore it
454
      readbuf.clear();
1✔
455
      return Record_Header(0);
1✔
456
   }
457

458
   if(fill_buffer_to(readbuf, input, input_len, consumed, DTLS_HEADER_SIZE + record_size) != 0) {
270,173✔
459
      // Truncated packet?
460
      readbuf.clear();
2✔
461
      return Record_Header(0);
2✔
462
   }
463

464
   BOTAN_ASSERT_EQUAL(static_cast<size_t>(DTLS_HEADER_SIZE) + record_size, readbuf.size(), "Have the full record");
270,171✔
465

466
   const Record_Type type = static_cast<Record_Type>(readbuf[0]);
270,171✔
467

468
   const uint64_t sequence = load_be<uint64_t>(&readbuf[3], 0);
270,171✔
469
   const uint16_t epoch = (sequence >> 48);
270,171✔
470

471
   const bool already_seen = sequence_numbers != nullptr && sequence_numbers->already_seen(sequence);
270,171✔
472

473
   if(already_seen && !(epoch == 0 && allow_epoch0_restart)) {
417✔
474
      readbuf.clear();
416✔
475
      return Record_Header(0);
416✔
476
   }
477

478
   if(epoch == 0) {
269,754✔
479
      // Unencrypted initial handshake
480
      recbuf.assign(readbuf.begin() + DTLS_HEADER_SIZE, readbuf.begin() + DTLS_HEADER_SIZE + record_size);
265,478✔
481
      readbuf.clear();
265,478✔
482
      if(sequence_numbers != nullptr) {
265,478✔
483
         sequence_numbers->read_accept(sequence);
265,077✔
484
      }
485
      return Record_Header(sequence, version, type);
265,478✔
486
   }
487

488
   try {
4,277✔
489
      // Otherwise, decrypt, check MAC, return plaintext
490
      auto cs = get_cipherstate(epoch);
4,277✔
491

492
      BOTAN_ASSERT(cs, "Have cipherstate for this epoch");
4,261✔
493

494
      decrypt_record(recbuf, &readbuf[DTLS_HEADER_SIZE], record_size, sequence, version, type, *cs);
4,261✔
495
   } catch(std::exception&) {
39✔
496
      readbuf.clear();
39✔
497
      return Record_Header(0);
39✔
498
   }
39✔
499

500
   if(sequence_numbers != nullptr) {
4,238✔
501
      sequence_numbers->read_accept(sequence);
4,238✔
502
   }
503

504
   readbuf.clear();
4,238✔
505
   return Record_Header(sequence, version, type);
4,238✔
506
}
507

508
}  // namespace
509

510
Record_Header read_record(bool is_datagram,
384,291✔
511
                          secure_vector<uint8_t>& readbuf,
512
                          const uint8_t input[],
513
                          size_t input_len,
514
                          size_t& consumed,
515
                          secure_vector<uint8_t>& recbuf,
516
                          Connection_Sequence_Numbers* sequence_numbers,
517
                          const get_cipherstate_fn& get_cipherstate,
518
                          bool allow_epoch0_restart) {
519
   if(is_datagram) {
384,291✔
520
      return read_dtls_record(
270,197✔
521
         readbuf, input, input_len, consumed, recbuf, sequence_numbers, get_cipherstate, allow_epoch0_restart);
270,197✔
522
   } else {
523
      return read_tls_record(readbuf, input, input_len, consumed, recbuf, sequence_numbers, get_cipherstate);
114,094✔
524
   }
525
}
526

527
}  // namespace Botan::TLS
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc