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

randombit / botan / 5869163808

15 Aug 2023 04:04PM CUT coverage: 91.687% (-0.01%) from 91.698%
5869163808

Pull #3671

github

web-flow
Merge 291c56f0b into fc4b4271f
Pull Request #3671: eXtendable Output Functions as first-class citizen

78588 of 85713 relevant lines covered (91.69%)

12360400.08 hits per line

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

90.76
/src/lib/tls/tls12/tls_channel_impl_12.cpp
1
/*
2
* TLS Channels
3
* (C) 2011,2012,2014,2015,2016 Jack Lloyd
4
*     2016 Matthias Gierlings
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8

9
#include <botan/internal/tls_channel_impl_12.h>
10

11
#include <botan/kdf.h>
12
#include <botan/tls_messages.h>
13
#include <botan/tls_policy.h>
14
#include <botan/x509cert.h>
15
#include <botan/internal/loadstor.h>
16
#include <botan/internal/stl_util.h>
17
#include <botan/internal/tls_handshake_state.h>
18
#include <botan/internal/tls_record.h>
19
#include <botan/internal/tls_seq_numbers.h>
20

21
namespace Botan::TLS {
22

23
Channel_Impl_12::Channel_Impl_12(const std::shared_ptr<Callbacks>& callbacks,
5,131✔
24
                                 const std::shared_ptr<Session_Manager>& session_manager,
25
                                 const std::shared_ptr<RandomNumberGenerator>& rng,
26
                                 const std::shared_ptr<const Policy>& policy,
27
                                 bool is_server,
28
                                 bool is_datagram,
29
                                 size_t reserved_io_buffer_size) :
5,131✔
30
      m_is_server(is_server),
5,131✔
31
      m_is_datagram(is_datagram),
5,131✔
32
      m_callbacks(callbacks),
5,131✔
33
      m_session_manager(session_manager),
5,131✔
34
      m_policy(policy),
5,131✔
35
      m_rng(rng),
5,131✔
36
      m_has_been_closed(false) {
10,262✔
37
   BOTAN_ASSERT_NONNULL(m_callbacks);
5,131✔
38
   BOTAN_ASSERT_NONNULL(m_session_manager);
5,131✔
39
   BOTAN_ASSERT_NONNULL(m_rng);
5,131✔
40
   BOTAN_ASSERT_NONNULL(m_policy);
5,131✔
41

42
   /* epoch 0 is plaintext, thus null cipher state */
43
   m_write_cipher_states[0] = nullptr;
5,131✔
44
   m_read_cipher_states[0] = nullptr;
5,131✔
45

46
   m_writebuf.reserve(reserved_io_buffer_size);
5,131✔
47
   m_readbuf.reserve(reserved_io_buffer_size);
5,131✔
48
}
5,131✔
49

50
void Channel_Impl_12::reset_state() {
3,473✔
51
   m_active_state.reset();
3,473✔
52
   m_pending_state.reset();
3,473✔
53
   m_readbuf.clear();
3,473✔
54
   m_write_cipher_states.clear();
3,473✔
55
   m_read_cipher_states.clear();
3,473✔
56
}
3,473✔
57

58
void Channel_Impl_12::reset_active_association_state() {
1✔
59
   // This operation only makes sense for DTLS
60
   BOTAN_ASSERT_NOMSG(m_is_datagram);
1✔
61
   m_active_state.reset();
1✔
62
   m_read_cipher_states.clear();
1✔
63
   m_write_cipher_states.clear();
1✔
64

65
   m_write_cipher_states[0] = nullptr;
1✔
66
   m_read_cipher_states[0] = nullptr;
1✔
67

68
   if(m_sequence_numbers) {
1✔
69
      m_sequence_numbers->reset();
1✔
70
   }
71
}
1✔
72

73
Channel_Impl_12::~Channel_Impl_12() = default;
44,893✔
74

75
Connection_Sequence_Numbers& Channel_Impl_12::sequence_numbers() const {
41,154✔
76
   BOTAN_ASSERT(m_sequence_numbers, "Have a sequence numbers object");
13,711✔
77
   return *m_sequence_numbers;
41,156✔
78
}
79

80
std::shared_ptr<Connection_Cipher_State> Channel_Impl_12::read_cipher_state_epoch(uint16_t epoch) const {
12,265✔
81
   auto i = m_read_cipher_states.find(epoch);
12,265✔
82
   if(i == m_read_cipher_states.end()) {
12,265✔
83
      throw Internal_Error("TLS::Channel_Impl_12 No read cipherstate for epoch " + std::to_string(epoch));
32✔
84
   }
85
   return i->second;
12,249✔
86
}
87

