/src/botan/build/include/botan/internal/tls_cipher_state.h
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 | | #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 | | |
15 | | #include <botan/internal/tls_transcript_hash_13.h> |
16 | | |
17 | | namespace Botan { |
18 | | |
19 | | class AEAD_Mode; |
20 | | class HashFunction; |
21 | | class HKDF_Extract; |
22 | | class HKDF_Expand; |
23 | | |
24 | | } |
25 | | |
26 | | namespace Botan::TLS { |
27 | | |
28 | | class Ciphersuite; |
29 | | |
30 | | /** |
31 | | * This class implements the key schedule for TLS 1.3 as described in RFC 8446 7.1. |
32 | | * |
33 | | * Internally, it reflects the state machine pictured in the same RFC section. |
34 | | * It provides the following entry points and state advancement methods that |
35 | | * each facilitate certain cryptographic functionality: |
36 | | * |
37 | | * * init_with_psk() |
38 | | * not yet implemented |
39 | | * |
40 | | * * init_with_server_hello() / advance_with_server_hello() |
41 | | * allows encrypting and decrypting handshake traffic, as well as producing |
42 | | * and validating the client/server handshake finished MACs |
43 | | * |
44 | | * * advance_with_server_finished() |
45 | | * allows encrypting and decrypting application traffic |
46 | | * |
47 | | * * advance_with_client_finished() |
48 | | * allows negotiation of resumption PSKs |
49 | | * |
50 | | * While encrypting and decrypting records (RFC 8446 5.2) Cipher_State |
51 | | * internally keeps track of the current sequence numbers (RFC 8446 5.3) to |
52 | | * calculate the correct Per-Record Nonce. Sequence numbers are reset |
53 | | * appropriately, whenever traffic secrets change. |
54 | | * |
55 | | * Handshake finished MAC calculation and verification is described in RFC 8446 4.4.4. |
56 | | * |
57 | | * PSKs calculation is described in RFC 8446 4.6.1. |
58 | | */ |
59 | | class BOTAN_TEST_API Cipher_State |
60 | | { |
61 | | public: |
62 | | ~Cipher_State(); |
63 | | |
64 | | /** |
65 | | * Construct a Cipher_State after receiving a server hello message. |
66 | | */ |
67 | | static std::unique_ptr<Cipher_State> init_with_server_hello( |
68 | | const Connection_Side side, |
69 | | secure_vector<uint8_t>&& shared_secret, |
70 | | const Ciphersuite& cipher, |
71 | | const Transcript_Hash& transcript_hash); |
72 | | |
73 | | /** |
74 | | * Transition internal secrets/keys for transporting application data. |
75 | | */ |
76 | | void advance_with_server_finished(const Transcript_Hash& transcript_hash); |
77 | | |
78 | | /** |
79 | | * Transition to the final internal state allowing to create resumptions. |
80 | | */ |
81 | | void advance_with_client_finished(const Transcript_Hash& transcript_hash); |
82 | | |
83 | | /** |
84 | | * Encrypt a TLS record fragment (RFC 8446 5.2 -- TLSInnerPlaintext) using the |
85 | | * currently available traffic secret keys and the current sequence number. |
86 | | * This will internally increment the sequence number. Hence, multiple |
87 | | * calls with the same input will not produce the same result. |
88 | | * |
89 | | * @returns the sequence number of the encrypted record |
90 | | */ |
91 | | uint64_t encrypt_record_fragment(const std::vector<uint8_t>& header, secure_vector<uint8_t>& fragment); |
92 | | |
93 | | /** |
94 | | * Decrypt a TLS record fragment (RFC 8446 5.2 -- TLSCiphertext.encrypted_record) |
95 | | * using the currently available traffic secret keys and the current sequence number. |
96 | | * This will internally increment the sequence number. Hence, multiple |
97 | | * calls with the same input will not produce the same result. |
98 | | * |
99 | | * @returns the sequence number of the decrypted record |
100 | | */ |
101 | | uint64_t decrypt_record_fragment(const std::vector<uint8_t>& header, secure_vector<uint8_t>& encrypted_fragment); |
102 | | |
103 | | /** |
104 | | * @returns number of bytes needed to encrypt \p input_length bytes |
105 | | */ |
106 | | size_t encrypt_output_length(const size_t input_length) const; |
107 | | |
108 | | /** |
109 | | * @returns number of bytes needed to decrypt \p input_length bytes |
110 | | */ |
111 | | size_t decrypt_output_length(const size_t input_length) const; |
112 | | |
113 | | /** |
114 | | * @returns the minimum ciphertext length for decryption |
115 | | */ |
116 | | size_t minimum_decryption_input_length() const; |
117 | | |
118 | | /** |
119 | | * Calculate the MAC for a TLS "Finished" handshake message (RFC 8446 4.4.4) |
120 | | */ |
121 | | std::vector<uint8_t> finished_mac(const Transcript_Hash& transcript_hash) const; |
122 | | |
123 | | /** |
124 | | * Validate a MAC received in a TLS "Finished" handshake message (RFC 8446 4.4.4) |
125 | | */ |
126 | | bool verify_peer_finished_mac(const Transcript_Hash& transcript_hash, |
127 | | const std::vector<uint8_t>& peer_mac) const; |
128 | | |
129 | | /** |
130 | | * Calculate the PSK for the given nonce (RFC 8446 4.6.1) |
131 | | */ |
132 | | secure_vector<uint8_t> psk(const std::vector<uint8_t>& nonce) const; |
133 | | |
134 | | /** |
135 | | * Derive key material to export (RFC 8446 7.5 and RFC 5705) |
136 | | * |
137 | | * TODO: this does not yet support key export based on the `early_exporter_master_secret`. |
138 | | * |
139 | | * RFC 8446 7.5 |
140 | | * Implementations MUST use the exporter_master_secret unless explicitly |
141 | | * specified by the application. The early_exporter_master_secret is |
142 | | * defined for use in settings where an exporter is needed for 0-RTT data. |
143 | | * A separate interface for the early exporter is RECOMMENDED [...]. |
144 | | * |
145 | | * @param label a disambiguating label string |
146 | | * @param context a per-association context value |
147 | | * @param length the length of the desired key in bytes |
148 | | * @return key of length bytes |
149 | | */ |
150 | | secure_vector<uint8_t> export_key(const std::string& label, |
151 | | const std::string& context, |
152 | | size_t length) const; |
153 | | |
154 | | /** |
155 | | * Indicates whether the appropriate secrets to export keys are available |
156 | | */ |
157 | | bool can_export_keys() const |
158 | 0 | { |
159 | 0 | return (m_state == State::ApplicationTraffic || m_state == State::Completed) && |
160 | 0 | !m_exporter_master_secret.empty(); |
161 | 0 | } |
162 | | |
163 | | /** |
164 | | * Indicates whether the appropriate secrets to encrypt application traffic are available |
165 | | */ |
166 | | bool can_encrypt_application_traffic() const |
167 | 0 | { |
168 | 0 | return m_state != State::Uninitialized && m_state != State::HandshakeTraffic |
169 | 0 | && !m_write_key.empty() && !m_write_iv.empty(); |
170 | 0 | } |
171 | | |
172 | | /** |
173 | | * Updates the key material used for decrypting data |
174 | | * This is triggered after we received a Key_Update from the peer. |
175 | | * |
176 | | * Note that this must not be called before the connection is ready for |
177 | | * application traffic. |
178 | | */ |
179 | | void update_read_keys(); |
180 | | |
181 | | /** |
182 | | * Updates the key material used for encrypting data |
183 | | * This is triggered after we send a Key_Update to the peer. |
184 | | * |
185 | | * Note that this must not be called before the connection is ready for |
186 | | * application traffic. |
187 | | */ |
188 | | void update_write_keys(); |
189 | | |
190 | | /** |
191 | | * Remove handshake/traffic secrets for decrypting data from peer |
192 | | */ |
193 | | void clear_read_keys(); |
194 | | |
195 | | /** |
196 | | * Remove handshake/traffic secrets for encrypting data |
197 | | */ |
198 | | void clear_write_keys(); |
199 | | |
200 | | private: |
201 | | /** |
202 | | * @param cipher the negotiated cipher suite |
203 | | * @param whoami whether we play the SERVER or CLIENT |
204 | | */ |
205 | | Cipher_State(Connection_Side whoami, const Ciphersuite& cipher); |
206 | | |
207 | | void advance_without_psk(); |
208 | | |
209 | | void advance_with_server_hello(secure_vector<uint8_t>&& shared_secret, |
210 | | const Transcript_Hash& transcript_hash); |
211 | | |
212 | | std::vector<uint8_t> current_nonce(const uint64_t seq_no, |
213 | | const secure_vector<uint8_t>& iv) const; |
214 | | |
215 | | void derive_write_traffic_key(const secure_vector<uint8_t>& traffic_secret, |
216 | | const bool handshake_traffic_secret = false); |
217 | | void derive_read_traffic_key(const secure_vector<uint8_t>& traffic_secret, |
218 | | const bool handshake_traffic_secret = false); |
219 | | |
220 | | /** |
221 | | * HKDF-Extract from RFC 8446 7.1 |
222 | | */ |
223 | | secure_vector<uint8_t> hkdf_extract(secure_vector<uint8_t>&& ikm) const; |
224 | | |
225 | | /** |
226 | | * HKDF-Expand-Label from RFC 8446 7.1 |
227 | | */ |
228 | | secure_vector<uint8_t> hkdf_expand_label( |
229 | | const secure_vector<uint8_t>& secret, |
230 | | const std::string& label, |
231 | | const std::vector<uint8_t>& context, |
232 | | const size_t length) const; |
233 | | |
234 | | /** |
235 | | * Derive-Secret from RFC 8446 7.1 |
236 | | */ |
237 | | secure_vector<uint8_t> derive_secret( |
238 | | const secure_vector<uint8_t>& secret, |
239 | | const std::string& label, |
240 | | const Transcript_Hash& messages_hash) const; |
241 | | |
242 | | std::vector<uint8_t> empty_hash() const; |
243 | | |
244 | | private: |
245 | | enum class State |
246 | | { |
247 | | Uninitialized, |
248 | | EarlyTraffic, |
249 | | HandshakeTraffic, |
250 | | ApplicationTraffic, |
251 | | Completed |
252 | | }; |
253 | | |
254 | | private: |
255 | | State m_state; |
256 | | Connection_Side m_connection_side; |
257 | | |
258 | | std::unique_ptr<AEAD_Mode> m_encrypt; |
259 | | std::unique_ptr<AEAD_Mode> m_decrypt; |
260 | | |
261 | | std::unique_ptr<HKDF_Extract> m_extract; |
262 | | std::unique_ptr<HKDF_Expand> m_expand; |
263 | | std::unique_ptr<HashFunction> m_hash; |
264 | | |
265 | | secure_vector<uint8_t> m_salt; |
266 | | |
267 | | secure_vector<uint8_t> m_write_application_traffic_secret; |
268 | | secure_vector<uint8_t> m_read_application_traffic_secret; |
269 | | |
270 | | secure_vector<uint8_t> m_write_key; |
271 | | secure_vector<uint8_t> m_write_iv; |
272 | | secure_vector<uint8_t> m_read_key; |
273 | | secure_vector<uint8_t> m_read_iv; |
274 | | |
275 | | uint64_t m_write_seq_no; |
276 | | uint64_t m_read_seq_no; |
277 | | |
278 | | secure_vector<uint8_t> m_finished_key; |
279 | | secure_vector<uint8_t> m_peer_finished_key; |
280 | | secure_vector<uint8_t> m_exporter_master_secret; |
281 | | secure_vector<uint8_t> m_resumption_master_secret; |
282 | | }; |
283 | | |
284 | | } |
285 | | |
286 | | #endif // BOTAN_TLS_CIPHER_STATE_H_ |