Botan 3.4.0
Crypto and TLS for C&
tls_cipher_state.h
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#ifndef BOTAN_TLS_CIPHER_STATE_H_
10#define BOTAN_TLS_CIPHER_STATE_H_
11
12#include <botan/secmem.h>
13#include <botan/tls_magic.h>
14#include <botan/tls_messages.h>
15
16#include <botan/internal/tls_transcript_hash_13.h>
17
18namespace Botan {
19
20class AEAD_Mode;
21class HashFunction;
22class HKDF_Extract;
23class HKDF_Expand;
24
25} // namespace Botan
26
27namespace Botan::TLS {
28
29class Ciphersuite;
30
31/**
32 * This class implements the key schedule for TLS 1.3 as described in RFC 8446 7.1.
33 *
34 * Internally, it reflects the state machine pictured in the same RFC section.
35 * It provides the following entry points and state advancement methods that
36 * each facilitate certain cryptographic functionality:
37 *
38 * * init_with_psk()
39 * sets up the cipher state with a pre-shared key (out of band or via session
40 * ticket). will allow sending early data in the future
41 *
42 * * init_with_server_hello() / advance_with_server_hello()
43 * allows encrypting and decrypting handshake traffic, as well as producing
44 * and validating the client/server handshake finished MACs
45 *
46 * * advance_with_server_finished()
47 * allows encrypting and decrypting application traffic
48 *
49 * * advance_with_client_finished()
50 * allows negotiation of resumption PSKs
51 *
52 * While encrypting and decrypting records (RFC 8446 5.2) Cipher_State
53 * internally keeps track of the current sequence numbers (RFC 8446 5.3) to
54 * calculate the correct Per-Record Nonce. Sequence numbers are reset
55 * appropriately, whenever traffic secrets change.
56 *
57 * Handshake finished MAC calculation and verification is described in RFC 8446 4.4.4.
58 *
59 * PSKs calculation is described in RFC 8446 4.6.1.
60 */
62 public:
63 enum class PSK_Type {
64 Resumption,
65 External, // currently not implemented
66 };
67
68 public:
70
71 /**
72 * Construct a Cipher_State from a Pre-Shared-Key.
73 */
74 static std::unique_ptr<Cipher_State> init_with_psk(Connection_Side side,
75 PSK_Type type,
77 std::string_view prf_algo);
78
79 /**
80 * Construct a Cipher_State after receiving a server hello message.
81 */
82 static std::unique_ptr<Cipher_State> init_with_server_hello(Connection_Side side,
83 secure_vector<uint8_t>&& shared_secret,
84 const Ciphersuite& cipher,
85 const Transcript_Hash& transcript_hash);
86
87 /**
88 * Transition internal secrets/keys for transporting early application data.
89 * Note that this state transition is legal only for handshakes using PSK.
90 */
91 void advance_with_client_hello(const Transcript_Hash& transcript_hash);
92
93 /**
94 * Transition internal secrets/keys for transporting handshake data.
95 */
96 void advance_with_server_hello(const Ciphersuite& cipher,
97 secure_vector<uint8_t>&& shared_secret,
98 const Transcript_Hash& transcript_hash);
99
100 /**
101 * Transition internal secrets/keys for transporting application data.
102 */
103 void advance_with_server_finished(const Transcript_Hash& transcript_hash);
104
105 /**
106 * Transition to the final internal state allowing to create resumptions.
107 */
108 void advance_with_client_finished(const Transcript_Hash& transcript_hash);
109
110 /**
111 * Encrypt a TLS record fragment (RFC 8446 5.2 -- TLSInnerPlaintext) using the
112 * currently available traffic secret keys and the current sequence number.
113 * This will internally increment the sequence number. Hence, multiple
114 * calls with the same input will not produce the same result.
115 *
116 * @returns the sequence number of the encrypted record
117 */
118 uint64_t encrypt_record_fragment(const std::vector<uint8_t>& header, secure_vector<uint8_t>& fragment);
119
120 /**
121 * Decrypt a TLS record fragment (RFC 8446 5.2 -- TLSCiphertext.encrypted_record)
122 * using the currently available traffic secret keys and the current sequence number.
123 * This will internally increment the sequence number. Hence, multiple
124 * calls with the same input will not produce the same result.
125 *
126 * @returns the sequence number of the decrypted record
127 */
128 uint64_t decrypt_record_fragment(const std::vector<uint8_t>& header, secure_vector<uint8_t>& encrypted_fragment);
129
130 /**
131 * @returns number of bytes needed to encrypt \p input_length bytes
132 */
133 size_t encrypt_output_length(size_t input_length) const;
134
135 /**
136 * @returns number of bytes needed to decrypt \p input_length bytes
137 */
138 size_t decrypt_output_length(size_t input_length) const;
139
140 /**
141 * @returns the minimum ciphertext length for decryption
142 */
143 size_t minimum_decryption_input_length() const;
144
145 /**
146 * Calculates the MAC for a PSK binder value in Client Hellos. Note that
147 * the transcript hash passed into this method is computed from a partial
148 * Client Hello (RFC 8446 4.2.11.2)
149 */
150 std::vector<uint8_t> psk_binder_mac(const Transcript_Hash& transcript_hash_with_truncated_client_hello) const;
151
152 /**
153 * Calculate the MAC for a TLS "Finished" handshake message (RFC 8446 4.4.4)
154 */
155 std::vector<uint8_t> finished_mac(const Transcript_Hash& transcript_hash) const;
156
157 /**
158 * Validate a MAC received in a TLS "Finished" handshake message (RFC 8446 4.4.4)
159 */
160 bool verify_peer_finished_mac(const Transcript_Hash& transcript_hash, const std::vector<uint8_t>& peer_mac) const;
161
162 /**
163 * Calculate the PSK for the given nonce (RFC 8446 4.6.1)
164 */
165 secure_vector<uint8_t> psk(const Ticket_Nonce& nonce) const;
166
167 /**
168 * Generates a nonce value that is unique for any given Cipher_State object.
169 * Note that the number of nonces is limited to 2^16 and this method will
170 * throw if more nonces are requested.
171 */
172 Ticket_Nonce next_ticket_nonce();
173
174 /**
175 * Derive key material to export (RFC 8446 7.5 and RFC 5705)
176 *
177 * TODO: this does not yet support key export based on the `early_exporter_master_secret`.
178 *
179 * RFC 8446 7.5
180 * Implementations MUST use the exporter_master_secret unless explicitly
181 * specified by the application. The early_exporter_master_secret is
182 * defined for use in settings where an exporter is needed for 0-RTT data.
183 * A separate interface for the early exporter is RECOMMENDED [...].
184 *
185 * @param label a disambiguating label string
186 * @param context a per-association context value
187 * @param length the length of the desired key in bytes
188 * @return key of length bytes
189 */
190 secure_vector<uint8_t> export_key(std::string_view label, std::string_view context, size_t length) const;
191
192 /**
193 * Indicates whether the appropriate secrets to export keys are available
194 */
195 bool can_export_keys() const {
196 return (m_state == State::EarlyTraffic || m_state == State::ServerApplicationTraffic ||
197 m_state == State::Completed) &&
198 !m_exporter_master_secret.empty();
199 }
200
201 /**
202 * Indicates whether unprotected Alert records are to be expected
203 */
204 bool must_expect_unprotected_alert_traffic() const;
205
206 /**
207 * Indicates whether the appropriate secrets to encrypt application traffic are available
208 */
209 bool can_encrypt_application_traffic() const;
210
211 /**
212 * Indicates whether the appropriate secrets to decrypt application traffic are available
213 */
214 bool can_decrypt_application_traffic() const;
215
216 /**
217 * The name of the hash algorithm used for the KDF in this cipher suite
218 */
219 std::string hash_algorithm() const;
220
221 /**
222 * @returns true if the selected cipher primitives are compatible with
223 * the \p cipher suite.
224 *
225 * Note that cipher suites are considered "compatible" as long as the
226 * already selected cipher primitives in this cipher state are compatible.
227 */
228 bool is_compatible_with(const Ciphersuite& cipher) const;
229
230 /**
231 * Updates the key material used for decrypting data
232 * This is triggered after we received a Key_Update from the peer.
233 *
234 * Note that this must not be called before the connection is ready for
235 * application traffic.
236 */
237 void update_read_keys();
238
239 /**
240 * Updates the key material used for encrypting data
241 * This is triggered after we send a Key_Update to the peer.
242 *
243 * Note that this must not be called before the connection is ready for
244 * application traffic.
245 */
246 void update_write_keys();
247
248 /**
249 * Remove handshake/traffic secrets for decrypting data from peer
250 */
251 void clear_read_keys();
252
253 /**
254 * Remove handshake/traffic secrets for encrypting data
255 */
256 void clear_write_keys();
257
258 private:
259 /**
260 * @param whoami whether we play the Server or Client
261 * @param hash_function the negotiated hash function to be used
262 */
263 Cipher_State(Connection_Side whoami, std::string_view hash_function);
264
265 void advance_with_psk(PSK_Type type, secure_vector<uint8_t>&& psk);
266 void advance_without_psk();
267
268 void derive_write_traffic_key(const secure_vector<uint8_t>& traffic_secret,
269 bool handshake_traffic_secret = false);
270 void derive_read_traffic_key(const secure_vector<uint8_t>& traffic_secret, bool handshake_traffic_secret = false);
271
272 /**
273 * HKDF-Extract from RFC 8446 7.1
274 */
275 secure_vector<uint8_t> hkdf_extract(secure_vector<uint8_t>&& ikm) const;
276
277 /**
278 * HKDF-Expand-Label from RFC 8446 7.1
279 */
281 std::string_view label,
282 const std::vector<uint8_t>& context,
283 size_t length) const;
284
285 /**
286 * Derive-Secret from RFC 8446 7.1
287 */
288 secure_vector<uint8_t> derive_secret(const secure_vector<uint8_t>& secret,
289 std::string_view label,
290 const Transcript_Hash& messages_hash) const;
291
292 std::vector<uint8_t> empty_hash() const;
293
294 private:
295 enum class State {
296 Uninitialized,
297 PskBinder,
298 EarlyTraffic,
299 HandshakeTraffic,
300 ServerApplicationTraffic,
301 Completed
302 };
303
304 private:
305 State m_state;
306 Connection_Side m_connection_side;
307
308 std::unique_ptr<AEAD_Mode> m_encrypt;
309 std::unique_ptr<AEAD_Mode> m_decrypt;
310
311 std::unique_ptr<HKDF_Extract> m_extract;
312 std::unique_ptr<HKDF_Expand> m_expand;
313 std::unique_ptr<HashFunction> m_hash;
314
316
317 secure_vector<uint8_t> m_write_application_traffic_secret;
318 secure_vector<uint8_t> m_read_application_traffic_secret;
319
320 secure_vector<uint8_t> m_write_key;
321 secure_vector<uint8_t> m_write_iv;
322 secure_vector<uint8_t> m_read_key;
323 secure_vector<uint8_t> m_read_iv;
324
325 uint64_t m_write_seq_no;
326 uint64_t m_read_seq_no;
327
328 uint16_t m_ticket_nonce;
329
330 secure_vector<uint8_t> m_finished_key;
331 secure_vector<uint8_t> m_peer_finished_key;
332 secure_vector<uint8_t> m_exporter_master_secret;
333 secure_vector<uint8_t> m_resumption_master_secret;
334
335 secure_vector<uint8_t> m_early_secret;
336 secure_vector<uint8_t> m_binder_key;
337};
338
339} // namespace Botan::TLS
340
341#endif // BOTAN_TLS_CIPHER_STATE_H_
CCCryptorRef m_encrypt
CCCryptorRef m_decrypt
#define BOTAN_TEST_API
Definition compiler.h:51
std::vector< uint8_t > Transcript_Hash
Definition tls_magic.h:81
secure_vector< uint8_t > hkdf_expand_label(std::string_view hash_fn, const uint8_t secret[], size_t secret_len, std::string_view label, const uint8_t hash_val[], size_t hash_val_len, size_t length)
Definition hkdf.cpp:131
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61