88
std::shared_ptr<Connection_Cipher_State> Channel_Impl_12::write_cipher_state_epoch(uint16_t epoch) const {
18,528✔
89
   auto i = m_write_cipher_states.find(epoch);
18,528✔
90
   if(i == m_write_cipher_states.end()) {
18,528✔
91
      throw Internal_Error("TLS::Channel_Impl_12 No write cipherstate for epoch " + std::to_string(epoch));
×
92
   }
93
   return i->second;
18,528✔
94
}
95

96
std::vector<X509_Certificate> Channel_Impl_12::peer_cert_chain() const {
116✔
97
   if(auto active = active_state()) {
116✔
98
      return get_peer_cert_chain(*active);
116✔
99
   }
100
   return std::vector<X509_Certificate>();
×
101
}
102

103
std::optional<std::string> Channel_Impl_12::external_psk_identity() const {
1,741✔
104
   const auto* state = (active_state() != nullptr) ? active_state() : pending_state();
1,741✔
105
   if(state) {
1,741✔
106
      return state->psk_identity();
1,741✔
107
   } else {
108
      return std::nullopt;
×
109
   }
110
}
111

112
Handshake_State& Channel_Impl_12::create_handshake_state(Protocol_Version version) {
4,054✔
113
   if(pending_state()) {
4,054✔
114
      throw Internal_Error("create_handshake_state called during handshake");
×
115
   }
116

117
   if(auto active = active_state()) {
4,054✔
118
      Protocol_Version active_version = active->version();
51✔
119

120
      if(active_version.is_datagram_protocol() != version.is_datagram_protocol()) {
51✔
121
         throw TLS_Exception(Alert::ProtocolVersion,
×
122
                             "Active state using version " + active_version.to_string() + " cannot change to " +
×
123
                                version.to_string() + " in pending");
×
124
      }
125
   }
126

127
   if(!m_sequence_numbers) {
4,054✔
128
      if(version.is_datagram_protocol()) {
4,003✔
129
         m_sequence_numbers = std::make_unique<Datagram_Sequence_Numbers>();
818✔
130
      } else {
131
         m_sequence_numbers = std::make_unique<Stream_Sequence_Numbers>();
3,185✔
132
      }
133
   }
134

135
   using namespace std::placeholders;
4,054✔
136

137
   std::unique_ptr<Handshake_IO> io;
4,054✔
138
   if(version.is_datagram_protocol()) {
4,054✔
139
      io =
821✔
140
         std::make_unique<Datagram_Handshake_IO>(std::bind(&Channel_Impl_12::send_record_under_epoch, this, _1, _2, _3),
821✔
141
                                                 sequence_numbers(),
142
                                                 static_cast<uint16_t>(policy().dtls_default_mtu()),
821✔
143
                                                 policy().dtls_initial_timeout(),
821✔
144
                                                 policy().dtls_maximum_timeout());
1,642✔
145
   } else {
146
      io = std::make_unique<Stream_Handshake_IO>(std::bind(&Channel_Impl_12::send_record, this, _1, _2));
3,233✔
147
   }
148

149
   m_pending_state = new_handshake_state(std::move(io));
4,054✔
150

151
   if(auto active = active_state()) {
4,054✔
152
      m_pending_state->set_version(active->version());
51✔
153
   }
154

155
   return *m_pending_state;
4,054✔
156
}
4,054✔
157

158
bool Channel_Impl_12::timeout_check() {
10✔
159
   if(m_pending_state) {
10✔
160
      return m_pending_state->handshake_io().timeout_check();
4✔
161
   }
162

163
   //FIXME: scan cipher suites and remove epochs older than 2*MSL
164
   return false;
165
}
166

167
void Channel_Impl_12::renegotiate(bool force_full_renegotiation) {
×
168
   if(pending_state()) {  // currently in handshake?
×
169
      return;
170
   }
171

172
   if(auto active = active_state()) {
×
173
      if(force_full_renegotiation == false) {
×
174
         force_full_renegotiation = !policy().allow_resumption_for_renegotiation();
×
175
      }
176

177
      initiate_handshake(create_handshake_state(active->version()), force_full_renegotiation);
×
178
   } else {
179
      throw Invalid_State("Cannot renegotiate on inactive connection");
×
180
   }
181
}
182

