Coverage Report

Created: 2023-01-25 06:35

/src/botan/src/lib/tls/tls13/tls_cipher_state.cpp
Line
Count
Source (jump to first uncovered line)
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
105
namespace Botan::TLS {
106
107
namespace {
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.
116
constexpr size_t NONCE_LENGTH = 12;
117
}
118
119
std::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
0
   {
125
0
   auto cs = std::unique_ptr<Cipher_State>(new Cipher_State(side, cipher.prf_algo()));
126
0
   cs->advance_without_psk();
127
0
   cs->advance_with_server_hello(cipher, std::move(shared_secret), transcript_hash);
128
0
   return cs;
129
0
   }
130
131
std::unique_ptr<Cipher_State> Cipher_State::init_with_psk(
132
         const Connection_Side side,
133
         const Cipher_State::PSK_Type type,
134
         secure_vector<uint8_t>&& psk,
135
         const Ciphersuite& cipher)
136
0
   {
137
0
   auto cs = std::unique_ptr<Cipher_State>(new Cipher_State(side, cipher.prf_algo()));
138
0
   cs->advance_with_psk(type, std::move(psk));
139
0
   return cs;
140
0
   }
141
142
void Cipher_State::advance_with_client_hello(const Transcript_Hash &transcript_hash)
143
0
   {
144
0
   BOTAN_ASSERT_NOMSG(m_state == State::PskBinder);
145
146
0
   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
0
   m_exporter_master_secret = derive_secret(m_early_secret, "e exp master", transcript_hash);
155
156
0
   m_salt = derive_secret(m_early_secret, "derived", empty_hash());
157
0
   zap(m_early_secret);
158
159
0
   m_state = State::EarlyTraffic;
160
0
   }
161
162
void Cipher_State::advance_with_server_finished(const Transcript_Hash& transcript_hash)
163
0
   {
164
0
   BOTAN_ASSERT_NOMSG(m_state == State::HandshakeTraffic);
165
166
0
   const auto master_secret = hkdf_extract(secure_vector<uint8_t>(m_hash->output_length(), 0x00));
167
168
0
   auto client_application_traffic_secret = derive_secret(master_secret, "c ap traffic", transcript_hash);
169
0
   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
0
   if(m_connection_side == Connection_Side::SERVER)
175
0
      {
176
0
      derive_write_traffic_key(server_application_traffic_secret);
177
0
      m_read_application_traffic_secret = std::move(client_application_traffic_secret);
178
0
      m_write_application_traffic_secret      = std::move(server_application_traffic_secret);
179
0
      }
180
0
   else
181
0
      {
182
0
      derive_read_traffic_key(server_application_traffic_secret);
183
0
      m_read_application_traffic_secret = std::move(server_application_traffic_secret);
184
0
      m_write_application_traffic_secret      = std::move(client_application_traffic_secret);
185
0
      }
186
187
0
   m_exporter_master_secret = derive_secret(master_secret, "exp master", transcript_hash);
188
189
0
   m_state = State::ServerApplicationTraffic;
190
0
   }
191
192
void Cipher_State::advance_with_client_finished(const Transcript_Hash& transcript_hash)
193
0
   {
194
0
   BOTAN_ASSERT_NOMSG(m_state == State::ServerApplicationTraffic);
195
196
0
   zap(m_finished_key);
197
0
   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
0
   if(m_connection_side == Connection_Side::SERVER)
202
0
      {
203
0
      derive_read_traffic_key(m_read_application_traffic_secret);
204
0
      }
205
0
   else
206
0
      {
207
0
      derive_write_traffic_key(m_write_application_traffic_secret);
208
0
      }
209
210
0
   const auto master_secret = hkdf_extract(secure_vector<uint8_t>(m_hash->output_length(), 0x00));
211
212
0
   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
0
   zap(m_salt);
216
217
0
   m_state = State::Completed;
218
0
   }
219
220
std::vector<uint8_t> Cipher_State::current_nonce(const uint64_t seq_no, const secure_vector<uint8_t>& iv) const
221
0
   {
222
   // RFC 8446 5.3
223
   //    The per-record nonce for the AEAD construction is formed as follows:
224
   //
225
   //    1.  The 64-bit record sequence number is encoded in network byte
226
   //        order and padded to the left with zeros to iv_length.
227
   //
228
   //    2.  The padded sequence number is XORed with either the static
229
   //        client_write_iv or server_write_iv (depending on the role).
230
0
   std::vector<uint8_t> nonce(NONCE_LENGTH);
231
0
   store_be(seq_no, nonce.data() + (NONCE_LENGTH-sizeof(seq_no)));
232
0
   xor_buf(nonce, iv.data(), iv.size());
233
0
   return nonce;
234
0
   }
235
236
uint64_t Cipher_State::encrypt_record_fragment(const std::vector<uint8_t>& header, secure_vector<uint8_t>& fragment)
237
0
   {
238
0
   BOTAN_ASSERT_NONNULL(m_encrypt);
239
240
0
   m_encrypt->set_key(m_write_key);
241
0
   m_encrypt->set_associated_data_vec(header);
242
0
   m_encrypt->start(current_nonce(m_write_seq_no, m_write_iv));
243
0
   m_encrypt->finish(fragment);
244
245
0
   return m_write_seq_no++;
246
0
   }
247
248
uint64_t Cipher_State::decrypt_record_fragment(const std::vector<uint8_t>& header,
249
      secure_vector<uint8_t>& encrypted_fragment)
250
0
   {
251
0
   BOTAN_ASSERT_NONNULL(m_decrypt);
252
0
   BOTAN_ARG_CHECK(encrypted_fragment.size() >= m_decrypt->minimum_final_size(),
253
0
         "fragment too short to decrypt");
254
255
0
   m_decrypt->set_key(m_read_key);
256
0
   m_decrypt->set_associated_data_vec(header);
257
0
   m_decrypt->start(current_nonce(m_read_seq_no, m_read_iv));
258
259
0
   m_decrypt->finish(encrypted_fragment);
260
261
0
   return m_read_seq_no++;
262
0
   }
263
264
size_t Cipher_State::encrypt_output_length(const size_t input_length) const
265
0
   {
266
0
   BOTAN_ASSERT_NONNULL(m_encrypt);
267
0
   return m_encrypt->output_length(input_length);
268
0
   }
269
270
size_t Cipher_State::decrypt_output_length(const size_t input_length) const
271
0
   {
272
0
   BOTAN_ASSERT_NONNULL(m_decrypt);
273
0
   return m_decrypt->output_length(input_length);
274
0
   }
275
276
size_t Cipher_State::minimum_decryption_input_length() const
277
0
   {
278
0
   BOTAN_ASSERT_NONNULL(m_decrypt);
279
0
   return m_decrypt->minimum_final_size();
280
0
   }
281
282
bool Cipher_State::must_expect_unprotected_alert_traffic() const
283
0
   {
284
   // Client side:
285
   //   After successfully receiving a Server Hello we expect servers to send
286
   //   alerts as protected records only, just like they start protecting their
287
   //   handshake data at this point.
288
0
   if(m_connection_side == CLIENT && m_state == State::EarlyTraffic)
289
0
      { return true; }
290
291
   // Server side:
292
   //   Servers must expect clients to send unprotected alerts during the hand-
293
   //   shake. In particular, in the response to the server's first protected
294
   //   flight. We don't expect the client to send alerts protected under the
295
   //   early traffic secret.
296
   //
297
   // TODO: when implementing PSK and/or early data for the server, we might
298
   //       need to reconsider this decision.
299
0
   if(m_connection_side == SERVER &&
300
0
         (m_state == State::HandshakeTraffic ||
301
0
          m_state == State::ServerApplicationTraffic))
302
0
      { return true; }
303
304
0
   return false;
305
0
   }
306
307
bool Cipher_State::can_encrypt_application_traffic() const
308
0
   {
309
   // TODO: when implementing early traffic (0-RTT) this will likely need
310
   //       to allow `State::EarlyTraffic`.
311
312
0
   if(m_connection_side == Connection_Side::CLIENT && m_state != State::Completed)
313
0
      { return false; }
314
315
0
   if (m_connection_side == Connection_Side::SERVER && m_state != State::ServerApplicationTraffic && m_state != State::Completed)
316
0
      { return false; }
317
318
0
   return !m_write_key.empty() && !m_write_iv.empty();
319
0
   }
320
321
bool Cipher_State::can_decrypt_application_traffic() const
322
0
   {
323
   // TODO: when implementing early traffic (0-RTT) this will likely need
324
   //       to allow `State::EarlyTraffic`.
325
326
0
   if(m_connection_side == Connection_Side::CLIENT && m_state != State::ServerApplicationTraffic && m_state != State::Completed)
327
0
      { return false; }
328
329
0
   if(m_connection_side == Connection_Side::SERVER && m_state != State::Completed)
330
0
      { return false; }
331
332
0
   return !m_read_key.empty() && !m_read_iv.empty();
333
0
   }
334
335
bool Cipher_State::is_compatible_with(const Ciphersuite& cipher) const
336
0
   {
337
0
   if(!cipher.usable_in_version(Protocol_Version::TLS_V13))
338
0
      return false;
339
340
0
   if(m_hash && m_hash->name() != cipher.prf_algo())
341
0
      return false;
342
343
0
   BOTAN_ASSERT_NOMSG((m_encrypt == nullptr) == (m_decrypt == nullptr));
344
   // TODO: Find a better way to check that the instantiated cipher algorithm
345
   //       is compatible with the one required by the cipher suite.
346
   // AEAD_Mode::create() sets defaults the tag length to 16 which is then
347
   // reported via AEAD_Mode::name() and hinders the trivial string comparison.
348
0
   if(m_encrypt && m_encrypt->name() != cipher.cipher_algo() &&
349
0
                   m_encrypt->name() != cipher.cipher_algo() + "(16)")
350
0
      return false;
351
352
0
   return true;
353
0
   }
354
355
std::vector<uint8_t> Cipher_State::psk_binder_mac(const Transcript_Hash& transcript_hash_with_truncated_client_hello)
356
0
   {
357
0
   BOTAN_ASSERT_NOMSG(m_state == State::PskBinder);
358
359
0
   auto hmac = HMAC(m_hash->new_object());
360
0
   hmac.set_key(m_binder_key);
361
0
   hmac.update(transcript_hash_with_truncated_client_hello);
362
0
   return hmac.final_stdvec();
363
0
   }
364
365
std::vector<uint8_t> Cipher_State::finished_mac(const Transcript_Hash& transcript_hash) const
366
0
   {
367
0
   BOTAN_ASSERT_NOMSG(m_connection_side != Connection_Side::SERVER || m_state == State::HandshakeTraffic);
368
0
   BOTAN_ASSERT_NOMSG(m_connection_side != Connection_Side::CLIENT || m_state == State::ServerApplicationTraffic);
369
0
   BOTAN_ASSERT_NOMSG(!m_finished_key.empty());
370
371
0
   auto hmac = HMAC(m_hash->new_object());
372
0
   hmac.set_key(m_finished_key);
373
0
   hmac.update(transcript_hash);
374
0
   return hmac.final_stdvec();
375
0
   }
376
377
bool Cipher_State::verify_peer_finished_mac(const Transcript_Hash& transcript_hash,
378
      const std::vector<uint8_t>& peer_mac) const
379
0
   {
380
0
   BOTAN_ASSERT_NOMSG(m_connection_side != Connection_Side::SERVER || m_state == State::ServerApplicationTraffic);
381
0
   BOTAN_ASSERT_NOMSG(m_connection_side != Connection_Side::CLIENT || m_state == State::HandshakeTraffic);
382
0
   BOTAN_ASSERT_NOMSG(!m_peer_finished_key.empty());
383
384
0
   auto hmac = HMAC(m_hash->new_object());
385
0
   hmac.set_key(m_peer_finished_key);
386
0
   hmac.update(transcript_hash);
387
0
   return hmac.verify_mac(peer_mac);
388
0
   }
389
390
secure_vector<uint8_t> Cipher_State::psk(const std::vector<uint8_t>& nonce) const
391
0
   {
392
0
   BOTAN_ASSERT_NOMSG(m_state == State::Completed);
393
394
0
   return derive_secret(m_resumption_master_secret, "resumption", nonce);
395
0
   }
396
397
398
secure_vector<uint8_t> Cipher_State::export_key(const std::string& label,
399
      const std::string& context,
400
      size_t length) const
401
0
   {
402
0
   BOTAN_ASSERT_NOMSG(can_export_keys());
403
404
0
   m_hash->update(context);
405
0
   const auto context_hash = m_hash->final_stdvec();
406
0
   return hkdf_expand_label(derive_secret(m_exporter_master_secret, label, empty_hash()),
407
0
                            "exporter", context_hash, length);
408
0
   }
409
410
411
namespace {
412
413
std::unique_ptr<MessageAuthenticationCode> create_hmac(const std::string& hash)
414
0
   {
415
0
   return std::make_unique<HMAC>(HashFunction::create_or_throw(hash));
416
0
   }
417
418
}
419
420
Cipher_State::Cipher_State(Connection_Side whoami, const std::string& hash_function)
421
   : m_state(State::Uninitialized)
422
   , m_connection_side(whoami)
423
   , m_extract(std::make_unique<HKDF_Extract>(create_hmac(hash_function)))
424
   , m_expand(std::make_unique<HKDF_Expand>(create_hmac(hash_function)))
425
   , m_hash(HashFunction::create_or_throw(hash_function))
426
   , m_salt(m_hash->output_length(), 0x00)
427
   , m_write_seq_no(0)
428
0
   , m_read_seq_no(0) {}
429
430
0
Cipher_State::~Cipher_State() = default;
431
432
void Cipher_State::advance_without_psk()
433
0
   {
434
0
   BOTAN_ASSERT_NOMSG(m_state == State::Uninitialized);
435
436
   // We are not using `m_early_secret` here because the secret won't be needed
437
   // in any further state advancement methods.
438
0
   const auto early_secret = hkdf_extract(secure_vector<uint8_t>(m_hash->output_length(), 0x00));
439
0
   m_salt = derive_secret(early_secret, "derived", empty_hash());
440
441
   // Without PSK we skip the `PskBinder` state and go right to `EarlyTraffic`.
442
0
   m_state = State::EarlyTraffic;
443
0
   }
444
445
void Cipher_State::advance_with_psk(PSK_Type type, secure_vector<uint8_t>&& psk)
446
0
   {
447
0
   BOTAN_ASSERT_NOMSG(m_state == State::Uninitialized);
448
449
0
   m_early_secret = hkdf_extract(std::move(psk));
450
451
0
   const char* binder_label =
452
0
      (type == PSK_Type::RESUMPTION)
453
0
         ? "res binder"
454
0
         : "ext binder";
455
456
   // RFC 8446 4.2.11.2
457
   //    The PskBinderEntry is computed in the same way as the Finished message
458
   //    [...] but with the BaseKey being the binder_key derived via the key
459
   //    schedule from the corresponding PSK which is being offered.
460
   //
461
   // Hence we are doing the binder key derivation and expansion in one go.
462
0
   const auto binder_key = derive_secret(m_early_secret, binder_label, empty_hash());
463
0
   m_binder_key = hkdf_expand_label(binder_key, "finished", {}, m_hash->output_length());
464
465
0
   m_state = State::PskBinder;
466
0
   }
467
468
void Cipher_State::advance_with_server_hello(const Ciphersuite& cipher,
469
      secure_vector<uint8_t>&& shared_secret,
470
      const Transcript_Hash& transcript_hash)
471
0
   {
472
0
   BOTAN_ASSERT_NOMSG(m_state == State::EarlyTraffic);
473
0
   BOTAN_ASSERT_NOMSG(!m_encrypt);
474
0
   BOTAN_ASSERT_NOMSG(!m_decrypt);
475
0
   BOTAN_STATE_CHECK(is_compatible_with(cipher));
476
477
0
   m_encrypt = AEAD_Mode::create_or_throw(cipher.cipher_algo(), ENCRYPTION);
478
0
   m_decrypt = AEAD_Mode::create_or_throw(cipher.cipher_algo(), DECRYPTION);
479
480
0
   const auto handshake_secret = hkdf_extract(std::move(shared_secret));
481
482
0
   const auto client_handshake_traffic_secret = derive_secret(handshake_secret, "c hs traffic", transcript_hash);
483
0
   const auto server_handshake_traffic_secret = derive_secret(handshake_secret, "s hs traffic", transcript_hash);
484
485
0
   if(m_connection_side == Connection_Side::SERVER)
486
0
      {
487
0
      derive_read_traffic_key(client_handshake_traffic_secret, true);
488
0
      derive_write_traffic_key(server_handshake_traffic_secret, true);
489
0
      }
490
0
   else
491
0
      {
492
0
      derive_read_traffic_key(server_handshake_traffic_secret, true);
493
0
      derive_write_traffic_key(client_handshake_traffic_secret, true);
494
0
      }
495
496
0
   m_salt = derive_secret(handshake_secret, "derived", empty_hash());
497
498
0
   m_state = State::HandshakeTraffic;
499
0
   }
500
501
void Cipher_State::derive_write_traffic_key(const secure_vector<uint8_t>& traffic_secret,
502
      const bool handshake_traffic_secret)
503
0
   {
504
0
   BOTAN_ASSERT_NONNULL(m_encrypt);
505
506
0
   m_write_key    = hkdf_expand_label(traffic_secret, "key", {}, m_encrypt->minimum_keylength());
507
0
   m_write_iv     = hkdf_expand_label(traffic_secret, "iv", {}, NONCE_LENGTH);
508
0
   m_write_seq_no = 0;
509
510
0
   if(handshake_traffic_secret)
511
0
      {
512
      // Key derivation for the MAC in the "Finished" handshake message as described in RFC 8446 4.4.4
513
      // (will be cleared in advance_with_server_finished())
514
0
      m_finished_key = hkdf_expand_label(traffic_secret, "finished", {}, m_hash->output_length());
515
0
      }
516
0
   }
517
518
void Cipher_State::derive_read_traffic_key(const secure_vector<uint8_t>& traffic_secret,
519
      const bool handshake_traffic_secret)
520
0
   {
521
0
   BOTAN_ASSERT_NONNULL(m_encrypt);
522
523
0
   m_read_key    = hkdf_expand_label(traffic_secret, "key", {}, m_encrypt->minimum_keylength());
524
0
   m_read_iv     = hkdf_expand_label(traffic_secret, "iv", {}, NONCE_LENGTH);
525
0
   m_read_seq_no = 0;
526
527
0
   if(handshake_traffic_secret)
528
0
      {
529
      // Key derivation for the MAC in the "Finished" handshake message as described in RFC 8446 4.4.4
530
      // (will be cleared in advance_with_client_finished())
531
0
      m_peer_finished_key = hkdf_expand_label(traffic_secret, "finished", {}, m_hash->output_length());
532
0
      }
533
0
   }
534
535
secure_vector<uint8_t> Cipher_State::hkdf_extract(secure_vector<uint8_t>&& ikm) const
536
0
   {
537
0
   return m_extract->derive_key(m_hash->output_length(), ikm, m_salt, std::vector<uint8_t>());
538
0
   }
539
540
secure_vector<uint8_t> Cipher_State::hkdf_expand_label(
541
   const secure_vector<uint8_t>& secret,
542
   const std::string&            label,
543
   const std::vector<uint8_t>&   context,
544
   const size_t                  length) const
545
0
   {
546
   // assemble (serialized) HkdfLabel
547
0
   secure_vector<uint8_t> hkdf_label;
548
0
   hkdf_label.reserve(2 /* length */ +
549
0
                      (label.size() +
550
0
                       6 /* 'tls13 ' */ +
551
0
                       1 /* length field*/) +
552
0
                      (context.size() +
553
0
                       1 /* length field*/));
554
555
   // length
556
0
   BOTAN_ARG_CHECK(length <= std::numeric_limits<uint16_t>::max(), "invalid length");
557
0
   const auto len = static_cast<uint16_t>(length);
558
0
   hkdf_label.push_back(get_byte<0>(len));
559
0
   hkdf_label.push_back(get_byte<1>(len));
560
561
   // label
562
0
   const std::string prefix = "tls13 ";
563
0
   BOTAN_ARG_CHECK(prefix.size() + label.size() <= 255, "label too large");
564
0
   hkdf_label.push_back(static_cast<uint8_t>(prefix.size() + label.size()));
565
0
   hkdf_label.insert(hkdf_label.end(), prefix.cbegin(), prefix.cend());
566
0
   hkdf_label.insert(hkdf_label.end(), label.cbegin(), label.cend());
567
568
   // context
569
0
   BOTAN_ARG_CHECK(context.size() <= 255, "context too large");
570
0
   hkdf_label.push_back(static_cast<uint8_t>(context.size()));
571
0
   hkdf_label.insert(hkdf_label.end(), context.cbegin(), context.cend());
572
573
   // HKDF-Expand
574
0
   return m_expand->derive_key(length, secret, hkdf_label, std::vector<uint8_t>() /* just pleasing botan's interface */);
575
0
   }
576
577
secure_vector<uint8_t> Cipher_State::derive_secret(
578
   const secure_vector<uint8_t>& secret,
579
   const std::string&            label,
580
   const Transcript_Hash&        messages_hash) const
581
0
   {
582
0
   return hkdf_expand_label(secret, label, messages_hash, m_hash->output_length());
583
0
   }
584
585
std::vector<uint8_t> Cipher_State::empty_hash() const
586
0
   {
587
0
   m_hash->update("");
588
0
   return m_hash->final_stdvec();
589
0
   }
590
591
void Cipher_State::update_read_keys()
592
0
   {
593
0
   BOTAN_ASSERT_NOMSG(m_state == State::ServerApplicationTraffic ||
594
0
                      m_state == State::Completed);
595
596
0
   m_read_application_traffic_secret =
597
0
      hkdf_expand_label(m_read_application_traffic_secret, "traffic upd", {}, m_hash->output_length());
598
599
0
   derive_read_traffic_key(m_read_application_traffic_secret);
600
0
   }
601
602
void Cipher_State::update_write_keys()
603
0
   {
604
0
   BOTAN_ASSERT_NOMSG(m_state == State::ServerApplicationTraffic ||
605
0
                      m_state == State::Completed);
606
0
   m_write_application_traffic_secret =
607
0
      hkdf_expand_label(m_write_application_traffic_secret, "traffic upd", {}, m_hash->output_length());
608
609
0
   derive_write_traffic_key(m_write_application_traffic_secret);
610
0
   }
611
612
void Cipher_State::clear_read_keys()
613
0
   {
614
0
   zap(m_read_key);
615
0
   zap(m_read_iv);
616
0
   zap(m_read_application_traffic_secret);
617
0
   }
618
619
void Cipher_State::clear_write_keys()
620
0
   {
621
0
   zap(m_write_key);
622
0
   zap(m_write_iv);
623
0
   zap(m_write_application_traffic_secret);
624
0
   }
625
626
}  // namespace Botan::TLS