Coverage Report

Created: 2022-09-23 06:05

/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
 *                                     |
20
 *                                     +-----> Derive-Secret(., "c e traffic", ClientHello)
21
 *                                     |                     = client_early_traffic_secret
22
 *                                     |
23
 *                                     +-----> Derive-Secret(., "e exp master", ClientHello)
24
 *                                     |                     = early_exporter_master_secret
25
 *                                     v
26
 *                               Derive-Secret(., "derived", "")
27
 *                                     |
28
 *                                     *
29
 *                             STATE EARLY TRAFFIC
30
 * This state is reached by constructing Cipher_State using init_with_psk() (not yet implemented).
31
 * The state can then be further advanced using advance_with_server_hello().
32
 *                                     *
33
 *                                     |
34
 *                                     v
35
 *                           (EC)DHE -> HKDF-Extract = Handshake Secret
36
 *                                     |
37
 *                                     +-----> Derive-Secret(., "c hs traffic",
38
 *                                     |                     ClientHello...ServerHello)
39
 *                                     |                     = client_handshake_traffic_secret
40
 *                                     |
41
 *                                     +-----> Derive-Secret(., "s hs traffic",
42
 *                                     |                     ClientHello...ServerHello)
43
 *                                     |                     = server_handshake_traffic_secret
44
 *                                     v
45
 *                               Derive-Secret(., "derived", "")
46
 *                                     |
47
 *                                     *
48
 *                          STATE HANDSHAKE TRAFFIC
49
 * This state is reached by constructing Cipher_State using init_with_server_hello().
50
 * In this state the handshake traffic secrets are available. The state can then be further
51
 * advanced using advance_with_server_finished().
52
 *                                     *
53
 *                                     |
54
 *                                     v
55
 *                           0 -> HKDF-Extract = Master Secret
56
 *                                     |
57
 *                                     +-----> Derive-Secret(., "c ap traffic",
58
 *                                     |                     ClientHello...server Finished)
59
 *                                     |                     = client_application_traffic_secret_0
60
 *                                     |
61
 *                                     +-----> Derive-Secret(., "s ap traffic",
62
 *                                     |                     ClientHello...server Finished)
63
 *                                     |                     = server_application_traffic_secret_0
64
 *                                     |
65
 *                                     +-----> Derive-Secret(., "exp master",
66
 *                                     |                     ClientHello...server Finished)
67
 *                                     |                     = exporter_master_secret
68
 *                                     *
69
 *                         STATE APPLICATION TRAFFIC
70
 * This state is reached by calling advance_with_server_finished(). The state can then be further
71
 * advanced using advance_with_client_finished().
72
 *                                     *
73
 *                                     |
74
 *                                     +-----> Derive-Secret(., "res master",
75
 *                                                           ClientHello...client Finished)
76
 *                                                           = resumption_master_secret
77
 *                             STATE COMPLETED
78
 */