183
void Channel_Impl_12::update_traffic_keys(bool) {
×
184
   throw Invalid_Argument("cannot update traffic keys on a TLS 1.2 channel");
×
185
}
186

187
void Channel_Impl_12::change_cipher_spec_reader(Connection_Side side) {
1,766✔
188
   auto pending = pending_state();
1,766✔
189

190
   BOTAN_ASSERT(pending && pending->server_hello(), "Have received server hello");
1,766✔
191

192
   if(pending->server_hello()->compression_method() != 0) {
1,766✔
193
      throw Internal_Error("Negotiated unknown compression algorithm");
×
194
   }
195

196
   sequence_numbers().new_read_cipher_state();
1,766✔
197

198
   const uint16_t epoch = sequence_numbers().current_read_epoch();
1,766✔
199

200
   BOTAN_ASSERT(!m_read_cipher_states.contains(epoch), "No read cipher state currently set for next epoch");
3,532✔
201

202
   // flip side as we are reading
203
   std::shared_ptr<Connection_Cipher_State> read_state(
1,766✔
204
      new Connection_Cipher_State(pending->version(),
3,532✔
205
                                  (side == Connection_Side::Client) ? Connection_Side::Server : Connection_Side::Client,
206
                                  false,
207
                                  pending->ciphersuite(),
1,766✔
208
                                  pending->session_keys(),
1,766✔
209
                                  pending->server_hello()->supports_encrypt_then_mac()));
2,589✔
210

211
   m_read_cipher_states[epoch] = read_state;
1,766✔
212
}
1,766✔
213

214
void Channel_Impl_12::change_cipher_spec_writer(Connection_Side side) {
1,765✔
215
   auto pending = pending_state();
1,765✔
216

217
   BOTAN_ASSERT(pending && pending->server_hello(), "Have received server hello");
1,765✔
218

219
   if(pending->server_hello()->compression_method() != 0) {
1,765✔
220
      throw Internal_Error("Negotiated unknown compression algorithm");
×
221
   }
222

223
   sequence_numbers().new_write_cipher_state();
1,765✔
224

225
   const uint16_t epoch = sequence_numbers().current_write_epoch();
1,765✔
226

227
   BOTAN_ASSERT(!m_write_cipher_states.contains(epoch), "No write cipher state currently set for next epoch");
3,530✔
228

229
   std::shared_ptr<Connection_Cipher_State> write_state(
1,765✔
230
      new Connection_Cipher_State(pending->version(),
3,530✔
231
                                  side,
232
                                  true,
233
                                  pending->ciphersuite(),
1,765✔
234
                                  pending->session_keys(),
1,765✔
235
                                  pending->server_hello()->supports_encrypt_then_mac()));
1,765✔
236

237
   m_write_cipher_states[epoch] = write_state;
1,765✔
238
}
1,765✔
239

240
bool Channel_Impl_12::is_active() const {
6,864✔
241
   if(is_closed()) {
6,864✔
242
      return false;
243
   }
244
   return (active_state() != nullptr);
6,100✔
245
}
246

247
bool Channel_Impl_12::is_closed() const {
14,281✔
248
   return m_has_been_closed;
14,281✔
249
}
250

251
void Channel_Impl_12::activate_session() {
1,726✔
252
   std::swap(m_active_state, m_pending_state);
1,726✔
253
   m_pending_state.reset();
1,726✔
254

255
   if(!m_active_state->version().is_datagram_protocol()) {
1,726✔
256
      // TLS is easy just remove all but the current state
257
      const uint16_t current_epoch = sequence_numbers().current_write_epoch();
1,030✔
258

259
      const auto not_current_epoch = [current_epoch](uint16_t epoch) { return (epoch != current_epoch); };
4,120✔
260

261
      map_remove_if(not_current_epoch, m_write_cipher_states);
1,030✔
262
      map_remove_if(not_current_epoch, m_read_cipher_states);
1,030✔
263
   }
264

265
   callbacks().tls_session_activated();
1,726✔
266
}
1,724✔
267

