Botan 3.12.0
Crypto and TLS for C&
Botan::TLS::Cipher_State Class Reference

#include <tls_cipher_state.h>

Public Types

enum class  PSK_Type : uint8_t { Resumption , External , Imported }

Public Member Functions

void advance_with_client_finished (const Transcript_Hash &transcript_hash)
void advance_with_client_hello (const Transcript_Hash &transcript_hash, const Secret_Logger &channel)
void advance_with_server_finished (const Transcript_Hash &transcript_hash, const Secret_Logger &channel)
void advance_with_server_hello (const Ciphersuite &cipher, secure_vector< uint8_t > &&shared_secret, const Transcript_Hash &transcript_hash, const Secret_Logger &channel)
bool can_decrypt_application_traffic () const
bool can_encrypt_application_traffic () const
bool can_export_keys () const
 Cipher_State (Cipher_State &&other)=delete
 Cipher_State (const Cipher_State &other)=delete
void clear_read_keys ()
void clear_write_keys ()
size_t decrypt_output_length (size_t input_length) const
uint64_t decrypt_record_fragment (const std::vector< uint8_t > &header, secure_vector< uint8_t > &encrypted_fragment)
size_t encrypt_output_length (size_t input_length) const
uint64_t encrypt_record_fragment (const std::vector< uint8_t > &header, secure_vector< uint8_t > &fragment)
secure_vector< uint8_t > export_key (std::string_view label, std::string_view context, size_t length) const
std::vector< uint8_t > finished_mac (const Transcript_Hash &transcript_hash) const
std::string hash_algorithm () const
bool is_compatible_with (const Ciphersuite &cipher) const
size_t minimum_decryption_input_length () const
bool must_expect_unprotected_alert_traffic () const
Ticket_Nonce next_ticket_nonce ()
Cipher_Stateoperator= (Cipher_State &&other)=delete
Cipher_Stateoperator= (const Cipher_State &other)=delete
secure_vector< uint8_t > psk (const Ticket_Nonce &nonce) const
std::vector< uint8_t > psk_binder_mac (const Transcript_Hash &transcript_hash_with_truncated_client_hello) const
void update_read_keys (const Secret_Logger &channel)
void update_write_keys (const Secret_Logger &channel)
bool verify_peer_finished_mac (const Transcript_Hash &transcript_hash, const std::vector< uint8_t > &peer_mac) const
 ~Cipher_State ()

Static Public Member Functions

static std::unique_ptr< Cipher_Stateinit_with_psk (Connection_Side side, PSK_Type type, secure_vector< uint8_t > &&psk, std::string_view prf_algo)
static std::unique_ptr< Cipher_Stateinit_with_server_hello (Connection_Side side, secure_vector< uint8_t > &&shared_secret, const Ciphersuite &cipher, const Transcript_Hash &transcript_hash, const Secret_Logger &channel)

Detailed Description

This class implements the key schedule for TLS 1.3 as described in RFC 8446 7.1.

Internally, it reflects the state machine pictured in the same RFC section. It provides the following entry points and state advancement methods that each facilitate certain cryptographic functionality:

While encrypting and decrypting records (RFC 8446 5.2) Cipher_State internally keeps track of the current sequence numbers (RFC 8446 5.3) to calculate the correct Per-Record Nonce. Sequence numbers are reset appropriately, whenever traffic secrets change.

Handshake finished MAC calculation and verification is described in RFC 8446 4.4.4.

PSKs calculation is described in RFC 8446 4.6.1.

Definition at line 61 of file tls_cipher_state.h.

Member Enumeration Documentation

◆ PSK_Type

enum class Botan::TLS::Cipher_State::PSK_Type : uint8_t
strong
Enumerator
Resumption 
External 
Imported 

Definition at line 63 of file tls_cipher_state.h.

63 : uint8_t {
64 Resumption, // RFC 8446
65 External, // RFC 8446
66 Imported, // RFC 9258 PSK importer - uses "imp binder" label
67 };

Constructor & Destructor Documentation

◆ ~Cipher_State()

Botan::TLS::Cipher_State::~Cipher_State ( )
default

◆ Cipher_State() [1/2]