79
80
#include <limits>
81
#include <utility>
82
83
#include <botan/internal/tls_cipher_state.h>
84
85
#include <botan/aead.h>
86
#include <botan/assert.h>
87
#include <botan/secmem.h>
88
#include <botan/tls_ciphersuite.h>
89
#include <botan/hash.h>
90
#include <botan/tls_magic.h>
91
92
#include <botan/internal/hkdf.h>
93
#include <botan/internal/hmac.h>
94
#include <botan/internal/loadstor.h>
95
96
namespace Botan::TLS {
97
98
namespace {
99
// RFC 8446 5.3
100
//    Each AEAD algorithm will specify a range of possible lengths for the
101
//    per-record nonce, from N_MIN bytes to N_MAX bytes of input [RFC5116].
102
//    The length of the TLS per-record nonce (iv_length) is set to the
103
//    larger of 8 bytes and N_MIN for the AEAD algorithm (see [RFC5116],
104
//    Section 4).
105
//
106
// N_MIN is 12 for AES_GCM and AES_CCM as per RFC 5116 and also 12 for ChaCha20 per RFC 8439.
107
constexpr size_t NONCE_LENGTH = 12;
108
}
109
110
std::unique_ptr<Cipher_State> Cipher_State::init_with_server_hello(
111
   const Connection_Side side,
112
   secure_vector<uint8_t>&& shared_secret,
113
   const Ciphersuite& cipher,
114
   const Transcript_Hash& transcript_hash)
115
0
   {
116
0
   auto cs = std::unique_ptr<Cipher_State>(new Cipher_State(side, cipher));
117
0
   cs->advance_without_psk();
118
0
   cs->advance_with_server_hello(std::move(shared_secret), transcript_hash);
119
0
   return cs;
120
0
   }
121
122
void Cipher_State::advance_with_server_finished(const Transcript_Hash& transcript_hash)
123
0
   {
124
0
   BOTAN_ASSERT_NOMSG(m_state == State::HandshakeTraffic);
125
126
0
   zap(m_finished_key);
127
0
   zap(m_peer_finished_key);
128
129
0
   const auto master_secret = hkdf_extract(secure_vector<uint8_t>(m_hash->output_length(), 0x00));
130
131
0
   auto client_application_traffic_secret = derive_secret(master_secret, "c ap traffic", transcript_hash);
132
0
   auto server_application_traffic_secret = derive_secret(master_secret, "s ap traffic", transcript_hash);
133
134
0
   if(m_connection_side == Connection_Side::SERVER)
135
0
      {
136
0
      derive_read_traffic_key(client_application_traffic_secret);
137
0
      derive_write_traffic_key(server_application_traffic_secret);
138
0
      m_read_application_traffic_secret = std::move(client_application_traffic_secret);
139
0
      m_write_application_traffic_secret      = std::move(server_application_traffic_secret);
140
0
      }
141
0
   else
142
0
      {
143
0
      derive_read_traffic_key(server_application_traffic_secret);
144
0
      derive_write_traffic_key(client_application_traffic_secret);
145
0
      m_read_application_traffic_secret = std::move(server_application_traffic_secret);
146
0
      m_write_application_traffic_secret      = std::move(client_application_traffic_secret);
147
0
      }
148
149
0
   m_exporter_master_secret = derive_secret(master_secret, "exp master", transcript_hash);
150
151
0
   m_state = State::ApplicationTraffic;
152
0
   }
153
154
void Cipher_State::advance_with_client_finished(const Transcript_Hash& transcript_hash)
155
0
   {
156
0
   BOTAN_ASSERT_NOMSG(m_state == State::ApplicationTraffic);
157
158
0
   const auto master_secret = hkdf_extract(secure_vector<uint8_t>(m_hash->output_length(), 0x00));
159
160
0
   m_resumption_master_secret = derive_secret(master_secret, "res master", transcript_hash);
161
162
   // This was the final state change; the salt is no longer needed.
163
0
   zap(m_salt);
164
165
0
   m_state = State::Completed;
166
0
   }
167
168
std::vector<uint8_t> Cipher_State::current_nonce(const uint64_t seq_no, const secure_vector<uint8_t>& iv) const
169
0
   {
170
   // RFC 8446 5.3
171
   //    The per-record nonce for the AEAD construction is formed as follows:
172
   //
173
   //    1.  The 64-bit record sequence number is encoded in network byte
174
   //        order and padded to the left with zeros to iv_length.
175
   //
176
   //    2.  The padded sequence number is XORed with either the static
177
   //        client_write_iv or server_write_iv (depending on the role).
178
0
   std::vector<uint8_t> nonce(NONCE_LENGTH);
179
0
   store_be(seq_no, nonce.data() + (NONCE_LENGTH-sizeof(seq_no)));
180
0
   xor_buf(nonce, iv.data(), iv.size());
181
0
   return nonce;
182
0
   }
183
184
uint64_t Cipher_State::encrypt_record_fragment(const std::vector<uint8_t>& header, secure_vector<uint8_t>& fragment)
185
0
   {
186
0
   m_encrypt->set_key(m_write_key);
187
0
   m_encrypt->set_associated_data_vec(header);
188
0
   m_encrypt->start(current_nonce(m_write_seq_no, m_write_iv));
189
0
   m_encrypt->finish(fragment);
190
191
0
   return m_write_seq_no++;
192
0
   }
193
194
uint64_t Cipher_State::decrypt_record_fragment(const std::vector<uint8_t>& header,
195
      secure_vector<uint8_t>& encrypted_fragment)
196
0
   {
197
0
   BOTAN_ARG_CHECK(encrypted_fragment.size() >= m_decrypt->minimum_final_size(),
198
0
         "fragment too short to decrypt");
199
200
0
   m_decrypt->set_key(m_read_key);
201
0
   m_decrypt->set_associated_data_vec(header);
202
0
   m_decrypt->start(current_nonce(m_read_seq_no, m_read_iv));
203
204
0
   m_decrypt->finish(encrypted_fragment);
205
206
0
   return m_read_seq_no++;
207
0
   }
208
209
size_t Cipher_State::encrypt_output_length(const size_t input_length) const
210
0
   {
211
0
   return m_encrypt->output_length(input_length);
212
0
   }
213
214
size_t Cipher_State::decrypt_output_length(const size_t input_length) const
215
0
   {
216
0
   return m_decrypt->output_length(input_length);
217
0
   }
218
219
size_t Cipher_State::minimum_decryption_input_length() const
220
0
   {
221
0
   return m_decrypt->minimum_final_size();
222
0
   }
223
224
std::vector<uint8_t> Cipher_State::finished_mac(const Transcript_Hash& transcript_hash) const
225
0
   {
226
0
   BOTAN_ASSERT_NOMSG(m_state == State::HandshakeTraffic);
227
228
0
   auto hmac = HMAC(m_hash->new_object());
229
0
   hmac.set_key(m_finished_key);
230
0
   hmac.update(transcript_hash);
231
0
   return hmac.final_stdvec();
232
0
   }
233
234
bool Cipher_State::verify_peer_finished_mac(const Transcript_Hash& transcript_hash,
235
      const std::vector<uint8_t>& peer_mac) const
236
0
   {
237
0
   BOTAN_ASSERT_NOMSG(m_state == State::HandshakeTraffic);
238
239
0
   auto hmac = HMAC(m_hash->new_object());
240
0
   hmac.set_key(m_peer_finished_key);
241
0
   hmac.update(transcript_hash);
242
0
   return hmac.verify_mac(peer_mac);
243
0
   }
244
245
secure_vector<uint8_t> Cipher_State::psk(const std::vector<uint8_t>& nonce) const
246
0
   {
247
0
   BOTAN_ASSERT_NOMSG(m_state == State::Completed);
248
249
0
   return derive_secret(m_resumption_master_secret, "resumption", nonce);
250
0
   }
251
252
253
secure_vector<uint8_t> Cipher_State::export_key(const std::string& label,
254
      const std::string& context,
255
      size_t length) const
256
0
   {
257
0
   BOTAN_ASSERT_NOMSG(can_export_keys());
258
259
0
   m_hash->update(context);
260
0
   const auto context_hash = m_hash->final_stdvec();
261
0
   return hkdf_expand_label(derive_secret(m_exporter_master_secret, label, empty_hash()),
262
0
                            "exporter", context_hash, length);
263
0
   }
264
265
266
namespace {
267
268
std::unique_ptr<MessageAuthenticationCode> create_hmac(const Ciphersuite& cipher)
269
0
   {
270
0
   return std::make_unique<HMAC>(HashFunction::create_or_throw(cipher.prf_algo()));
271
0
   }
272
273
}
274
275
Cipher_State::Cipher_State(Connection_Side whoami, const Ciphersuite& cipher)
276
   : m_state(State::Uninitialized)
277
   , m_connection_side(whoami)
278
   , m_encrypt(AEAD_Mode::create(cipher.cipher_algo(), ENCRYPTION))
279
   , m_decrypt(AEAD_Mode::create(cipher.cipher_algo(), DECRYPTION))
280
   , m_extract(std::make_unique<HKDF_Extract>(create_hmac(cipher)))
281
   , m_expand(std::make_unique<HKDF_Expand>(create_hmac(cipher)))
282
   , m_hash(HashFunction::create_or_throw(cipher.prf_algo()))
283
   , m_salt(m_hash->output_length(), 0x00)
284
   , m_write_seq_no(0)
285
0
   , m_read_seq_no(0) {}
286
287
0
Cipher_State::~Cipher_State() = default;
288
289
void Cipher_State::advance_without_psk()
290
0
   {
291
0
   BOTAN_ASSERT_NOMSG(m_state == State::Uninitialized);
292
293
0
   const auto early_secret = hkdf_extract(secure_vector<uint8_t>(m_hash->output_length(), 0x00));
294
0
   m_salt = derive_secret(early_secret, "derived", empty_hash());
295
296
0
   m_state = State::EarlyTraffic;
297
0
   }
298
299
void Cipher_State::advance_with_server_hello(secure_vector<uint8_t>&& shared_secret,
300
      const Transcript_Hash& transcript_hash)
301
0
   {
302
0
   BOTAN_ASSERT_NOMSG(m_state == State::EarlyTraffic);
303
304
0
   const auto handshake_secret = hkdf_extract(std::move(shared_secret));
305
306
0
   const auto client_handshake_traffic_secret = derive_secret(handshake_secret, "c hs traffic", transcript_hash);
307
0
   const auto server_handshake_traffic_secret = derive_secret(handshake_secret, "s hs traffic", transcript_hash);
308
309
0
   if(m_connection_side == Connection_Side::SERVER)
310
0
      {
311
0
      derive_read_traffic_key(client_handshake_traffic_secret, true);
312
0
      derive_write_traffic_key(server_handshake_traffic_secret, true);
313
0
      }
314
0
   else
315
0
      {
316
0
      derive_read_traffic_key(server_handshake_traffic_secret, true);
317
0
      derive_write_traffic_key(client_handshake_traffic_secret, true);
318
0
      }
319
320
0
   m_salt = derive_secret(handshake_secret, "derived", empty_hash());
321
322
0
   m_state = State::HandshakeTraffic;
323
0
   }
324
325
void Cipher_State::derive_write_traffic_key(const secure_vector<uint8_t>& traffic_secret,
326
      const bool handshake_traffic_secret)
327
0
   {
328
0
   m_write_key    = hkdf_expand_label(traffic_secret, "key", {}, m_encrypt->minimum_keylength());
329
0
   m_write_iv     = hkdf_expand_label(traffic_secret, "iv", {}, NONCE_LENGTH);
330
0
   m_write_seq_no = 0;
331
332
0
   if(handshake_traffic_secret)
333
0
      {
334
      // Key derivation for the MAC in the "Finished" handshake message as described in RFC 8446 4.4.4
335
      // (will be cleared in advance_with_server_finished())
336
0
      m_finished_key = hkdf_expand_label(traffic_secret, "finished", {}, m_hash->output_length());
337
0
      }
338
0
   }
339
340
void Cipher_State::derive_read_traffic_key(const secure_vector<uint8_t>& traffic_secret,
341
      const bool handshake_traffic_secret)
342
0
   {
343
0
   m_read_key    = hkdf_expand_label(traffic_secret, "key", {}, m_encrypt->minimum_keylength());
344
0
   m_read_iv     = hkdf_expand_label(traffic_secret, "iv", {}, NONCE_LENGTH);
345
0
   m_read_seq_no = 0;
346
347
0
   if(handshake_traffic_secret)
348
0
      {
349
      // Key derivation for the MAC in the "Finished" handshake message as described in RFC 8446 4.4.4
350
      // (will be cleared in advance_with_server_finished())
351
0
      m_peer_finished_key = hkdf_expand_label(traffic_secret, "finished", {}, m_hash->output_length());
352
0
      }
353
0
   }
354
355
secure_vector<uint8_t> Cipher_State::hkdf_extract(secure_vector<uint8_t>&& ikm) const
356
0
   {
357
0
   return m_extract->derive_key(m_hash->output_length(), ikm, m_salt, std::vector<uint8_t>());
358
0
   }
359
360
secure_vector<uint8_t> Cipher_State::hkdf_expand_label(
361
   const secure_vector<uint8_t>& secret,
362
   const std::string&            label,
363
   const std::vector<uint8_t>&   context,
364
   const size_t                  length) const
365
0
   {
366
   // assemble (serialized) HkdfLabel
367
0
   secure_vector<uint8_t> hkdf_label;
368
0
   hkdf_label.reserve(2 /* length */ +
369
0
                      (label.size() +
370
0
                       6 /* 'tls13 ' */ +
371
0
                       1 /* length field*/) +
372
0
                      (context.size() +
373
0
                       1 /* length field*/));
374
375
   // length
376
0
   BOTAN_ARG_CHECK(length <= std::numeric_limits<uint16_t>::max(), "invalid length");
377
0
   const auto len = static_cast<uint16_t>(length);
378
0
   hkdf_label.push_back(get_byte<0>(len));
379
0
   hkdf_label.push_back(get_byte<1>(len));
380
381
   // label
382
0
   const std::string prefix = "tls13 ";
383
0
   BOTAN_ARG_CHECK(prefix.size() + label.size() <= 255, "label too large");
384
0
   hkdf_label.push_back(static_cast<uint8_t>(prefix.size() + label.size()));
385
0
   hkdf_label.insert(hkdf_label.end(), prefix.cbegin(), prefix.cend());
386
0
   hkdf_label.insert(hkdf_label.end(), label.cbegin(), label.cend());
387
388
   // context
389
0
   BOTAN_ARG_CHECK(context.size() <= 255, "context too large");
390
0
   hkdf_label.push_back(static_cast<uint8_t>(context.size()));
391
0
   hkdf_label.insert(hkdf_label.end(), context.cbegin(), context.cend());
392
393
   // HKDF-Expand
394
0
   return m_expand->derive_key(length, secret, hkdf_label, std::vector<uint8_t>() /* just pleasing botan's interface */);
395
0
   }
396
397
secure_vector<uint8_t> Cipher_State::derive_secret(
398
   const secure_vector<uint8_t>& secret,
399
   const std::string&            label,
400
   const Transcript_Hash&        messages_hash) const
401
0
   {
402
0
   return hkdf_expand_label(secret, label, messages_hash, m_hash->output_length());
403
0
   }
404
405
std::vector<uint8_t> Cipher_State::empty_hash() const
406
0
   {
407
0
   m_hash->update("");
408
0
   return m_hash->final_stdvec();
409
0
   }
410
411
void Cipher_State::update_read_keys()
412
0
   {
413
0
   BOTAN_ASSERT_NOMSG(m_state == State::ApplicationTraffic ||
414
0
                      m_state == State::Completed);
415
416
0
   m_read_application_traffic_secret =
417
0
      hkdf_expand_label(m_read_application_traffic_secret, "traffic upd", {}, m_hash->output_length());
418
419
0
   derive_read_traffic_key(m_read_application_traffic_secret);
420
0
   }
421
422
void Cipher_State::update_write_keys()
423
0
   {
424
0
   BOTAN_ASSERT_NOMSG(m_state == State::ApplicationTraffic ||
425
0
                      m_state == State::Completed);
426
0
   m_write_application_traffic_secret =
427
0
      hkdf_expand_label(m_write_application_traffic_secret, "traffic upd", {}, m_hash->output_length());
428
429
0
   derive_write_traffic_key(m_write_application_traffic_secret);
430
0
   }
431
432
void Cipher_State::clear_read_keys()
433
0
   {
434
0
   zap(m_read_key);
435
0
   zap(m_read_iv);
436
0
   zap(m_read_application_traffic_secret);
437
0
   }
438
439
void Cipher_State::clear_write_keys()
440
0
   {
441
0
   zap(m_write_key);
442
0
   zap(m_write_iv);
443
0
   zap(m_write_application_traffic_secret);
444
0
   }
445
446
}  // namespace Botan::TLS