268
size_t Channel_Impl_12::from_peer(std::span<const uint8_t> data) {
148,242✔
269
   const bool allow_epoch0_restart = m_is_datagram && m_is_server && policy().allow_dtls_epoch0_restart();
148,242✔
270

271
   auto input = data.data();
148,242✔
272
   auto input_size = data.size();
148,242✔
273

274
   try {
148,242✔
275
      while(input_size) {
444,589✔
276
         size_t consumed = 0;
300,514✔
277

278
         auto get_epoch = [this](uint16_t epoch) { return read_cipher_state_epoch(epoch); };
12,265✔
279

280
         const Record_Header record = read_record(m_is_datagram,
302,259✔
281
                                                  m_readbuf,
300,514✔
282
                                                  input,
283
                                                  input_size,
284
                                                  consumed,
285
                                                  m_record_buf,
300,514✔
286
                                                  m_sequence_numbers.get(),
287
                                                  get_epoch,
288
                                                  allow_epoch0_restart);
289

290
         const size_t needed = record.needed();
298,769✔
291

292
         BOTAN_ASSERT(consumed > 0, "Got to eat something");
298,769✔
293

294
         BOTAN_ASSERT(consumed <= input_size, "Record reader consumed sane amount");
298,769✔
295

296
         input += consumed;
298,769✔
297
         input_size -= consumed;
298,769✔
298

299
         BOTAN_ASSERT(input_size == 0 || needed == 0, "Got a full record or consumed all input");
298,769✔
300

301
         if(input_size == 0 && needed != 0) {
298,769✔
302
            return needed;  // need more data to complete record
696✔
303
         }
304

305
         // Ignore invalid records in DTLS
306
         if(m_is_datagram && record.type() == Record_Type::Invalid) {
483,305✔
307
            return 0;
308
         }
309

310
         if(m_record_buf.size() > MAX_PLAINTEXT_SIZE) {
298,073✔
311
            throw TLS_Exception(Alert::RecordOverflow, "TLS plaintext record is larger than allowed maximum");
1✔
312
         }
313

314
         const bool epoch0_restart = m_is_datagram && record.epoch() == 0 && active_state();
481,925✔
315
         BOTAN_ASSERT_IMPLICATION(epoch0_restart, allow_epoch0_restart, "Allowed state");
298,072✔
316

317
         const bool initial_record = epoch0_restart || (!pending_state() && !active_state());
298,072✔
318

319
         if(record.type() != Record_Type::Alert) {
298,072✔
320
            if(initial_record) {
296,221✔
321
               // For initial records just check for basic sanity
322
               if(record.version().major_version() != 3 && record.version().major_version() != 0xFE) {
937✔
323
                  throw TLS_Exception(Alert::ProtocolVersion, "Received unexpected record version in initial record");
×
324
               }
325
            } else if(auto pending = pending_state()) {
295,284✔
326
               if(pending->server_hello() != nullptr && record.version() != pending->version()) {
292,884✔
327
                  throw TLS_Exception(Alert::ProtocolVersion, "Received unexpected record version");
×
328
               }
329
            } else if(auto active = active_state()) {
2,400✔
330
               if(record.version() != active->version()) {
2,400✔
331
                  throw TLS_Exception(Alert::ProtocolVersion, "Received unexpected record version");
×
332
               }
333
            }
334
         }
335

336
         if(record.type() == Record_Type::Handshake || record.type() == Record_Type::ChangeCipherSpec) {
298,072✔
337
            if(m_has_been_closed) {
293,877✔
338
               throw TLS_Exception(Alert::UnexpectedMessage, "Received handshake data after connection closure");
18✔
339
            }
340
            process_handshake_ccs(m_record_buf, record.sequence(), record.type(), record.version(), epoch0_restart);
587,718✔
341
         } else if(record.type() == Record_Type::ApplicationData) {
4,195✔
342
            if(m_has_been_closed) {
2,343✔
343
               throw TLS_Exception(Alert::UnexpectedMessage, "Received application data after connection closure");
6✔
344
            }
345
            if(pending_state() != nullptr) {
2,337✔
346
               throw TLS_Exception(Alert::UnexpectedMessage, "Can't interleave application and handshake data");
12✔
347
            }
348
            process_application_data(record.sequence(), m_record_buf);
2,325✔
349
         } else if(record.type() == Record_Type::Alert) {
1,852✔
350
            process_alert(m_record_buf);
1,851✔
351
         } else if(record.type() != Record_Type::Invalid) {
1✔
352
            throw Unexpected_Message("Unexpected record type " + std::to_string(static_cast<size_t>(record.type())) +
2✔
353
                                     " from counterparty");
2✔
354
         }
355
      }
356

357
      return 0;  // on a record boundary
358
   } catch(TLS_Exception& e) {
3,465✔
359
      send_fatal_alert(e.type());
3,253✔
360
      throw;
3,253✔
361
   } catch(Invalid_Authentication_Tag&) {
3,266✔
362
      send_fatal_alert(Alert::BadRecordMac);
13✔
363
      throw;
13✔
364
   } catch(Decoding_Error&) {
187✔
365
      send_fatal_alert(Alert::DecodeError);
174✔
366
      throw;
174✔
367
   } catch(...) {
199✔
368
      send_fatal_alert(Alert::InternalError);
25✔
369
      throw;
25✔
370
   }
25✔
371
}
372