Botan::TLS::Cipher_State::Cipher_State ( const Cipher_State & other)
delete

◆ Cipher_State() [2/2]

Botan::TLS::Cipher_State::Cipher_State ( Cipher_State && other)
delete

References Cipher_State().

Member Function Documentation

◆ advance_with_client_finished()

void Botan::TLS::Cipher_State::advance_with_client_finished ( const Transcript_Hash & transcript_hash)

Transition to the final internal state allowing to create resumptions.

Definition at line 205 of file tls_cipher_state.cpp.

205 {
206 BOTAN_ASSERT_NOMSG(m_state == State::ServerApplicationTraffic);
207
208 zap(m_finished_key);
209 zap(m_peer_finished_key);
210
211 // With the client's Finished message, the handshake is complete and
212 // we can process client application data.
213 if(m_connection_side == Connection_Side::Server) {
214 derive_read_traffic_key(m_read_application_traffic_secret);
215 } else {
216 derive_write_traffic_key(m_write_application_traffic_secret);
217 }
218
219 const auto master_secret = hkdf_extract(secure_vector<uint8_t>(m_hash->output_length(), 0x00));
220
221 m_resumption_master_secret = derive_secret(master_secret, "res master", transcript_hash);
222
223 // This was the final state change; the salt is no longer needed.
224 zap(m_salt);
225
226 m_state = State::Completed;
227}
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
void zap(std::vector< T, Alloc > &vec)
Definition secmem.h:157
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:68

References BOTAN_ASSERT_NOMSG, Botan::TLS::Server, and Botan::zap().

Referenced by operator=().

◆ advance_with_client_hello()

void Botan::TLS::Cipher_State::advance_with_client_hello ( const Transcript_Hash & transcript_hash,
const Secret_Logger & channel )

Transition internal secrets/keys for transporting early application data. Note that this state transition is legal only for handshakes using PSK.

Definition at line 141 of file tls_cipher_state.cpp.

141 {
142 BOTAN_ASSERT_NOMSG(m_state == State::PskBinder);
143
144 zap(m_binder_key);
145
146 // TODO: Currently 0-RTT is not yet implemented, hence we don't derive the
147 // early traffic secret for now.
148 //
149 // const auto client_early_traffic_secret = derive_secret(m_early_secret, "c e traffic", transcript_hash);
150 // derive_write_traffic_key(client_early_traffic_secret);
151
152 m_exporter_master_secret = derive_secret(m_early_secret, "e exp master", transcript_hash);
153
154 // draft-thomson-tls-keylogfile-00 Section 3.1
155 // An implementation of TLS 1.3 use the label
156 // "EARLY_EXPORTER_MASTER_SECRET" to identify the secret that is using for
157 // early exporters
158 logger.maybe_log_secret("EARLY_EXPORTER_MASTER_SECRET", m_exporter_master_secret);
159
160 m_salt = derive_secret(m_early_secret, "derived", empty_hash());
161 zap(m_early_secret);
162
163 m_state = State::EarlyTraffic;
164}

References BOTAN_ASSERT_NOMSG, Botan::TLS::Secret_Logger::maybe_log_secret(), and Botan::zap().

Referenced by operator=().

◆ advance_with_server_finished()

void Botan::TLS::Cipher_State::advance_with_server_finished ( const Transcript_Hash & transcript_hash,
const Secret_Logger & channel )

Transition internal secrets/keys for transporting application data.

Definition at line 166 of file tls_cipher_state.cpp.

