Botan 3.0.0-alpha0
Crypto and TLS for C&
tls_channel_impl_12.cpp
Go to the documentation of this file.
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/tls_policy.h>
10#include <botan/tls_messages.h>
11#include <botan/kdf.h>
12#include <botan/internal/tls_channel_impl_12.h>
13#include <botan/internal/tls_handshake_state.h>
14#include <botan/internal/tls_record.h>
15#include <botan/internal/tls_seq_numbers.h>
16#include <botan/internal/stl_util.h>
17#include <botan/internal/loadstor.h>
18#include <botan/x509cert.h>
19
20namespace Botan::TLS {
21
23 Session_Manager& session_manager,
25 const Policy& policy,
26 bool is_server,
27 bool is_datagram,
28 size_t reserved_io_buffer_size) :
29 m_is_server(is_server),
30 m_is_datagram(is_datagram),
31 m_callbacks(callbacks),
32 m_session_manager(session_manager),
33 m_policy(policy),
34 m_rng(rng),
35 m_has_been_closed(false)
36 {
37 /* epoch 0 is plaintext, thus null cipher state */
38 m_write_cipher_states[0] = nullptr;
39 m_read_cipher_states[0] = nullptr;
40
41 m_writebuf.reserve(reserved_io_buffer_size);
42 m_readbuf.reserve(reserved_io_buffer_size);
43 }
44
45void Channel_Impl_12::reset_state()
46 {
47 m_active_state.reset();
48 m_pending_state.reset();
49 m_readbuf.clear();
50 m_write_cipher_states.clear();
51 m_read_cipher_states.clear();
52 }
53
55 {
56 // This operation only makes sense for DTLS
57 BOTAN_ASSERT_NOMSG(m_is_datagram);
58 m_active_state.reset();
59 m_read_cipher_states.clear();
60 m_write_cipher_states.clear();
61
62 m_write_cipher_states[0] = nullptr;
63 m_read_cipher_states[0] = nullptr;
64
65 if(m_sequence_numbers)
66 m_sequence_numbers->reset();
67 }
68
70 {
71 // So unique_ptr destructors run correctly
72 }
73
74Connection_Sequence_Numbers& Channel_Impl_12::sequence_numbers() const
75 {
76 BOTAN_ASSERT(m_sequence_numbers, "Have a sequence numbers object");
77 return *m_sequence_numbers;
78 }
79
80std::shared_ptr<Connection_Cipher_State> Channel_Impl_12::read_cipher_state_epoch(uint16_t epoch) const
81 {
82 auto i = m_read_cipher_states.find(epoch);
83 if(i == m_read_cipher_states.end())
84 { throw Internal_Error("TLS::Channel_Impl_12 No read cipherstate for epoch " + std::to_string(epoch)); }
85 return i->second;
86 }
87
88std::shared_ptr<Connection_Cipher_State> Channel_Impl_12::write_cipher_state_epoch(uint16_t epoch) const
89 {
90 auto i = m_write_cipher_states.find(epoch);
91 if(i == m_write_cipher_states.end())
92 { throw Internal_Error("TLS::Channel_Impl_12 No write cipherstate for epoch " + std::to_string(epoch)); }
93 return i->second;
94 }
95
96std::vector<X509_Certificate> Channel_Impl_12::peer_cert_chain() const
97 {
98 if(auto active = active_state())
99 return get_peer_cert_chain(*active);
100 return std::vector<X509_Certificate>();
101 }
102
104 {
105 return callbacks().tls_session_established(session);
106 }
107
109 {
110 if(pending_state())
111 throw Internal_Error("create_handshake_state called during handshake");
112
113 if(auto active = active_state())
114 {
115 Protocol_Version active_version = active->version();
116
117 if(active_version.is_datagram_protocol() != version.is_datagram_protocol())
118 {
120 "Active state using version " + active_version.to_string() +
121 " cannot change to " + version.to_string() + " in pending");
122 }
123 }
124
125 if(!m_sequence_numbers)
126 {
127 if(version.is_datagram_protocol())
128 m_sequence_numbers.reset(new Datagram_Sequence_Numbers);
129 else
130 m_sequence_numbers.reset(new Stream_Sequence_Numbers);
131 }
132
133 using namespace std::placeholders;
134
135 std::unique_ptr<Handshake_IO> io;
136 if(version.is_datagram_protocol())
137 {
138 io.reset(new Datagram_Handshake_IO(
139 std::bind(&Channel_Impl_12::send_record_under_epoch, this, _1, _2, _3),
140 sequence_numbers(),
141 static_cast<uint16_t>(m_policy.dtls_default_mtu()),
142 m_policy.dtls_initial_timeout(),
143 m_policy.dtls_maximum_timeout()));
144 }
145 else
146 {
147 io.reset(new Stream_Handshake_IO(std::bind(&Channel_Impl_12::send_record, this, _1, _2)));
148 }
149
150 m_pending_state = new_handshake_state(std::move(io));
151
152 if(auto active = active_state())
153 m_pending_state->set_version(active->version());
154
155 return *m_pending_state.get();
156 }
157
159 {
160 if(m_pending_state)
161 return m_pending_state->handshake_io().timeout_check();
162
163 //FIXME: scan cipher suites and remove epochs older than 2*MSL
164 return false;
165 }
166
167void Channel_Impl_12::renegotiate(bool force_full_renegotiation)
168 {
169 if(pending_state()) // currently in handshake?
170 return;
171
172 if(auto active = active_state())
173 {
174 if(force_full_renegotiation == false)
175 force_full_renegotiation = !policy().allow_resumption_for_renegotiation();
176
178 force_full_renegotiation);
179 }
180 else
181 throw Invalid_State("Cannot renegotiate on inactive connection");
182 }
183
185 {
186 throw Invalid_Argument("cannot update traffic keys on a TLS 1.2 channel");
187 }
188
190 {
191 auto pending = pending_state();
192
193 BOTAN_ASSERT(pending && pending->server_hello(),
194 "Have received server hello");
195
196 if(pending->server_hello()->compression_method() != 0)
197 throw Internal_Error("Negotiated unknown compression algorithm");
198
199 sequence_numbers().new_read_cipher_state();
200
201 const uint16_t epoch = sequence_numbers().current_read_epoch();
202
203 BOTAN_ASSERT(m_read_cipher_states.count(epoch) == 0,
204 "No read cipher state currently set for next epoch");
205
206 // flip side as we are reading
207 std::shared_ptr<Connection_Cipher_State> read_state(
208 new Connection_Cipher_State(pending->version(),
209 (side == CLIENT) ? SERVER : CLIENT,
210 false,
211 pending->ciphersuite(),
212 pending->session_keys(),
213 pending->server_hello()->supports_encrypt_then_mac()));
214
215 m_read_cipher_states[epoch] = read_state;
216 }
217
219 {
220 auto pending = pending_state();
221
222 BOTAN_ASSERT(pending && pending->server_hello(),
223 "Have received server hello");
224
225 if(pending->server_hello()->compression_method() != 0)
226 throw Internal_Error("Negotiated unknown compression algorithm");
227
228 sequence_numbers().new_write_cipher_state();
229
230 const uint16_t epoch = sequence_numbers().current_write_epoch();
231
232 BOTAN_ASSERT(m_write_cipher_states.count(epoch) == 0,
233 "No write cipher state currently set for next epoch");
234
235 std::shared_ptr<Connection_Cipher_State> write_state(
236 new Connection_Cipher_State(pending->version(),
237 side,
238 true,
239 pending->ciphersuite(),
240 pending->session_keys(),
241 pending->server_hello()->supports_encrypt_then_mac()));
242
243 m_write_cipher_states[epoch] = write_state;
244 }
245
247 {
248 if(is_closed())
249 return false;
250 return (active_state() != nullptr);
251 }
252
254 {
255 return m_has_been_closed;
256 }
257
259 {
260 std::swap(m_active_state, m_pending_state);
261 m_pending_state.reset();
262
263 if(!m_active_state->version().is_datagram_protocol())
264 {
265 // TLS is easy just remove all but the current state
266 const uint16_t current_epoch = sequence_numbers().current_write_epoch();
267
268 const auto not_current_epoch =
269 [current_epoch](uint16_t epoch) { return (epoch != current_epoch); };
270
271 map_remove_if(not_current_epoch, m_write_cipher_states);
272 map_remove_if(not_current_epoch, m_read_cipher_states);
273 }
274
276 }
277
278size_t Channel_Impl_12::received_data(const uint8_t input[], size_t input_size)
279 {
280 const bool allow_epoch0_restart = m_is_datagram && m_is_server && policy().allow_dtls_epoch0_restart();
281
282 try
283 {
284 while(input_size)
285 {
286 size_t consumed = 0;
287
288 auto get_epoch = [this](uint16_t epoch) { return read_cipher_state_epoch(epoch); };
289
290 const Record_Header record =
291 read_record(m_is_datagram,
292 m_readbuf,
293 input,
294 input_size,
295 consumed,
296 m_record_buf,
297 m_sequence_numbers.get(),
298 get_epoch,
299 allow_epoch0_restart);
300
301 const size_t needed = record.needed();
302
303 BOTAN_ASSERT(consumed > 0, "Got to eat something");
304
305 BOTAN_ASSERT(consumed <= input_size,
306 "Record reader consumed sane amount");
307
308 input += consumed;
309 input_size -= consumed;
310
311 BOTAN_ASSERT(input_size == 0 || needed == 0,
312 "Got a full record or consumed all input");
313
314 if(input_size == 0 && needed != 0)
315 return needed; // need more data to complete record
316
317 // Ignore invalid records in DTLS
318 if(m_is_datagram && record.type() == NO_RECORD)
319 {
320 return 0;
321 }
322
323 if(m_record_buf.size() > MAX_PLAINTEXT_SIZE)
325 "TLS plaintext record is larger than allowed maximum");
326
327
328 const bool epoch0_restart = m_is_datagram && record.epoch() == 0 && active_state();
329 BOTAN_ASSERT_IMPLICATION(epoch0_restart, allow_epoch0_restart, "Allowed state");
330
331 const bool initial_record = epoch0_restart || (!pending_state() && !active_state());
332
333 if(record.type() != ALERT)
334 {
335 if(initial_record)
336 {
337 // For initial records just check for basic sanity
338 if(record.version().major_version() != 3 &&
339 record.version().major_version() != 0xFE)
340 {
342 "Received unexpected record version in initial record");
343 }
344 }
345 else if(auto pending = pending_state())
346 {
347 if(pending->server_hello() != nullptr && record.version() != pending->version())
348 {
350 "Received unexpected record version");
351 }
352 }
353 else if(auto active = active_state())
354 {
355 if(record.version() != active->version())
356 {
358 "Received unexpected record version");
359 }
360 }
361 }
362
363 if(record.type() == HANDSHAKE || record.type() == CHANGE_CIPHER_SPEC)
364 {
365 if(m_has_been_closed)
366 throw TLS_Exception(Alert::UNEXPECTED_MESSAGE, "Received handshake data after connection closure");
367 process_handshake_ccs(m_record_buf, record.sequence(), record.type(), record.version(), epoch0_restart);
368 }
369 else if(record.type() == APPLICATION_DATA)
370 {
371 if(m_has_been_closed)
372 throw TLS_Exception(Alert::UNEXPECTED_MESSAGE, "Received application data after connection closure");
373 if(pending_state() != nullptr)
374 throw TLS_Exception(Alert::UNEXPECTED_MESSAGE, "Can't interleave application and handshake data");
375 process_application_data(record.sequence(), m_record_buf);
376 }
377 else if(record.type() == ALERT)
378 {
379 process_alert(m_record_buf);
380 }
381 else if(record.type() != NO_RECORD)
382 throw Unexpected_Message("Unexpected record type " +
383 std::to_string(record.type()) +
384 " from counterparty");
385 }
386
387 return 0; // on a record boundary
388 }
389 catch(TLS_Exception& e)
390 {
392 throw;
393 }
395 {
397 throw;
398 }
399 catch(Decoding_Error&)
400 {
402 throw;
403 }
404 catch(...)
405 {
407 throw;
408 }
409 }
410
411void Channel_Impl_12::process_handshake_ccs(const secure_vector<uint8_t>& record,
412 uint64_t record_sequence,
413 Record_Type record_type,
414 Protocol_Version record_version,
415 bool epoch0_restart)
416 {
417 if(!m_pending_state)
418 {
419 // No pending handshake, possibly new:
420 if(record_version.is_datagram_protocol() && !epoch0_restart)
421 {
422 if(m_sequence_numbers)
423 {
424 /*
425 * Might be a peer retransmit under epoch - 1 in which
426 * case we must retransmit last flight
427 */
428 sequence_numbers().read_accept(record_sequence);
429
430 const uint16_t epoch = record_sequence >> 48;
431
432 if(epoch == sequence_numbers().current_read_epoch())
433 {
434 create_handshake_state(record_version);
435 }
436 else if(epoch == sequence_numbers().current_read_epoch() - 1)
437 {
438 BOTAN_ASSERT(m_active_state, "Have active state here");
439 m_active_state->handshake_io().add_record(record.data(),
440 record.size(),
441 record_type,
442 record_sequence);
443 }
444 }
445 else
446 {
447 create_handshake_state(record_version);
448 }
449 }
450 else
451 {
452 create_handshake_state(record_version);
453 }
454 }
455
456 // May have been created in above conditional
457 if(m_pending_state)
458 {
459 m_pending_state->handshake_io().add_record(record.data(),
460 record.size(),
461 record_type,
462 record_sequence);
463
464 while(auto pending = m_pending_state.get())
465 {
466 auto msg = pending->get_next_handshake_msg();
467
468 if(msg.first == HANDSHAKE_NONE) // no full handshake yet
469 break;
470
471 process_handshake_msg(active_state(), *pending,
472 msg.first, msg.second, epoch0_restart);
473
474 if(!m_pending_state)
475 break;
476 }
477 }
478 }
479
480void Channel_Impl_12::process_application_data(uint64_t seq_no, const secure_vector<uint8_t>& record)
481 {
482 if(!active_state())
483 throw Unexpected_Message("Application data before handshake done");
484
485 callbacks().tls_record_received(seq_no, record.data(), record.size());
486 }
487
488void Channel_Impl_12::process_alert(const secure_vector<uint8_t>& record)
489 {
490 Alert alert_msg(record);
491
492 if(alert_msg.type() == Alert::NO_RENEGOTIATION)
493 m_pending_state.reset();
494
495 callbacks().tls_alert(alert_msg);
496
497 if(alert_msg.is_fatal())
498 {
499 if(auto active = active_state())
500 m_session_manager.remove_entry(active->server_hello()->session_id());
501 }
502
503 if(alert_msg.type() == Alert::CLOSE_NOTIFY)
504 send_warning_alert(Alert::CLOSE_NOTIFY); // reply in kind
505
506 if(alert_msg.type() == Alert::CLOSE_NOTIFY || alert_msg.is_fatal())
507 {
508 m_has_been_closed = true;
509 }
510 }
511
512void Channel_Impl_12::write_record(Connection_Cipher_State* cipher_state, uint16_t epoch,
513 uint8_t record_type, const uint8_t input[], size_t length)
514 {
515 BOTAN_ASSERT(m_pending_state || m_active_state, "Some connection state exists");
516
517 const Protocol_Version record_version =
518 (m_pending_state) ? (m_pending_state->version()) : (m_active_state->version());
519
520 const uint64_t next_seq = sequence_numbers().next_write_sequence(epoch);
521
522 if(cipher_state == nullptr)
523 {
524 TLS::write_unencrypted_record(m_writebuf, record_type, record_version, next_seq,
525 input, length);
526 }
527 else
528 {
529 TLS::write_record(m_writebuf, record_type, record_version, next_seq,
530 input, length, *cipher_state, m_rng);
531 }
532
533 callbacks().tls_emit_data(m_writebuf.data(), m_writebuf.size());
534 }
535
536void Channel_Impl_12::send_record_array(uint16_t epoch, uint8_t type, const uint8_t input[], size_t length)
537 {
538 if(length == 0)
539 return;
540
541 auto cipher_state = write_cipher_state_epoch(epoch);
542
543 while(length)
544 {
545 const size_t sending = std::min<size_t>(length, MAX_PLAINTEXT_SIZE);
546 write_record(cipher_state.get(), epoch, type, input, sending);
547
548 input += sending;
549 length -= sending;
550 }
551 }
552
553void Channel_Impl_12::send_record(uint8_t record_type, const std::vector<uint8_t>& record)
554 {
555 send_record_array(sequence_numbers().current_write_epoch(),
556 record_type, record.data(), record.size());
557 }
558
559void Channel_Impl_12::send_record_under_epoch(uint16_t epoch, uint8_t record_type,
560 const std::vector<uint8_t>& record)
561 {
562 send_record_array(epoch, record_type, record.data(), record.size());
563 }
564
565void Channel_Impl_12::send(const uint8_t buf[], size_t buf_size)
566 {
567 if(!is_active())
568 throw Invalid_State("Data cannot be sent on inactive TLS connection");
569
570 send_record_array(sequence_numbers().current_write_epoch(),
571 APPLICATION_DATA, buf, buf_size);
572 }
573
575 {
576 const bool ready_to_send_anything = !is_closed() && m_sequence_numbers;
577 if(alert.is_valid() && ready_to_send_anything)
578 {
579 try
580 {
581 send_record(ALERT, alert.serialize());
582 }
583 catch(...) { /* swallow it */ }
584 }
585
586 if(alert.type() == Alert::NO_RENEGOTIATION)
587 m_pending_state.reset();
588
589 if(alert.is_fatal())
590 {
591 if(auto active = active_state())
592 {
593 m_session_manager.remove_entry(active->server_hello()->session_id());
594 }
595 reset_state();
596 }
597
598 if(alert.type() == Alert::CLOSE_NOTIFY || alert.is_fatal())
599 {
600 m_has_been_closed = true;
601 }
602 }
603
605 {
606 const bool secure_renegotiation = client_hello->secure_renegotiation();
607
608 if(auto active = active_state())
609 {
610 const bool active_sr = active->client_hello()->secure_renegotiation();
611
612 if(active_sr != secure_renegotiation)
614 "Client changed its mind about secure renegotiation");
615 }
616
617 if(secure_renegotiation)
618 {
619 const std::vector<uint8_t>& data = client_hello->renegotiation_info();
620
623 "Client sent bad values for secure renegotiation");
624 }
625 }
626
628 {
629 const bool secure_renegotiation = server_hello->secure_renegotiation();
630
631 if(auto active = active_state())
632 {
633 const bool active_sr = active->server_hello()->secure_renegotiation();
634
635 if(active_sr != secure_renegotiation)
637 "Server changed its mind about secure renegotiation");
638 }
639
640 if(secure_renegotiation)
641 {
642 const std::vector<uint8_t>& data = server_hello->renegotiation_info();
643
646 "Server sent bad values for secure renegotiation");
647 }
648 }
649
651 {
652 if(auto active = active_state())
653 return active->client_finished()->verify_data();
654 return std::vector<uint8_t>();
655 }
656
658 {
659 if(auto active = active_state())
660 {
661 std::vector<uint8_t> buf = active->client_finished()->verify_data();
662 buf += active->server_finished()->verify_data();
663 return buf;
664 }
665
666 return std::vector<uint8_t>();
667 }
668
670 {
671 if(auto active = active_state())
672 return active->server_hello()->secure_renegotiation();
673
674 if(auto pending = pending_state())
675 if(auto hello = pending->server_hello())
676 return hello->secure_renegotiation();
677
678 return false;
679 }
680
682 const std::string& context,
683 size_t length) const
684 {
685 if(auto active = active_state())
686 {
687 if(pending_state() != nullptr)
688 { throw Invalid_State("Channel_Impl_12::key_material_export cannot export during renegotiation"); }
689
690 auto prf = active->protocol_specific_prf();
691
692 const secure_vector<uint8_t>& master_secret =
693 active->session_keys().master_secret();
694
695 std::vector<uint8_t> salt;
696 salt += active->client_hello()->random();
697 salt += active->server_hello()->random();
698
699 if(!context.empty())
700 {
701 size_t context_size = context.length();
702 if(context_size > 0xFFFF)
703 throw Invalid_Argument("key_material_export context is too long");
704 salt.push_back(get_byte<0>(static_cast<uint16_t>(context_size)));
705 salt.push_back(get_byte<1>(static_cast<uint16_t>(context_size)));
706 salt += to_byte_vector(context);
707 }
708
709 return prf->derive_key(length, master_secret, salt, to_byte_vector(label));
710 }
711 else
712 {
713 throw Invalid_State("Channel_Impl_12::key_material_export connection not active");
714 }
715 }
716
717}
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:67
#define BOTAN_ASSERT_IMPLICATION(expr1, expr2, msg)
Definition: assert.h:93
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:54
bool is_valid() const
Definition: tls_alert.h:71
std::vector< uint8_t > serialize() const
Definition: tls_alert.cpp:29
bool is_fatal() const
Definition: tls_alert.h:82
Type type() const
Definition: tls_alert.h:87
virtual void tls_emit_data(const uint8_t data[], size_t size)=0
virtual void tls_session_activated()
Definition: tls_callbacks.h:99
virtual bool tls_session_established(const Session &session)=0
virtual void tls_record_received(uint64_t seq_no, const uint8_t data[], size_t size)=0
virtual void tls_alert(Alert alert)=0
virtual std::vector< X509_Certificate > get_peer_cert_chain(const Handshake_State &state) const =0
void change_cipher_spec_reader(Connection_Side side)
Channel_Impl_12(Callbacks &callbacks, Session_Manager &session_manager, RandomNumberGenerator &rng, const Policy &policy, bool is_server, bool is_datagram, size_t io_buf_sz=Botan::TLS::Channel::IO_BUF_DEFAULT_SIZE)
void send(const uint8_t buf[], size_t buf_size) override
void update_traffic_keys(bool request_peer_update=false) override
Handshake_State & create_handshake_state(Protocol_Version version)
std::vector< uint8_t > secure_renegotiation_data_for_server_hello() const
void secure_renegotiation_check(const Client_Hello_12 *client_hello)
const Policy & policy() const
void send_alert(const Alert &alert) override
virtual void initiate_handshake(Handshake_State &state, bool force_full_renegotiation)=0
std::vector< X509_Certificate > peer_cert_chain() const override
void change_cipher_spec_writer(Connection_Side side)
std::vector< uint8_t > secure_renegotiation_data_for_client_hello() const
virtual std::unique_ptr< Handshake_State > new_handshake_state(std::unique_ptr< class Handshake_IO > io)=0
size_t received_data(const uint8_t buf[], size_t buf_size) override
bool save_session(const Session &session)
virtual void process_handshake_msg(const Handshake_State *active_state, Handshake_State &pending_state, Handshake_Type type, const std::vector< uint8_t > &contents, bool epoch0_restart)=0
SymmetricKey key_material_export(const std::string &label, const std::string &context, size_t length) const override
bool secure_renegotiation_supported() const override
void renegotiate(bool force_full_renegotiation=false) override
void send_warning_alert(Alert::Type type)
void send_fatal_alert(Alert::Type type)
std::vector< uint8_t > renegotiation_info() const
virtual uint16_t current_read_epoch() const =0
virtual void read_accept(uint64_t seq)=0
virtual uint16_t current_write_epoch() const =0
virtual uint64_t next_write_sequence(uint16_t)=0
virtual size_t dtls_maximum_timeout() const
Definition: tls_policy.cpp:359
virtual size_t dtls_default_mtu() const
Definition: tls_policy.cpp:361
virtual bool allow_dtls_epoch0_restart() const
Definition: tls_policy.cpp:353
virtual size_t dtls_initial_timeout() const
Definition: tls_policy.cpp:358
virtual bool allow_resumption_for_renegotiation() const
Definition: tls_policy.cpp:346
std::string to_string() const
Definition: tls_version.cpp:15
uint8_t major_version() const
Definition: tls_version.h:83
Protocol_Version version() const
Definition: tls_record.h:96
Record_Type type() const
Definition: tls_record.h:113
uint64_t sequence() const
Definition: tls_record.h:102
size_t needed() const
Definition: tls_record.h:94
uint16_t epoch() const
Definition: tls_record.h:108
std::vector< uint8_t > renegotiation_info() const
virtual void remove_entry(const std::vector< uint8_t > &session_id)=0
Alert::Type type() const
Definition: tls_exceptn.h:24
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:209
@ HANDSHAKE_NONE
Definition: tls_magic.h:88
@ CHANGE_CIPHER_SPEC
Definition: tls_magic.h:52
@ APPLICATION_DATA
Definition: tls_magic.h:55
Record_Header read_record(bool is_datagram, secure_vector< uint8_t > &readbuf, const uint8_t input[], size_t input_len, size_t &consumed, secure_vector< uint8_t > &recbuf, Connection_Sequence_Numbers *sequence_numbers, const get_cipherstate_fn &get_cipherstate, bool allow_epoch0_restart)
Definition: tls_record.cpp:557
void write_record(secure_vector< uint8_t > &output, uint8_t record_type, Protocol_Version version, uint64_t record_sequence, const uint8_t *message, size_t message_len, Connection_Cipher_State &cs, RandomNumberGenerator &rng)
Definition: tls_record.cpp:222
void write_unencrypted_record(secure_vector< uint8_t > &output, uint8_t record_type, Protocol_Version version, uint64_t record_sequence, const uint8_t *message, size_t message_len)
Definition: tls_record.cpp:208
@ MAX_PLAINTEXT_SIZE
Definition: tls_magic.h:32
void map_remove_if(Pred pred, T &assoc)
Definition: stl_util.h:99
std::vector< uint8_t > to_byte_vector(const std::string &s)
Definition: stl_util.h:23
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
MechanismType type