373
void Channel_Impl_12::process_handshake_ccs(const secure_vector<uint8_t>& record,
293,859✔
374
                                            uint64_t record_sequence,
375
                                            Record_Type record_type,
376
                                            Protocol_Version record_version,
377
                                            bool epoch0_restart) {
378
   if(!m_pending_state) {
293,859✔
379
      // No pending handshake, possibly new:
380
      if(record_version.is_datagram_protocol() && !epoch0_restart) {
986✔
381
         if(m_sequence_numbers) {
377✔
382
            /*
383
            * Might be a peer retransmit under epoch - 1 in which
384
            * case we must retransmit last flight
385
            */
386
            sequence_numbers().read_accept(record_sequence);
2✔
387

388
            const uint16_t epoch = record_sequence >> 48;
2✔
389

390
            if(epoch == sequence_numbers().current_read_epoch()) {
2✔
391
               create_handshake_state(record_version);
2✔
392
            } else if(epoch == sequence_numbers().current_read_epoch() - 1) {
×
393
               BOTAN_ASSERT(m_active_state, "Have active state here");
×
394
               m_active_state->handshake_io().add_record(record.data(), record.size(), record_type, record_sequence);
×
395
            }
396
         } else {
397
            create_handshake_state(record_version);
375✔
398
         }
399
      } else {
400
         create_handshake_state(record_version);
609✔
401
      }
402
   }
403

404
   // May have been created in above conditional
405
   if(m_pending_state) {
293,859✔
406
      m_pending_state->handshake_io().add_record(record.data(), record.size(), record_type, record_sequence);
293,859✔
407

408
      while(auto pending = m_pending_state.get()) {
302,455✔
409
         auto msg = pending->get_next_handshake_msg();
302,455✔
410

411
         if(msg.first == Handshake_Type::None) {  // no full handshake yet
302,455✔
412
            break;
413
         }
414

415
         process_handshake_msg(active_state(), *pending, msg.first, msg.second, epoch0_restart);
11,999✔
416

417
         if(!m_pending_state) {
10,330✔
418
            break;
419
         }
420
      }
300,786✔
421
   }
422
}
292,181✔
423

424
void Channel_Impl_12::process_application_data(uint64_t seq_no, const secure_vector<uint8_t>& record) {
2,325✔
425
   if(!active_state()) {
2,325✔
426
      throw Unexpected_Message("Application data before handshake done");
×
427
   }
428

429
   callbacks().tls_record_received(seq_no, record);
2,325✔
430
}
2,325✔
431

432
void Channel_Impl_12::process_alert(const secure_vector<uint8_t>& record) {
1,851✔
433
   Alert alert_msg(record);
1,851✔
434

435
   if(alert_msg.type() == Alert::NoRenegotiation) {
1,847✔
436
      m_pending_state.reset();
232✔
437
   }
438

439
   callbacks().tls_alert(alert_msg);
1,847✔
440

441
   if(alert_msg.is_fatal()) {
1,841✔
442
      if(auto active = active_state()) {
14✔
443
         const auto& session_id = active->server_hello()->session_id();
6✔
444
         if(!session_id.empty()) {
6✔
445
            session_manager().remove(session_id);
12✔
446
         }
447
      }
448
   }
449

450
   if(alert_msg.type() == Alert::CloseNotify) {
1,841✔
451
      // TLS 1.2 requires us to immediately react with our "close_notify",
452
      // the return value of the application's callback has no effect on that.
453
      callbacks().tls_peer_closed_connection();
1,574✔
454
      send_warning_alert(Alert::CloseNotify);  // reply in kind
1,574✔
455
   }
456

457
   if(alert_msg.type() == Alert::CloseNotify || alert_msg.is_fatal()) {
1,841✔
458
      m_has_been_closed = true;
1,588✔
459
   }
460
}
1,841✔
461