166 {
167 BOTAN_ASSERT_NOMSG(m_state == State::HandshakeTraffic);
168
169 const auto master_secret = hkdf_extract(secure_vector<uint8_t>(m_hash->output_length(), 0x00));
170
171 auto client_application_traffic_secret = derive_secret(master_secret, "c ap traffic", transcript_hash);
172 auto server_application_traffic_secret = derive_secret(master_secret, "s ap traffic", transcript_hash);
173
174 // draft-thomson-tls-keylogfile-00 Section 3.1
175 // An implementation of TLS 1.3 use the label "CLIENT_TRAFFIC_SECRET_0"
176 // and "SERVER_TRAFFIC_SECRET_0" to identify the secrets are using to
177 // protect the connection.
178 logger.maybe_log_secret("CLIENT_TRAFFIC_SECRET_0", client_application_traffic_secret);
179 logger.maybe_log_secret("SERVER_TRAFFIC_SECRET_0", server_application_traffic_secret);
180
181 // Note: the secrets for processing client's application data
182 // are not derived before the client's Finished message
183 // was seen and the handshake can be considered finished.
184 if(m_connection_side == Connection_Side::Server) {
185 derive_write_traffic_key(server_application_traffic_secret);
186 m_read_application_traffic_secret = std::move(client_application_traffic_secret);
187 m_write_application_traffic_secret = std::move(server_application_traffic_secret);
188 } else {
189 derive_read_traffic_key(server_application_traffic_secret);
190 m_read_application_traffic_secret = std::move(server_application_traffic_secret);
191 m_write_application_traffic_secret = std::move(client_application_traffic_secret);
192 }
193
194 m_exporter_master_secret = derive_secret(master_secret, "exp master", transcript_hash);
195
196 // draft-thomson-tls-keylogfile-00 Section 3.1
197 // An implementation of TLS 1.3 use the label "EXPORTER_SECRET" to
198 // identify the secret that is used in generating exporters(rfc8446
199 // Section 7.5).
200 logger.maybe_log_secret("EXPORTER_SECRET", m_exporter_master_secret);
201
202 m_state = State::ServerApplicationTraffic;
203}

References BOTAN_ASSERT_NOMSG, Botan::TLS::Secret_Logger::maybe_log_secret(), and Botan::TLS::Server.

Referenced by operator=().

◆ advance_with_server_hello()

void Botan::TLS::Cipher_State::advance_with_server_hello ( const Ciphersuite & cipher,
secure_vector< uint8_t > && shared_secret,
const Transcript_Hash & transcript_hash,
const Secret_Logger & channel )

Transition internal secrets/keys for transporting handshake data.

Definition at line 516 of file tls_cipher_state.cpp.

519 {
520 BOTAN_ASSERT_NOMSG(m_state == State::EarlyTraffic);
521 BOTAN_ASSERT_NOMSG(!m_encrypt);
522 BOTAN_ASSERT_NOMSG(!m_decrypt);
524
525 m_encrypt = AEAD_Mode::create_or_throw(cipher.cipher_algo(), Cipher_Dir::Encryption);
526 m_decrypt = AEAD_Mode::create_or_throw(cipher.cipher_algo(), Cipher_Dir::Decryption);
527
528 const auto handshake_secret = hkdf_extract(std::move(shared_secret));
529
530 const auto client_handshake_traffic_secret = derive_secret(handshake_secret, "c hs traffic", transcript_hash);
531 const auto server_handshake_traffic_secret = derive_secret(handshake_secret, "s hs traffic", transcript_hash);
532
533 // draft-thomson-tls-keylogfile-00 Section 3.1
534 // An implementation of TLS 1.3 use the label
535 // "CLIENT_HANDSHAKE_TRAFFIC_SECRET" and "SERVER_HANDSHAKE_TRAFFIC_SECRET"
536 // to identify the secrets are using to protect handshake messages.
537 logger.maybe_log_secret("CLIENT_HANDSHAKE_TRAFFIC_SECRET", client_handshake_traffic_secret);
538 logger.maybe_log_secret("SERVER_HANDSHAKE_TRAFFIC_SECRET", server_handshake_traffic_secret);
539
540 if(m_connection_side == Connection_Side::Server) {
541 derive_read_traffic_key(client_handshake_traffic_secret, true);
542 derive_write_traffic_key(server_handshake_traffic_secret, true);
543 } else {
544 derive_read_traffic_key(server_handshake_traffic_secret, true);
545 derive_write_traffic_key(client_handshake_traffic_secret, true);
546 }
547
548 m_salt = derive_secret(handshake_secret, "derived", empty_hash());
549
550 m_state = State::HandshakeTraffic;
551}
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
static std::unique_ptr< AEAD_Mode > create_or_throw(std::string_view algo, Cipher_Dir direction, std::string_view provider="")
Definition aead.cpp:49
bool is_compatible_with(const Ciphersuite &cipher) const

