Botan 3.0.0
Crypto and TLS for C&
tls_cipher_state.cpp
Go to the documentation of this file.
1/*
2* TLS cipher state 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/**
10 * Cipher_State state machine adapted from RFC 8446 7.1.
11 *
12 * 0
13 * |
14 * v
15 * PSK -> HKDF-Extract = Early Secret
16 * |
17 * +-----> Derive-Secret(., "ext binder" | "res binder", "")
18 * | = binder_key
19 * STATE PSK BINDER
20 * This state is reached by constructing the Cipher_State using init_with_psk().
21 * The state can then be further advanced using advance_with_client_hello() once
22 * the initial Client Hello is fully generated.
23 * |
24 * +-----> Derive-Secret(., "c e traffic", ClientHello)
25 * | = client_early_traffic_secret
26 * |
27 * +-----> Derive-Secret(., "e exp master", ClientHello)
28 * | = early_exporter_master_secret
29 * v
30 * Derive-Secret(., "derived", "")
31 * |
32 * *
33 * STATE EARLY TRAFFIC
34 * This state is reached by calling advance_with_client_hello().
35 * In this state the early data traffic secrets are available. TODO: implement early data.
36 * The state can then be further advanced using advance_with_server_hello().
37 * *
38 * |
39 * v
40 * (EC)DHE -> HKDF-Extract = Handshake Secret
41 * |
42 * +-----> Derive-Secret(., "c hs traffic",
43 * | ClientHello...ServerHello)
44 * | = client_handshake_traffic_secret
45 * |
46 * +-----> Derive-Secret(., "s hs traffic",
47 * | ClientHello...ServerHello)
48 * | = server_handshake_traffic_secret
49 * v
50 * Derive-Secret(., "derived", "")
51 * |
52 * *
53 * STATE HANDSHAKE TRAFFIC
54 * This state is reached by constructing Cipher_State using init_with_server_hello() or
55 * advance_with_server_hello(). In this state the handshake traffic secrets are available.
56 * The state can then be further advanced using advance_with_server_finished().
57 * *
58 * |
59 * v
60 * 0 -> HKDF-Extract = Master Secret
61 * |
62 * +-----> Derive-Secret(., "c ap traffic",
63 * | ClientHello...server Finished)
64 * | = client_application_traffic_secret_0
65 * |
66 * +-----> Derive-Secret(., "s ap traffic",
67 * | ClientHello...server Finished)
68 * | = server_application_traffic_secret_0
69 * |
70 * +-----> Derive-Secret(., "exp master",
71 * | ClientHello...server Finished)
72 * | = exporter_master_secret
73 * *
74 * STATE SERVER APPLICATION TRAFFIC
75 * This state is reached by calling advance_with_server_finished(). It allows the server
76 * to send application traffic and the client to receive it. The opposite direction is not
77 * yet possible in this state. The state can then be further advanced using
78 * advance_with_client_finished().
79 * *
80 * |
81 * +-----> Derive-Secret(., "res master",
82 * ClientHello...client Finished)
83 * = resumption_master_secret
84 * STATE COMPLETED
85 * Once this state is reached the handshake is finished, both client and server can exchange
86 * application data and no further cipher state advances are possible.
87 */
88
89#include <limits>
90#include <utility>
91
92#include <botan/internal/tls_cipher_state.h>
93
94#include <botan/aead.h>
95#include <botan/assert.h>
96#include <botan/secmem.h>
97#include <botan/tls_ciphersuite.h>
98#include <botan/hash.h>
99#include <botan/tls_magic.h>
100
101#include <botan/internal/hkdf.h>
102#include <botan/internal/hmac.h>
103#include <botan/internal/loadstor.h>
104
105namespace Botan::TLS {
106
107namespace {
108// RFC 8446 5.3
109// Each AEAD algorithm will specify a range of possible lengths for the
110// per-record nonce, from N_MIN bytes to N_MAX bytes of input [RFC5116].
111// The length of the TLS per-record nonce (iv_length) is set to the
112// larger of 8 bytes and N_MIN for the AEAD algorithm (see [RFC5116],
113// Section 4).
114//
115// N_MIN is 12 for AES_GCM and AES_CCM as per RFC 5116 and also 12 for ChaCha20 per RFC 8439.
116constexpr size_t NONCE_LENGTH = 12;
117}
118
119std::unique_ptr<Cipher_State> Cipher_State::init_with_server_hello(
120 const Connection_Side side,
121 secure_vector<uint8_t>&& shared_secret,
122 const Ciphersuite& cipher,
123 const Transcript_Hash& transcript_hash)
124 {
125 auto cs = std::unique_ptr<Cipher_State>(new Cipher_State(side, cipher.prf_algo()));
126 cs->advance_without_psk();
127 cs->advance_with_server_hello(cipher, std::move(shared_secret), transcript_hash);
128 return cs;
129 }
130
131std::unique_ptr<Cipher_State> Cipher_State::init_with_psk(
132 const Connection_Side side,
133 const Cipher_State::PSK_Type type,
135 const Ciphersuite& cipher)
136 {
137 auto cs = std::unique_ptr<Cipher_State>(new Cipher_State(side, cipher.prf_algo()));
138 cs->advance_with_psk(type, std::move(psk));
139 return cs;
140 }
141
143 {
144 BOTAN_ASSERT_NOMSG(m_state == State::PskBinder);
145
146 zap(m_binder_key);
147
148 // TODO: Currently 0-RTT is not yet implemented, hence we don't derive the
149 // early traffic secret for now.
150 //
151 // const auto client_early_traffic_secret = derive_secret(m_early_secret, "c e traffic", transcript_hash);
152 // derive_write_traffic_key(client_early_traffic_secret);
153
154 m_exporter_master_secret = derive_secret(m_early_secret, "e exp master", transcript_hash);
155
156 m_salt = derive_secret(m_early_secret, "derived", empty_hash());
157 zap(m_early_secret);
158
159 m_state = State::EarlyTraffic;
160 }
161
163 {
164 BOTAN_ASSERT_NOMSG(m_state == State::HandshakeTraffic);
165
166 const auto master_secret = hkdf_extract(secure_vector<uint8_t>(m_hash->output_length(), 0x00));
167
168 auto client_application_traffic_secret = derive_secret(master_secret, "c ap traffic", transcript_hash);
169 auto server_application_traffic_secret = derive_secret(master_secret, "s ap traffic", transcript_hash);
170
171 // Note: the secrets for processing client's application data
172 // are not derived before the client's Finished message
173 // was seen and the handshake can be considered finished.
174 if(m_connection_side == Connection_Side::Server)
175 {
176 derive_write_traffic_key(server_application_traffic_secret);
177 m_read_application_traffic_secret = std::move(client_application_traffic_secret);
178 m_write_application_traffic_secret = std::move(server_application_traffic_secret);
179 }
180 else
181 {
182 derive_read_traffic_key(server_application_traffic_secret);
183 m_read_application_traffic_secret = std::move(server_application_traffic_secret);
184 m_write_application_traffic_secret = std::move(client_application_traffic_secret);
185 }
186
187 m_exporter_master_secret = derive_secret(master_secret, "exp master", transcript_hash);
188
189 m_state = State::ServerApplicationTraffic;
190 }
191
193 {
194 BOTAN_ASSERT_NOMSG(m_state == State::ServerApplicationTraffic);
195
196 zap(m_finished_key);
197 zap(m_peer_finished_key);
198
199 // With the client's Finished message, the handshake is complete and
200 // we can process client application data.
201 if(m_connection_side == Connection_Side::Server)
202 {
203 derive_read_traffic_key(m_read_application_traffic_secret);
204 }
205 else
206 {
207 derive_write_traffic_key(m_write_application_traffic_secret);
208 }
209
210 const auto master_secret = hkdf_extract(secure_vector<uint8_t>(m_hash->output_length(), 0x00));
211
212 m_resumption_master_secret = derive_secret(master_secret, "res master", transcript_hash);
213
214 // This was the final state change; the salt is no longer needed.
215 zap(m_salt);
216
217 m_state = State::Completed;
218 }
219
220namespace {
221
222std::vector<uint8_t> current_nonce(const uint64_t seq_no, const secure_vector<uint8_t>& iv)
223 {
224 // RFC 8446 5.3
225 // The per-record nonce for the AEAD construction is formed as follows:
226 //
227 // 1. The 64-bit record sequence number is encoded in network byte
228 // order and padded to the left with zeros to iv_length.
229 //
230 // 2. The padded sequence number is XORed with either the static
231 // client_write_iv or server_write_iv (depending on the role).
232 std::vector<uint8_t> nonce(NONCE_LENGTH);
233 store_be(seq_no, nonce.data() + (NONCE_LENGTH-sizeof(seq_no)));
234 xor_buf(nonce, iv.data(), iv.size());
235 return nonce;
236 }
237
238}
239
240uint64_t Cipher_State::encrypt_record_fragment(const std::vector<uint8_t>& header, secure_vector<uint8_t>& fragment)
241 {
242 BOTAN_ASSERT_NONNULL(m_encrypt);
243
244 m_encrypt->set_key(m_write_key);
245 m_encrypt->set_associated_data(header);
246 m_encrypt->start(current_nonce(m_write_seq_no, m_write_iv));
247 m_encrypt->finish(fragment);
248
249 return m_write_seq_no++;
250 }
251
252uint64_t Cipher_State::decrypt_record_fragment(const std::vector<uint8_t>& header,
253 secure_vector<uint8_t>& encrypted_fragment)
254 {
255 BOTAN_ASSERT_NONNULL(m_decrypt);
256 BOTAN_ARG_CHECK(encrypted_fragment.size() >= m_decrypt->minimum_final_size(),
257 "fragment too short to decrypt");
258
259 m_decrypt->set_key(m_read_key);
260 m_decrypt->set_associated_data(header);
261 m_decrypt->start(current_nonce(m_read_seq_no, m_read_iv));
262
263 m_decrypt->finish(encrypted_fragment);
264
265 return m_read_seq_no++;
266 }
267
268size_t Cipher_State::encrypt_output_length(const size_t input_length) const
269 {
270 BOTAN_ASSERT_NONNULL(m_encrypt);
271 return m_encrypt->output_length(input_length);
272 }
273
274size_t Cipher_State::decrypt_output_length(const size_t input_length) const
275 {
276 BOTAN_ASSERT_NONNULL(m_decrypt);
277 return m_decrypt->output_length(input_length);
278 }
279
281 {
282 BOTAN_ASSERT_NONNULL(m_decrypt);
283 return m_decrypt->minimum_final_size();
284 }
285
287 {
288 // Client side:
289 // After successfully receiving a Server Hello we expect servers to send
290 // alerts as protected records only, just like they start protecting their
291 // handshake data at this point.
292 if(m_connection_side == Connection_Side::Client && m_state == State::EarlyTraffic)
293 { return true; }
294
295 // Server side:
296 // Servers must expect clients to send unprotected alerts during the hand-
297 // shake. In particular, in the response to the server's first protected
298 // flight. We don't expect the client to send alerts protected under the
299 // early traffic secret.
300 //
301 // TODO: when implementing PSK and/or early data for the server, we might
302 // need to reconsider this decision.
303 if(m_connection_side == Connection_Side::Server &&
304 (m_state == State::HandshakeTraffic ||
305 m_state == State::ServerApplicationTraffic))
306 { return true; }
307
308 return false;
309 }
310
312 {
313 // TODO: when implementing early traffic (0-RTT) this will likely need
314 // to allow `State::EarlyTraffic`.
315
316 if(m_connection_side == Connection_Side::Client && m_state != State::Completed)
317 { return false; }
318
319 if (m_connection_side == Connection_Side::Server && m_state != State::ServerApplicationTraffic && m_state != State::Completed)
320 { return false; }
321
322 return !m_write_key.empty() && !m_write_iv.empty();
323 }
324
326 {
327 // TODO: when implementing early traffic (0-RTT) this will likely need
328 // to allow `State::EarlyTraffic`.
329
330 if(m_connection_side == Connection_Side::Client && m_state != State::ServerApplicationTraffic && m_state != State::Completed)
331 { return false; }
332
333 if(m_connection_side == Connection_Side::Server && m_state != State::Completed)
334 { return false; }
335
336 return !m_read_key.empty() && !m_read_iv.empty();
337 }
338
340 {
341 BOTAN_ASSERT_NONNULL(m_hash);
342 return m_hash->name();
343 }
344
346 {
347 if(!cipher.usable_in_version(Protocol_Version::TLS_V13))
348 return false;
349
350 if(hash_algorithm() != cipher.prf_algo())
351 return false;
352
353 BOTAN_ASSERT_NOMSG((m_encrypt == nullptr) == (m_decrypt == nullptr));
354 // TODO: Find a better way to check that the instantiated cipher algorithm
355 // is compatible with the one required by the cipher suite.
356 // AEAD_Mode::create() sets defaults the tag length to 16 which is then
357 // reported via AEAD_Mode::name() and hinders the trivial string comparison.
358 if(m_encrypt && m_encrypt->name() != cipher.cipher_algo() &&
359 m_encrypt->name() != cipher.cipher_algo() + "(16)")
360 return false;
361
362 return true;
363 }
364
365std::vector<uint8_t> Cipher_State::psk_binder_mac(const Transcript_Hash& transcript_hash_with_truncated_client_hello)
366 {
367 BOTAN_ASSERT_NOMSG(m_state == State::PskBinder);
368
369 auto hmac = HMAC(m_hash->new_object());
370 hmac.set_key(m_binder_key);
371 hmac.update(transcript_hash_with_truncated_client_hello);
372 return hmac.final_stdvec();
373 }
374
375std::vector<uint8_t> Cipher_State::finished_mac(const Transcript_Hash& transcript_hash) const
376 {
377 BOTAN_ASSERT_NOMSG(m_connection_side != Connection_Side::Server || m_state == State::HandshakeTraffic);
378 BOTAN_ASSERT_NOMSG(m_connection_side != Connection_Side::Client || m_state == State::ServerApplicationTraffic);
379 BOTAN_ASSERT_NOMSG(!m_finished_key.empty());
380
381 auto hmac = HMAC(m_hash->new_object());
382 hmac.set_key(m_finished_key);
383 hmac.update(transcript_hash);
384 return hmac.final_stdvec();
385 }
386
388 const std::vector<uint8_t>& peer_mac) const
389 {
390 BOTAN_ASSERT_NOMSG(m_connection_side != Connection_Side::Server || m_state == State::ServerApplicationTraffic);
391 BOTAN_ASSERT_NOMSG(m_connection_side != Connection_Side::Client || m_state == State::HandshakeTraffic);
392 BOTAN_ASSERT_NOMSG(!m_peer_finished_key.empty());
393
394 auto hmac = HMAC(m_hash->new_object());
395 hmac.set_key(m_peer_finished_key);
396 hmac.update(transcript_hash);
397 return hmac.verify_mac(peer_mac);
398 }
399
400secure_vector<uint8_t> Cipher_State::psk(const Ticket_Nonce& nonce) const
401 {
402 BOTAN_ASSERT_NOMSG(m_state == State::Completed);
403
404 return derive_secret(m_resumption_master_secret, "resumption", nonce.get());
405 }
406
408 {
409 BOTAN_STATE_CHECK(m_state == State::Completed);
410 if(m_ticket_nonce == std::numeric_limits<decltype(m_ticket_nonce)>::max())
411 {
412 throw Botan::Invalid_State("ticket nonce pool exhausted");
413 }
414
415 Ticket_Nonce retval(std::vector<uint8_t>(sizeof(m_ticket_nonce)));
416 store_be(m_ticket_nonce++, retval.data());
417
418 return retval;
419 }
420
422 std::string_view context,
423 size_t length) const
424 {
426
427 m_hash->update(context);
428 const auto context_hash = m_hash->final_stdvec();
429 return hkdf_expand_label(derive_secret(m_exporter_master_secret, label, empty_hash()),
430 "exporter", context_hash, length);
431 }
432
433
434namespace {
435
436std::unique_ptr<MessageAuthenticationCode> create_hmac(std::string_view hash)
437 {
438 return std::make_unique<HMAC>(HashFunction::create_or_throw(hash));
439 }
440
441}
442
443Cipher_State::Cipher_State(Connection_Side whoami, std::string_view hash_function)
444 : m_state(State::Uninitialized)
445 , m_connection_side(whoami)
446 , m_extract(std::make_unique<HKDF_Extract>(create_hmac(hash_function)))
447 , m_expand(std::make_unique<HKDF_Expand>(create_hmac(hash_function)))
448 , m_hash(HashFunction::create_or_throw(hash_function))
449 , m_salt(m_hash->output_length(), 0x00)
450 , m_write_seq_no(0)
451 , m_read_seq_no(0)
452 , m_ticket_nonce(0) {}
453
455
456void Cipher_State::advance_without_psk()
457 {
458 BOTAN_ASSERT_NOMSG(m_state == State::Uninitialized);
459
460 // We are not using `m_early_secret` here because the secret won't be needed
461 // in any further state advancement methods.
462 const auto early_secret = hkdf_extract(secure_vector<uint8_t>(m_hash->output_length(), 0x00));
463 m_salt = derive_secret(early_secret, "derived", empty_hash());
464
465 // Without PSK we skip the `PskBinder` state and go right to `EarlyTraffic`.
466 m_state = State::EarlyTraffic;
467 }
468
469void Cipher_State::advance_with_psk(PSK_Type type, secure_vector<uint8_t>&& psk)
470 {
471 BOTAN_ASSERT_NOMSG(m_state == State::Uninitialized);
472
473 m_early_secret = hkdf_extract(std::move(psk));
474
475 const char* binder_label =
476 (type == PSK_Type::Resumption)
477 ? "res binder"
478 : "ext binder";
479
480 // RFC 8446 4.2.11.2
481 // The PskBinderEntry is computed in the same way as the Finished message
482 // [...] but with the BaseKey being the binder_key derived via the key
483 // schedule from the corresponding PSK which is being offered.
484 //
485 // Hence we are doing the binder key derivation and expansion in one go.
486 const auto binder_key = derive_secret(m_early_secret, binder_label, empty_hash());
487 m_binder_key = hkdf_expand_label(binder_key, "finished", {}, m_hash->output_length());
488
489 m_state = State::PskBinder;
490 }
491
493 secure_vector<uint8_t>&& shared_secret,
494 const Transcript_Hash& transcript_hash)
495 {
496 BOTAN_ASSERT_NOMSG(m_state == State::EarlyTraffic);
497 BOTAN_ASSERT_NOMSG(!m_encrypt);
498 BOTAN_ASSERT_NOMSG(!m_decrypt);
500
503
504 const auto handshake_secret = hkdf_extract(std::move(shared_secret));
505
506 const auto client_handshake_traffic_secret = derive_secret(handshake_secret, "c hs traffic", transcript_hash);
507 const auto server_handshake_traffic_secret = derive_secret(handshake_secret, "s hs traffic", transcript_hash);
508
509 if(m_connection_side == Connection_Side::Server)
510 {
511 derive_read_traffic_key(client_handshake_traffic_secret, true);
512 derive_write_traffic_key(server_handshake_traffic_secret, true);
513 }
514 else
515 {
516 derive_read_traffic_key(server_handshake_traffic_secret, true);
517 derive_write_traffic_key(client_handshake_traffic_secret, true);
518 }
519
520 m_salt = derive_secret(handshake_secret, "derived", empty_hash());
521
522 m_state = State::HandshakeTraffic;
523 }
524
525void Cipher_State::derive_write_traffic_key(const secure_vector<uint8_t>& traffic_secret,
526 const bool handshake_traffic_secret)
527 {
528 BOTAN_ASSERT_NONNULL(m_encrypt);
529
530 m_write_key = hkdf_expand_label(traffic_secret, "key", {}, m_encrypt->minimum_keylength());
531 m_write_iv = hkdf_expand_label(traffic_secret, "iv", {}, NONCE_LENGTH);
532 m_write_seq_no = 0;
533
534 if(handshake_traffic_secret)
535 {
536 // Key derivation for the MAC in the "Finished" handshake message as described in RFC 8446 4.4.4
537 // (will be cleared in advance_with_server_finished())
538 m_finished_key = hkdf_expand_label(traffic_secret, "finished", {}, m_hash->output_length());
539 }
540 }
541
542void Cipher_State::derive_read_traffic_key(const secure_vector<uint8_t>& traffic_secret,
543 const bool handshake_traffic_secret)
544 {
545 BOTAN_ASSERT_NONNULL(m_encrypt);
546
547 m_read_key = hkdf_expand_label(traffic_secret, "key", {}, m_encrypt->minimum_keylength());
548 m_read_iv = hkdf_expand_label(traffic_secret, "iv", {}, NONCE_LENGTH);
549 m_read_seq_no = 0;
550
551 if(handshake_traffic_secret)
552 {
553 // Key derivation for the MAC in the "Finished" handshake message as described in RFC 8446 4.4.4
554 // (will be cleared in advance_with_client_finished())
555 m_peer_finished_key = hkdf_expand_label(traffic_secret, "finished", {}, m_hash->output_length());
556 }
557 }
558
559secure_vector<uint8_t> Cipher_State::hkdf_extract(secure_vector<uint8_t>&& ikm) const
560 {
561 return m_extract->derive_key(m_hash->output_length(), ikm, m_salt, std::vector<uint8_t>());
562 }
563
564secure_vector<uint8_t> Cipher_State::hkdf_expand_label(
565 const secure_vector<uint8_t>& secret,
566 std::string_view label,
567 const std::vector<uint8_t>& context,
568 const size_t length) const
569 {
570 // assemble (serialized) HkdfLabel
571 secure_vector<uint8_t> hkdf_label;
572 hkdf_label.reserve(2 /* length */ +
573 (label.size() +
574 6 /* 'tls13 ' */ +
575 1 /* length field*/) +
576 (context.size() +
577 1 /* length field*/));
578
579 // length
580 BOTAN_ARG_CHECK(length <= std::numeric_limits<uint16_t>::max(), "invalid length");
581 const auto len = static_cast<uint16_t>(length);
582 hkdf_label.push_back(get_byte<0>(len));
583 hkdf_label.push_back(get_byte<1>(len));
584
585 // label
586 const std::string prefix = "tls13 ";
587 BOTAN_ARG_CHECK(prefix.size() + label.size() <= 255, "label too large");
588 hkdf_label.push_back(static_cast<uint8_t>(prefix.size() + label.size()));
589 hkdf_label.insert(hkdf_label.end(), prefix.cbegin(), prefix.cend());
590 hkdf_label.insert(hkdf_label.end(), label.cbegin(), label.cend());
591
592 // context
593 BOTAN_ARG_CHECK(context.size() <= 255, "context too large");
594 hkdf_label.push_back(static_cast<uint8_t>(context.size()));
595 hkdf_label.insert(hkdf_label.end(), context.cbegin(), context.cend());
596
597 // HKDF-Expand
598 return m_expand->derive_key(length, secret, hkdf_label, std::vector<uint8_t>() /* just pleasing botan's interface */);
599 }
600
601secure_vector<uint8_t> Cipher_State::derive_secret(
602 const secure_vector<uint8_t>& secret,
603 std::string_view label,
604 const Transcript_Hash& messages_hash) const
605 {
606 return hkdf_expand_label(secret, label, messages_hash, m_hash->output_length());
607 }
608
609std::vector<uint8_t> Cipher_State::empty_hash() const
610 {
611 m_hash->update("");
612 return m_hash->final_stdvec();
613 }
614
616 {
617 BOTAN_ASSERT_NOMSG(m_state == State::ServerApplicationTraffic ||
618 m_state == State::Completed);
619
620 m_read_application_traffic_secret =
621 hkdf_expand_label(m_read_application_traffic_secret, "traffic upd", {}, m_hash->output_length());
622
623 derive_read_traffic_key(m_read_application_traffic_secret);
624 }
625
627 {
628 BOTAN_ASSERT_NOMSG(m_state == State::ServerApplicationTraffic ||
629 m_state == State::Completed);
630 m_write_application_traffic_secret =
631 hkdf_expand_label(m_write_application_traffic_secret, "traffic upd", {}, m_hash->output_length());
632
633 derive_write_traffic_key(m_write_application_traffic_secret);
634 }
635
637 {
638 zap(m_read_key);
639 zap(m_read_iv);
640 zap(m_read_application_traffic_secret);
641 }
642
644 {
645 zap(m_write_key);
646 zap(m_write_iv);
647 zap(m_write_application_traffic_secret);
648 }
649
650} // namespace Botan::TLS
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:67
#define BOTAN_STATE_CHECK(expr)
Definition: assert.h:48
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:106
#define BOTAN_ARG_CHECK(expr, msg)
Definition: assert.h:36
static std::unique_ptr< AEAD_Mode > create_or_throw(std::string_view algo, Cipher_Dir direction, std::string_view provider="")
Definition: aead.cpp:42
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition: hash.cpp:320
bool can_decrypt_application_traffic() const
size_t decrypt_output_length(const size_t input_length) const
uint64_t decrypt_record_fragment(const std::vector< uint8_t > &header, secure_vector< uint8_t > &encrypted_fragment)
static std::unique_ptr< Cipher_State > init_with_psk(const Connection_Side side, const PSK_Type type, secure_vector< uint8_t > &&psk, const Ciphersuite &cipher)
void advance_with_client_hello(const Transcript_Hash &transcript_hash)
size_t minimum_decryption_input_length() const
void advance_with_server_finished(const Transcript_Hash &transcript_hash)
bool must_expect_unprotected_alert_traffic() const
void advance_with_client_finished(const Transcript_Hash &transcript_hash)
bool verify_peer_finished_mac(const Transcript_Hash &transcript_hash, const std::vector< uint8_t > &peer_mac) const
std::string hash_algorithm() const
uint64_t encrypt_record_fragment(const std::vector< uint8_t > &header, secure_vector< uint8_t > &fragment)
static std::unique_ptr< Cipher_State > init_with_server_hello(const Connection_Side side, secure_vector< uint8_t > &&shared_secret, const Ciphersuite &cipher, const Transcript_Hash &transcript_hash)
secure_vector< uint8_t > psk(const Ticket_Nonce &nonce) const
void advance_with_server_hello(const Ciphersuite &cipher, secure_vector< uint8_t > &&shared_secret, const Transcript_Hash &transcript_hash)
bool is_compatible_with(const Ciphersuite &cipher) const
size_t encrypt_output_length(const size_t input_length) const
std::vector< uint8_t > psk_binder_mac(const Transcript_Hash &transcript_hash_with_truncated_client_hello)
secure_vector< uint8_t > export_key(std::string_view label, std::string_view context, size_t length) const
bool can_encrypt_application_traffic() const
std::vector< uint8_t > finished_mac(const Transcript_Hash &transcript_hash) const
bool usable_in_version(Protocol_Version version) const
std::string prf_algo() const
std::string cipher_algo() const
std::vector< uint8_t > Transcript_Hash
Definition: tls_magic.h:83
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:129
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:255
constexpr void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:449
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:64
Definition: bigint.h:1092