462
void Channel_Impl_12::write_record(Connection_Cipher_State* cipher_state,
18,528✔
463
                                   uint16_t epoch,
464
                                   Record_Type record_type,
465
                                   const uint8_t input[],
466
                                   size_t length) {
467
   BOTAN_ASSERT(m_pending_state || m_active_state, "Some connection state exists");
18,528✔
468

469
   const Protocol_Version record_version =
18,528✔
470
      (m_pending_state) ? (m_pending_state->version()) : (m_active_state->version());
18,528✔
471

472
   const uint64_t next_seq = sequence_numbers().next_write_sequence(epoch);
18,528✔
473

474
   if(cipher_state == nullptr) {
18,528✔
475
      TLS::write_unencrypted_record(m_writebuf, record_type, record_version, next_seq, input, length);
12,228✔
476
   } else {
477
      TLS::write_record(m_writebuf, record_type, record_version, next_seq, input, length, *cipher_state, rng());
6,300✔
478
   }
479

480
   callbacks().tls_emit_data(m_writebuf);
18,528✔
481
}
18,526✔
482

483
void Channel_Impl_12::send_record_array(uint16_t epoch, Record_Type type, const uint8_t input[], size_t length) {
18,528✔
484
   if(length == 0) {
18,528✔
485
      return;
×
486
   }
487

488
   auto cipher_state = write_cipher_state_epoch(epoch);
18,528✔
489

490
   while(length) {
37,054✔
491
      const size_t sending = std::min<size_t>(length, MAX_PLAINTEXT_SIZE);
18,528✔
492
      write_record(cipher_state.get(), epoch, type, input, sending);
18,528✔
493

494
      input += sending;
18,526✔
495
      length -= sending;
18,526✔
496
   }
497
}
18,526✔
498

499
void Channel_Impl_12::send_record(Record_Type record_type, const std::vector<uint8_t>& record) {
11,200✔
500
   send_record_array(sequence_numbers().current_write_epoch(), record_type, record.data(), record.size());
11,200✔
501
}
11,199✔
502

503
void Channel_Impl_12::send_record_under_epoch(uint16_t epoch,
4,817✔
504
                                              Record_Type record_type,
505
                                              const std::vector<uint8_t>& record) {
506
   send_record_array(epoch, record_type, record.data(), record.size());
4,817✔
507
}
4,816✔
508

509
void Channel_Impl_12::to_peer(std::span<const uint8_t> data) {
2,511✔
510
   if(!is_active()) {
2,511✔
511
      throw Invalid_State("Data cannot be sent on inactive TLS connection");
×
512
   }
513

514
   send_record_array(sequence_numbers().current_write_epoch(), Record_Type::ApplicationData, data.data(), data.size());
2,511✔
515
}
2,511✔
516

517
void Channel_Impl_12::send_alert(const Alert& alert) {
6,779✔
518
   const bool ready_to_send_anything = !is_closed() && m_sequence_numbers;
6,779✔
519
   if(alert.is_valid() && ready_to_send_anything) {
6,779✔
520
      try {
4,198✔
521
         send_record(Record_Type::Alert, alert.serialize());
8,396✔
522
      } catch(...) { /* swallow it */
×
523
      }
×
524
   }
525

526
   if(alert.type() == Alert::NoRenegotiation) {
6,779✔
527
      m_pending_state.reset();
244✔
528
   }
529

530
   if(alert.is_fatal()) {
6,779✔
531
      if(auto active = active_state()) {
3,473✔
532
         const auto& session_id = active->server_hello()->session_id();
87✔
533
         if(!session_id.empty()) {
87✔
534
            session_manager().remove(Session_ID(session_id));
18✔
535
         }
536
      }
537
      reset_state();
3,473✔
538
   }
539

540
   if(alert.type() == Alert::CloseNotify || alert.is_fatal()) {
6,779✔
541
      m_has_been_closed = true;
6,540✔
542
   }
543
}
6,779✔
544