References BOTAN_ASSERT_NOMSG, BOTAN_STATE_CHECK, Botan::TLS::Ciphersuite::cipher_algo(), Botan::AEAD_Mode::create_or_throw(), Botan::Decryption, Botan::Encryption, is_compatible_with(), Botan::TLS::Secret_Logger::maybe_log_secret(), and Botan::TLS::Server.

Referenced by operator=().

◆ can_decrypt_application_traffic()

bool Botan::TLS::Cipher_State::can_decrypt_application_traffic ( ) const

Indicates whether the appropriate secrets to decrypt application traffic are available

Definition at line 339 of file tls_cipher_state.cpp.

339 {
340 // TODO: when implementing early traffic (0-RTT) this will likely need
341 // to allow `State::EarlyTraffic`.
342
343 if(m_connection_side == Connection_Side::Client && m_state != State::ServerApplicationTraffic &&
344 m_state != State::Completed) {
345 return false;
346 }
347
348 if(m_connection_side == Connection_Side::Server && m_state != State::Completed) {
349 return false;
350 }
351
352 return !m_read_key.empty() && !m_read_iv.empty();
353}

References Botan::TLS::Client, and Botan::TLS::Server.

◆ can_encrypt_application_traffic()

bool Botan::TLS::Cipher_State::can_encrypt_application_traffic ( ) const

Indicates whether the appropriate secrets to encrypt application traffic are available

Definition at line 323 of file tls_cipher_state.cpp.

323 {
324 // TODO: when implementing early traffic (0-RTT) this will likely need
325 // to allow `State::EarlyTraffic`.
326
327 if(m_connection_side == Connection_Side::Client && m_state != State::Completed) {
328 return false;
329 }
330
331 if(m_connection_side == Connection_Side::Server && m_state != State::ServerApplicationTraffic &&
332 m_state != State::Completed) {
333 return false;
334 }
335
336 return !m_write_key.empty() && !m_write_iv.empty();
337}

References Botan::TLS::Client, and Botan::TLS::Server.

◆ can_export_keys()

bool Botan::TLS::Cipher_State::can_export_keys ( ) const
inline

Indicates whether the appropriate secrets to export keys are available

Definition at line 203 of file tls_cipher_state.h.

203 {
204 return (m_state == State::EarlyTraffic || m_state == State::ServerApplicationTraffic ||
205 m_state == State::Completed) &&
206 !m_exporter_master_secret.empty();
207 }

Referenced by export_key().

◆ clear_read_keys()

void Botan::TLS::Cipher_State::clear_read_keys ( )

Remove handshake/traffic secrets for decrypting data from peer

Definition at line 661 of file tls_cipher_state.cpp.

661 {
662 zap(m_read_key);
663 zap(m_read_iv);
664 zap(m_read_application_traffic_secret);
665}

References Botan::zap().

◆ clear_write_keys()

void Botan::TLS::Cipher_State::clear_write_keys ( )

Remove handshake/traffic secrets for encrypting data

Definition at line 667 of file tls_cipher_state.cpp.

667 {
668 zap(m_write_key);
669 zap(m_write_iv);
670 zap(m_write_application_traffic_secret);
671}

References Botan::zap().

◆ decrypt_output_length()

size_t Botan::TLS::Cipher_State::decrypt_output_length ( size_t input_length) const
Returns
number of bytes needed to decrypt input_length bytes

Definition at line 288 of file tls_cipher_state.cpp.

288 {
289 BOTAN_ASSERT_NONNULL(m_decrypt);
290 return m_decrypt->output_length(input_length);
291}
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114

References BOTAN_ASSERT_NONNULL.

Referenced by Botan::TLS::Record_Layer::next_record(), and operator=().

◆ decrypt_record_fragment()

uint64_t Botan::TLS::Cipher_State::decrypt_record_fragment ( const std::vector< uint8_t > & header,
secure_vector< uint8_t > & encrypted_fragment )

Decrypt a TLS record fragment (RFC 8446 5.2 – TLSCiphertext.encrypted_record) using the currently available traffic secret keys and the current sequence number. This will internally increment the sequence number. Hence, multiple calls with the same input will not produce the same result.

Returns
the sequence number of the decrypted record