545
void Channel_Impl_12::secure_renegotiation_check(const Client_Hello_12* client_hello) {
4,026✔
546
   const bool secure_renegotiation = client_hello->secure_renegotiation();
4,026✔
547

548
   if(auto active = active_state()) {
4,026✔
549
      const bool active_sr = active->client_hello()->secure_renegotiation();
33✔
550

551
      if(active_sr != secure_renegotiation) {
33✔
552
         throw TLS_Exception(Alert::HandshakeFailure, "Client changed its mind about secure renegotiation");
×
553
      }
554
   }
555

556
   if(secure_renegotiation) {
4,026✔
557
      const std::vector<uint8_t>& data = client_hello->renegotiation_info();
4,023✔
558

559
      if(data != secure_renegotiation_data_for_client_hello()) {
4,023✔
560
         throw TLS_Exception(Alert::HandshakeFailure, "Client sent bad values for secure renegotiation");
×
561
      }
562
   }
4,023✔
563
}
4,026✔
564

565
void Channel_Impl_12::secure_renegotiation_check(const Server_Hello_12* server_hello) {
2,019✔
566
   const bool secure_renegotiation = server_hello->secure_renegotiation();
2,019✔
567

568
   if(auto active = active_state()) {
2,019✔
569
      const bool active_sr = active->server_hello()->secure_renegotiation();
31✔
570

571
      if(active_sr != secure_renegotiation) {
31✔
572
         throw TLS_Exception(Alert::HandshakeFailure, "Server changed its mind about secure renegotiation");
1✔
573
      }
574
   }
575

576
   if(secure_renegotiation) {
2,018✔
577
      const std::vector<uint8_t>& data = server_hello->renegotiation_info();
2,010✔
578

579
      if(data != secure_renegotiation_data_for_server_hello()) {
2,039✔
580
         throw TLS_Exception(Alert::HandshakeFailure, "Server sent bad values for secure renegotiation");
3✔
581
      }
582
   }
2,007✔
583
}
2,015✔
584

585
std::vector<uint8_t> Channel_Impl_12::secure_renegotiation_data_for_client_hello() const {
6,666✔
586
   if(auto active = active_state()) {
6,666✔
587
      return active->client_finished()->verify_data();
66✔
588
   }
589
   return std::vector<uint8_t>();
6,633✔
590
}
591

592
std::vector<uint8_t> Channel_Impl_12::secure_renegotiation_data_for_server_hello() const {
2,922✔
593
   if(auto active = active_state()) {
2,922✔
594
      std::vector<uint8_t> buf = active->client_finished()->verify_data();
29✔
595
      buf += active->server_finished()->verify_data();
29✔
596
      return buf;
29✔
597
   }
29✔
598

599
   return std::vector<uint8_t>();
2,922✔
600
}
601

602
bool Channel_Impl_12::secure_renegotiation_supported() const {
44✔
603
   if(auto active = active_state()) {
44✔
604
      return active->server_hello()->secure_renegotiation();
39✔
605
   }
606

607
   if(auto pending = pending_state()) {
5✔
608
      if(auto hello = pending->server_hello()) {
5✔
609
         return hello->secure_renegotiation();
5✔
610
      }
611
   }
612

613
   return false;
614
}
615

616
SymmetricKey Channel_Impl_12::key_material_export(std::string_view label,
405✔
617
                                                  std::string_view context,
618
                                                  size_t length) const {
619
   if(auto active = active_state()) {
405✔
620
      if(pending_state() != nullptr) {
405✔
621
         throw Invalid_State("Channel_Impl_12::key_material_export cannot export during renegotiation");
1✔
622
      }
623

624
      auto prf = active->protocol_specific_prf();
404✔
625

626
      const secure_vector<uint8_t>& master_secret = active->session_keys().master_secret();
404✔
627

628
      std::vector<uint8_t> salt;
404✔
629
      salt += active->client_hello()->random();
404✔
630
      salt += active->server_hello()->random();
404✔
631

632
      if(!context.empty()) {
404✔
633
         size_t context_size = context.length();
235✔
634
         if(context_size > 0xFFFF) {
235✔
635
            throw Invalid_Argument("key_material_export context is too long");
×
636
         }
637
         salt.push_back(get_byte<0>(static_cast<uint16_t>(context_size)));
235✔
638
         salt.push_back(get_byte<1>(static_cast<uint16_t>(context_size)));
235✔
639
         salt += to_byte_vector(context);
470✔
640
      }
641

642
      return SymmetricKey(prf->derive_key(length, master_secret, salt, to_byte_vector(label)));
639✔
643
   } else {
808✔
644
      throw Invalid_State("Channel_Impl_12::key_material_export connection not active");
×
645
   }
646
}
647

648
}  // 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

© 2025 Coveralls, Inc