Definition at line 264 of file tls_cipher_state.cpp.

265 {
266 BOTAN_ASSERT_NONNULL(m_decrypt);
267 BOTAN_ARG_CHECK(encrypted_fragment.size() >= m_decrypt->minimum_final_size(), "fragment too short to decrypt");
268
269 // RFC 8446 5.3
270 // Sequence numbers MUST NOT wrap.
271 if(m_read_seq_no == std::numeric_limits<uint64_t>::max()) {
272 throw Invalid_State("TLS read sequence number overflow");
273 }
274
275 m_decrypt->set_associated_data(header);
276 m_decrypt->start(current_nonce(m_read_seq_no, m_read_iv));
277
278 m_decrypt->finish(encrypted_fragment);
279
280 return m_read_seq_no++;
281}
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33

References BOTAN_ARG_CHECK, and BOTAN_ASSERT_NONNULL.

Referenced by Botan::TLS::Record_Layer::next_record(), and operator=().

◆ encrypt_output_length()

size_t Botan::TLS::Cipher_State::encrypt_output_length ( size_t input_length) const
Returns
number of bytes needed to encrypt input_length bytes

Definition at line 283 of file tls_cipher_state.cpp.

283 {
284 BOTAN_ASSERT_NONNULL(m_encrypt);
285 return m_encrypt->output_length(input_length);
286}

References BOTAN_ASSERT_NONNULL.

Referenced by operator=(), and Botan::TLS::Record_Layer::prepare_records().

◆ encrypt_record_fragment()

uint64_t Botan::TLS::Cipher_State::encrypt_record_fragment ( const std::vector< uint8_t > & header,
secure_vector< uint8_t > & fragment )

Encrypt a TLS record fragment (RFC 8446 5.2 – TLSInnerPlaintext) using the currently available traffic secret keys and the current sequence number. This will internally increment the sequence number. Hence, multiple calls with the same input will not produce the same result.

Returns
the sequence number of the encrypted record

Definition at line 248 of file tls_cipher_state.cpp.

248 {
249 BOTAN_ASSERT_NONNULL(m_encrypt);
250
251 // RFC 8446 5.3
252 // Sequence numbers MUST NOT wrap.
253 if(m_write_seq_no == std::numeric_limits<uint64_t>::max()) {
254 throw Invalid_State("TLS write sequence number overflow");
255 }
256
257 m_encrypt->set_associated_data(header);
258 m_encrypt->start(current_nonce(m_write_seq_no, m_write_iv));
259 m_encrypt->finish(fragment);
260
261 return m_write_seq_no++;
262}

References BOTAN_ASSERT_NONNULL.

Referenced by operator=(), and Botan::TLS::Record_Layer::prepare_records().

◆ export_key()

secure_vector< uint8_t > Botan::TLS::Cipher_State::export_key ( std::string_view label,
std::string_view context,
size_t length ) const

Derive key material to export (RFC 8446 7.5 and RFC 5705)

TODO: this does not yet support key export based on the early_exporter_master_secret.

RFC 8446 7.5 Implementations MUST use the exporter_master_secret unless explicitly specified by the application. The early_exporter_master_secret is defined for use in settings where an exporter is needed for 0-RTT data. A separate interface for the early exporter is RECOMMENDED [...].

Parameters
labela disambiguating label string
contexta per-association context value
lengththe length of the desired key in bytes
Returns
key of length bytes

Definition at line 442 of file tls_cipher_state.cpp.

442 {
444
445 m_hash->update(context);
446 const auto context_hash = m_hash->final_stdvec();
447 return hkdf_expand_label(
448 derive_secret(m_exporter_master_secret, label, empty_hash()), "exporter", context_hash, length);
449}

References BOTAN_ASSERT_NOMSG, and can_export_keys().

Referenced by operator=().

◆ finished_mac()

std::vector< uint8_t > Botan::TLS::Cipher_State::finished_mac ( const Transcript_Hash & transcript_hash) const

Calculate the MAC for a TLS "Finished" handshake message (RFC 8446 4.4.4)

Definition at line 396 of file tls_cipher_state.cpp.

396 {
397 BOTAN_ASSERT_NOMSG(m_connection_side != Connection_Side::Server || m_state == State::HandshakeTraffic);
398 BOTAN_ASSERT_NOMSG(m_connection_side != Connection_Side::Client || m_state == State::ServerApplicationTraffic);
399 BOTAN_ASSERT_NOMSG(!m_finished_key.empty());
400
401 auto hmac = HMAC(m_hash->new_object());
402 hmac.set_key(m_finished_key);
403 hmac.update(transcript_hash);
404 return hmac.final_stdvec();
405}

References BOTAN_ASSERT_NOMSG, Botan::TLS::Client, and Botan::TLS::Server.

Referenced by Botan::TLS::Finished_13::Finished_13(), and operator=().

◆ hash_algorithm()

std::string Botan::TLS::Cipher_State::hash_algorithm ( ) const

The name of the hash algorithm used for the KDF in this cipher suite

Definition at line 355 of file tls_cipher_state.cpp.

355 {
356 BOTAN_ASSERT_NONNULL(m_hash);
357 return m_hash->name();
358}

References BOTAN_ASSERT_NONNULL.

Referenced by is_compatible_with().

◆ init_with_psk()

std::unique_ptr< Cipher_State > Botan::TLS::Cipher_State::init_with_psk ( Connection_Side side,
const Cipher_State::PSK_Type type,
secure_vector< uint8_t > && psk,
std::string_view prf_algo )
static

Construct a Cipher_State from a Pre-Shared-Key.

Definition at line 132 of file tls_cipher_state.cpp.

135 {
136 auto cs = std::unique_ptr<Cipher_State>(new Cipher_State(side, prf_algo));
137 cs->advance_with_psk(type, std::move(psk));
138 return cs;
139}
Cipher_State(const Cipher_State &other)=delete
secure_vector< uint8_t > psk(const Ticket_Nonce &nonce) const

References Cipher_State(), and psk().

Referenced by operator=().

◆ init_with_server_hello()

std::unique_ptr< Cipher_State > Botan::TLS::Cipher_State::init_with_server_hello ( Connection_Side side,
secure_vector< uint8_t > && shared_secret,
const Ciphersuite & cipher,
const Transcript_Hash & transcript_hash,
const Secret_Logger & channel )
static

Construct a Cipher_State after receiving a server hello message.

Definition at line 121 of file tls_cipher_state.cpp.

125 {
126 auto cs = std::unique_ptr<Cipher_State>(new Cipher_State(side, cipher.prf_algo()));
127 cs->advance_without_psk();
128 cs->advance_with_server_hello(cipher, std::move(shared_secret), transcript_hash, logger);
129 return cs;
130}

References Cipher_State(), and Botan::TLS::Ciphersuite::prf_algo().

Referenced by operator=().

◆ is_compatible_with()

bool Botan::TLS::Cipher_State::is_compatible_with ( const Ciphersuite & cipher) const
Returns
true if the selected cipher primitives are compatible with the cipher suite.

Note that cipher suites are considered "compatible" as long as the already selected cipher primitives in this cipher state are compatible.

Definition at line 360 of file tls_cipher_state.cpp.

360 {
361 if(!cipher.usable_in_version(Protocol_Version::TLS_V13)) {
362 return false;
363 }
364
365 if(hash_algorithm() != cipher.prf_algo()) {
366 return false;
367 }
368
369 BOTAN_ASSERT_NOMSG((m_encrypt == nullptr) == (m_decrypt == nullptr));
370 // Compare canonical AEAD names rather than substring-matching cipher_algo
371 // against m_encrypt->name(). starts_with() is both too permissive (an
372 // AES-128/CCM-8 instance starts with "AES-128/CCM" so it would accept the
373 // CCM-16 suite) and too restrictive (cipher_algo "AES-128/CCM(8)" does not
374 // prefix the canonical "AES-128/CCM(8,3)"). Re-instantiating the AEAD from
375 // cipher_algo yields the same canonical name() the suite would produce.
376 if(m_encrypt) {
377 auto canonical = AEAD_Mode::create(cipher.cipher_algo(), Cipher_Dir::Encryption);
378 if(!canonical || canonical->name() != m_encrypt->name()) {
379 return false;
380 }
381 }
382
383 return true;
384}
static std::unique_ptr< AEAD_Mode > create(std::string_view algo, Cipher_Dir direction, std::string_view provider="")
Definition aead.cpp:59
std::string hash_algorithm() const

References BOTAN_ASSERT_NOMSG, Botan::TLS::Ciphersuite::cipher_algo(), Botan::AEAD_Mode::create(), Botan::Encryption, hash_algorithm(), Botan::TLS::Ciphersuite::prf_algo(), and Botan::TLS::Ciphersuite::usable_in_version().

Referenced by advance_with_server_hello().

◆ minimum_decryption_input_length()

size_t Botan::TLS::Cipher_State::minimum_decryption_input_length ( ) const
Returns
the minimum ciphertext length for decryption

Definition at line 293 of file tls_cipher_state.cpp.

293 {
294 BOTAN_ASSERT_NONNULL(m_decrypt);
295 return m_decrypt->minimum_final_size();
296}

References BOTAN_ASSERT_NONNULL.

Referenced by Botan::TLS::Record_Layer::next_record(), and operator=().

◆ must_expect_unprotected_alert_traffic()

bool Botan::TLS::Cipher_State::must_expect_unprotected_alert_traffic ( ) const

Indicates whether unprotected Alert records are to be expected

Definition at line 298 of file tls_cipher_state.cpp.

298 {
299 // Client side:
300 // After successfully receiving a Server Hello we expect servers to send
301 // alerts as protected records only, just like they start protecting their
302 // handshake data at this point.
303 if(m_connection_side == Connection_Side::Client && m_state == State::EarlyTraffic) {
304 return true;
305 }
306
307 // Server side:
308 // Servers must expect clients to send unprotected alerts during the hand-
309 // shake. In particular, in the response to the server's first protected
310 // flight. We don't expect the client to send alerts protected under the
311 // early traffic secret.
312 //
313 // TODO: when implementing PSK and/or early data for the server, we might
314 // need to reconsider this decision.
315 if(m_connection_side == Connection_Side::Server &&
316 (m_state == State::HandshakeTraffic || m_state == State::ServerApplicationTraffic)) {
317 return true;
318 }
319
320 return false;
321}

References Botan::TLS::Client, and Botan::TLS::Server.

Referenced by Botan::TLS::Record_Layer::next_record().

◆ next_ticket_nonce()

Ticket_Nonce Botan::TLS::Cipher_State::next_ticket_nonce ( )

Generates a nonce value that is unique for any given Cipher_State object. Note that the number of nonces is limited to 2^16 and this method will throw if more nonces are requested.

Definition at line 425 of file tls_cipher_state.cpp.

425 {
426 BOTAN_STATE_CHECK(m_state == State::Completed);
427 if(m_ticket_nonce_exhausted) {
428 throw Botan::Invalid_State("ticket nonce pool exhausted");
429 }
430
431 auto retval = store_be<Ticket_Nonce>(m_ticket_nonce);
432
433 if(m_ticket_nonce == std::numeric_limits<decltype(m_ticket_nonce)>::max()) {
434 m_ticket_nonce_exhausted = true;
435 } else {
436 ++m_ticket_nonce;
437 }
438
439 return retval;
440}
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:745

References BOTAN_STATE_CHECK, and Botan::store_be().

Referenced by operator=().

◆ operator=() [1/2]

◆ operator=() [2/2]

Cipher_State & Botan::TLS::Cipher_State::operator= ( const Cipher_State & other)
delete

References Cipher_State().

◆ psk()

secure_vector< uint8_t > Botan::TLS::Cipher_State::psk ( const Ticket_Nonce & nonce) const

Calculate the PSK for the given nonce (RFC 8446 4.6.1)

Definition at line 419 of file tls_cipher_state.cpp.

419 {
420 BOTAN_ASSERT_NOMSG(m_state == State::Completed);
421
422 return derive_secret(m_resumption_master_secret, "resumption", nonce.get());
423}

References BOTAN_ASSERT_NOMSG, and Botan::detail::Strong_Base< T >::get().

Referenced by init_with_psk(), and operator=().

◆ psk_binder_mac()

std::vector< uint8_t > Botan::TLS::Cipher_State::psk_binder_mac ( const Transcript_Hash & transcript_hash_with_truncated_client_hello) const

Calculates the MAC for a PSK binder value in Client Hellos. Note that the transcript hash passed into this method is computed from a partial Client Hello (RFC 8446 4.2.11.2)

Definition at line 386 of file tls_cipher_state.cpp.

387 {
388 BOTAN_ASSERT_NOMSG(m_state == State::PskBinder);
389
390 auto hmac = HMAC(m_hash->new_object());
391 hmac.set_key(m_binder_key);
392 hmac.update(transcript_hash_with_truncated_client_hello);
393 return hmac.final_stdvec();
394}

References BOTAN_ASSERT_NOMSG.

Referenced by operator=().

◆ update_read_keys()

void Botan::TLS::Cipher_State::update_read_keys ( const Secret_Logger & channel)

Updates the key material used for decrypting data This is triggered after we received a Key_Update from the peer.

Note that this must not be called before the connection is ready for application traffic.

Definition at line 634 of file tls_cipher_state.cpp.

634 {
635 BOTAN_ASSERT_NOMSG(m_state == State::ServerApplicationTraffic || m_state == State::Completed);
636
637 m_read_application_traffic_secret =
638 hkdf_expand_label(m_read_application_traffic_secret, "traffic upd", {}, m_hash->output_length());
639
640 const auto secret_label = fmt("{}_TRAFFIC_SECRET_{}",
641 m_connection_side == Connection_Side::Server ? "CLIENT" : "SERVER",
642 ++m_read_key_update_count);
643 logger.maybe_log_secret(secret_label, m_read_application_traffic_secret);
644
645 derive_read_traffic_key(m_read_application_traffic_secret);
646}
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53

References BOTAN_ASSERT_NOMSG, Botan::fmt(), Botan::TLS::Secret_Logger::maybe_log_secret(), and Botan::TLS::Server.

◆ update_write_keys()

void Botan::TLS::Cipher_State::update_write_keys ( const Secret_Logger & channel)

Updates the key material used for encrypting data This is triggered after we send a Key_Update to the peer.

Note that this must not be called before the connection is ready for application traffic.

Definition at line 648 of file tls_cipher_state.cpp.

648 {
649 BOTAN_ASSERT_NOMSG(m_state == State::ServerApplicationTraffic || m_state == State::Completed);
650 m_write_application_traffic_secret =
651 hkdf_expand_label(m_write_application_traffic_secret, "traffic upd", {}, m_hash->output_length());
652
653 const auto secret_label = fmt("{}_TRAFFIC_SECRET_{}",
654 m_connection_side == Connection_Side::Server ? "SERVER" : "CLIENT",
655 ++m_write_key_update_count);
656 logger.maybe_log_secret(secret_label, m_write_application_traffic_secret);
657
658 derive_write_traffic_key(m_write_application_traffic_secret);
659}

References BOTAN_ASSERT_NOMSG, Botan::fmt(), Botan::TLS::Secret_Logger::maybe_log_secret(), and Botan::TLS::Server.

◆ verify_peer_finished_mac()

bool Botan::TLS::Cipher_State::verify_peer_finished_mac ( const Transcript_Hash & transcript_hash,
const std::vector< uint8_t > & peer_mac ) const

Validate a MAC received in a TLS "Finished" handshake message (RFC 8446 4.4.4)

Definition at line 407 of file tls_cipher_state.cpp.

408 {
409 BOTAN_ASSERT_NOMSG(m_connection_side != Connection_Side::Server || m_state == State::ServerApplicationTraffic);
410 BOTAN_ASSERT_NOMSG(m_connection_side != Connection_Side::Client || m_state == State::HandshakeTraffic);
411 BOTAN_ASSERT_NOMSG(!m_peer_finished_key.empty());
412
413 auto hmac = HMAC(m_hash->new_object());
414 hmac.set_key(m_peer_finished_key);
415 hmac.update(transcript_hash);
416 return hmac.verify_mac(peer_mac);
417}

References BOTAN_ASSERT_NOMSG, Botan::TLS::Client, and Botan::TLS::Server.

Referenced by operator=(), and Botan::TLS::Finished_13::verify().


The documentation for this class was generated from the following files: