Branch data Line data Source code
1 : : /*
2 : : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License").
5 : : * You may not use this file except in compliance with the License.
6 : : * A copy of the License is located at
7 : : *
8 : : * http://aws.amazon.com/apache2.0
9 : : *
10 : : * or in the "license" file accompanying this file. This file is distributed
11 : : * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 : : * express or implied. See the License for the specific language governing
13 : : * permissions and limitations under the License.
14 : : */
15 : :
16 : : #include "tls/s2n_ktls.h"
17 : :
18 : : #include "crypto/s2n_ktls_crypto.h"
19 : : #include "crypto/s2n_sequence.h"
20 : : #include "tls/s2n_key_update.h"
21 : : #include "tls/s2n_prf.h"
22 : : #include "tls/s2n_tls.h"
23 : : #include "tls/s2n_tls13_handshake.h"
24 : : #include "tls/s2n_tls13_key_schedule.h"
25 : :
26 : : /* Used for overriding setsockopt calls in testing */
27 : : s2n_setsockopt_fn s2n_setsockopt = setsockopt;
28 : :
29 : : S2N_RESULT s2n_ktls_set_setsockopt_cb(s2n_setsockopt_fn cb)
30 : 24 : {
31 [ - + ][ # # ]: 24 : RESULT_ENSURE(s2n_in_test(), S2N_ERR_NOT_IN_TEST);
32 : 24 : s2n_setsockopt = cb;
33 : 24 : return S2N_RESULT_OK;
34 : 24 : }
35 : :
36 : : bool s2n_ktls_is_supported_on_platform()
37 : 39 : {
38 : 39 : #if defined(S2N_KTLS_SUPPORTED)
39 : 39 : return true;
40 : : #else
41 : : return false;
42 : : #endif
43 : 39 : }
44 : :
45 : : static int s2n_ktls_disabled_read(void *io_context, uint8_t *buf, uint32_t len)
46 : 0 : {
47 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_IO);
48 : 0 : }
49 : :
50 : : static S2N_RESULT s2n_ktls_validate(struct s2n_connection *conn, s2n_ktls_mode ktls_mode)
51 : 37 : {
52 [ - + ][ # # ]: 37 : RESULT_ENSURE_REF(conn);
53 : 37 : const struct s2n_config *config = conn->config;
54 [ - + ][ # # ]: 37 : RESULT_ENSURE_REF(config);
55 : :
56 [ # # ][ - + ]: 37 : RESULT_ENSURE(s2n_ktls_is_supported_on_platform(), S2N_ERR_KTLS_UNSUPPORTED_PLATFORM);
57 : :
58 : : /* kTLS enable should only be called once the handshake has completed. */
59 [ + - ][ + + ]: 37 : RESULT_ENSURE(is_handshake_complete(conn), S2N_ERR_HANDSHAKE_NOT_COMPLETE);
60 : :
61 : : /* kTLS uses the prf_space to recalculate the keys, but the prf_space may be
62 : : * freed by s2n_connection_free_handshake to reduce the connection size.
63 : : * Explicitly check for prf_space here to avoid a confusing S2N_ERR_NULL later.
64 : : */
65 [ # # ][ - + ]: 35 : RESULT_ENSURE(conn->prf_space, S2N_ERR_INVALID_STATE);
66 : :
67 : : /* For now, only allow TlS1.3 if explicitly enabled.
68 : : *
69 : : * TLS1.3 is potentially more dangerous to enable than TLS1.2, since the kernel
70 : : * does not currently support updating TLS keys and therefore will fail if
71 : : * KeyUpdate messages are encountered.
72 : : */
73 [ + + ]: 35 : bool version_supported = (conn->actual_protocol_version == S2N_TLS12)
74 [ + + ][ + - ]: 35 : || (conn->config->ktls_tls13_enabled && conn->actual_protocol_version == S2N_TLS13);
75 [ + + ][ + - ]: 35 : RESULT_ENSURE(version_supported, S2N_ERR_KTLS_UNSUPPORTED_CONN);
76 : :
77 : : /* Check if the cipher supports kTLS */
78 : 32 : const struct s2n_cipher *cipher = NULL;
79 [ - + ]: 32 : RESULT_GUARD(s2n_connection_get_secure_cipher(conn, &cipher));
80 [ - + ][ # # ]: 32 : RESULT_ENSURE_REF(cipher);
81 [ + - ][ + + ]: 32 : RESULT_ENSURE(cipher->set_ktls_info, S2N_ERR_KTLS_UNSUPPORTED_CONN);
82 : :
83 : : /* Renegotiation requires updating the keys, which kTLS doesn't currently support.
84 : : *
85 : : * Setting the renegotiation callback doesn't guarantee that a client will
86 : : * attempt to renegotiate. The callback can also be used to send warning alerts
87 : : * signaling that renegotiation was rejected. However, we can provide applications
88 : : * with a clearer signal earlier by preventing them from enabling ktls on a
89 : : * connection that MIGHT require renegotiation. We can relax this restriction
90 : : * later if necessary.
91 : : */
92 : 30 : bool may_receive_hello_request = s2n_result_is_ok(s2n_client_hello_request_validate(conn));
93 [ + + ][ + + ]: 30 : bool may_renegotiate = may_receive_hello_request && config->renegotiate_request_cb;
94 [ + + ][ + - ]: 30 : RESULT_ENSURE(!may_renegotiate, S2N_ERR_KTLS_RENEG);
95 : :
96 : : /* Prevent kTLS from being enabled on connections that might be serialized.
97 : : *
98 : : * The socket takes over tracking sequence numbers when kTLS is enabled.
99 : : * We would need to call getsockopt to retrieve the current sequence numbers for
100 : : * serialization. This would complicate the serialization implementation so
101 : : * for now, do not support kTLS with serialization.
102 : : */
103 [ + - ][ + + ]: 29 : RESULT_ENSURE(config->serialized_connection_version == S2N_SERIALIZED_CONN_NONE,
104 : 28 : S2N_ERR_KTLS_UNSUPPORTED_CONN);
105 : :
106 : : /* kTLS I/O functionality is managed by s2n-tls. kTLS cannot be enabled if the
107 : : * application sets custom I/O (managed_send_io == false means application has
108 : : * set custom I/O).
109 : : */
110 : 28 : switch (ktls_mode) {
111 [ + + ]: 12 : case S2N_KTLS_MODE_SEND:
112 [ + + ][ + - ]: 12 : RESULT_ENSURE(conn->managed_send_io, S2N_ERR_KTLS_MANAGED_IO);
113 : : /* The output stuffer should be empty before enabling kTLS. */
114 [ + + ][ + - ]: 11 : RESULT_ENSURE(s2n_stuffer_is_consumed(&conn->out), S2N_ERR_RECORD_STUFFER_NEEDS_DRAINING);
115 : 10 : break;
116 [ + + ]: 16 : case S2N_KTLS_MODE_RECV:
117 [ + - ][ + + ]: 16 : RESULT_ENSURE(conn->managed_recv_io, S2N_ERR_KTLS_MANAGED_IO);
118 : : /* The input stuffers should be empty before enabling kTLS. */
119 [ + + ][ + - ]: 15 : RESULT_ENSURE(s2n_stuffer_is_consumed(&conn->header_in), S2N_ERR_RECORD_STUFFER_NEEDS_DRAINING);
120 [ + - ][ + + ]: 14 : RESULT_ENSURE(s2n_stuffer_is_consumed(&conn->in), S2N_ERR_RECORD_STUFFER_NEEDS_DRAINING);
121 [ + - ][ + + ]: 13 : RESULT_ENSURE(s2n_stuffer_is_consumed(&conn->buffer_in), S2N_ERR_KTLS_UNSUPPORTED_CONN);
122 : 12 : break;
123 [ - + ]: 12 : default:
124 [ # # ]: 0 : RESULT_BAIL(S2N_ERR_SAFETY);
125 : 0 : break;
126 : 28 : }
127 : :
128 : 22 : return S2N_RESULT_OK;
129 : 28 : }
130 : :
131 : : /* Enabling kTLS preserves the original *io_context; making this functions
132 : : * safe to call even after kTLS has been enabled on the connection.
133 : : *
134 : : * Retrieving fd assumes that the connection is using socket IO and has the
135 : : * send_io_context set. While kTLS overrides IO and essentially disables
136 : : * the socket conn->send function callback, it doesn't modify the
137 : : * send_io_context. */
138 : : S2N_RESULT s2n_ktls_get_file_descriptor(struct s2n_connection *conn, s2n_ktls_mode ktls_mode, int *fd)
139 : 1506 : {
140 [ # # ][ - + ]: 1506 : RESULT_ENSURE_REF(conn);
141 [ - + ][ # # ]: 1506 : RESULT_ENSURE_REF(fd);
142 : :
143 [ + + ]: 1506 : if (ktls_mode == S2N_KTLS_MODE_RECV) {
144 [ - + ]: 12 : RESULT_GUARD_POSIX(s2n_connection_get_read_fd(conn, fd));
145 [ + - ]: 1494 : } else if (ktls_mode == S2N_KTLS_MODE_SEND) {
146 [ - + ]: 1494 : RESULT_GUARD_POSIX(s2n_connection_get_write_fd(conn, fd));
147 : 1494 : }
148 : 1506 : return S2N_RESULT_OK;
149 : 1506 : }
150 : :
151 : : static S2N_RESULT s2n_ktls_get_io_mode(s2n_ktls_mode ktls_mode, int *tls_tx_rx_mode)
152 : 22 : {
153 [ - + ][ # # ]: 22 : RESULT_ENSURE_REF(tls_tx_rx_mode);
154 : :
155 [ + + ]: 22 : if (ktls_mode == S2N_KTLS_MODE_SEND) {
156 : 10 : *tls_tx_rx_mode = S2N_TLS_TX;
157 : 12 : } else {
158 : 12 : *tls_tx_rx_mode = S2N_TLS_RX;
159 : 12 : }
160 : 22 : return S2N_RESULT_OK;
161 : 22 : }
162 : :
163 : : static S2N_RESULT s2n_ktls_crypto_info_init(struct s2n_connection *conn, s2n_ktls_mode ktls_mode,
164 : : struct s2n_ktls_crypto_info *crypto_info)
165 : 22 : {
166 [ # # ][ - + ]: 22 : RESULT_ENSURE_REF(conn);
167 : 22 : struct s2n_crypto_parameters *secure = conn->secure;
168 [ - + ][ # # ]: 22 : RESULT_ENSURE_REF(secure);
169 : :
170 : : /* In order to avoid storing the encryption keys on the connection, we instead
171 : : * regenerate them when required by ktls.
172 : : *
173 : : * s2n_key_material also includes an IV, but we should use the IV stored
174 : : * on the connection instead. Some record algorithms (like CBC) mutate the
175 : : * "implicit_iv" when writing records, so the IV may change after generation.
176 : : */
177 : 22 : struct s2n_key_material key_material = { 0 };
178 : :
179 : 22 : bool is_sending_key = (ktls_mode == S2N_KTLS_MODE_SEND);
180 [ + + ]: 22 : s2n_mode key_mode = (is_sending_key) ? conn->mode : S2N_PEER_MODE(conn->mode);
181 : :
182 : 22 : switch (conn->actual_protocol_version) {
183 [ + + ]: 21 : case S2N_TLS12:
184 [ - + ]: 21 : RESULT_GUARD(s2n_prf_generate_key_material(conn, &key_material));
185 : 21 : break;
186 [ + + ]: 21 : case S2N_TLS13:
187 [ - + ]: 1 : RESULT_GUARD(s2n_tls13_key_schedule_generate_key_material(
188 : 1 : conn, key_mode, &key_material));
189 : 1 : break;
190 [ - + ]: 1 : default:
191 [ # # ]: 0 : RESULT_BAIL(S2N_ERR_KTLS_UNSUPPORTED_CONN);
192 : 22 : }
193 : :
194 : 22 : struct s2n_ktls_crypto_info_inputs inputs = { 0 };
195 [ + + ]: 22 : if (key_mode == S2N_CLIENT) {
196 : 11 : inputs.key = key_material.client_key;
197 [ - + ]: 11 : RESULT_GUARD_POSIX(s2n_blob_init(&inputs.iv,
198 : 11 : secure->client_implicit_iv, sizeof(secure->client_implicit_iv)));
199 : 11 : } else {
200 : 11 : inputs.key = key_material.server_key;
201 [ - + ]: 11 : RESULT_GUARD_POSIX(s2n_blob_init(&inputs.iv,
202 : 11 : secure->server_implicit_iv, sizeof(secure->server_implicit_iv)));
203 : 11 : }
204 [ - + ]: 22 : RESULT_GUARD(s2n_connection_get_sequence_number(conn, key_mode, &inputs.seq));
205 : :
206 : 22 : const struct s2n_cipher *cipher = NULL;
207 [ - + ]: 22 : RESULT_GUARD(s2n_connection_get_secure_cipher(conn, &cipher));
208 [ - + ][ # # ]: 22 : RESULT_ENSURE_REF(cipher);
209 [ - + ][ # # ]: 22 : RESULT_ENSURE_REF(cipher->set_ktls_info);
210 [ - + ]: 22 : RESULT_GUARD(cipher->set_ktls_info(&inputs, crypto_info));
211 : 22 : return S2N_RESULT_OK;
212 : 22 : }
213 : :
214 : : /* This method intentionally returns void because it may NOT perform any fallible
215 : : * operations. See s2n_connection_ktls_enable.
216 : : */
217 : : void s2n_ktls_configure_connection(struct s2n_connection *conn, s2n_ktls_mode ktls_mode)
218 : 41 : {
219 [ - + ]: 41 : if (conn == NULL) {
220 : 0 : return;
221 : 0 : }
222 [ + + ]: 41 : if (ktls_mode == S2N_KTLS_MODE_SEND) {
223 : 16 : conn->ktls_send_enabled = true;
224 : 16 : conn->send = s2n_ktls_send_cb;
225 : 25 : } else {
226 : 25 : conn->ktls_recv_enabled = true;
227 : 25 : conn->recv = s2n_ktls_disabled_read;
228 : 25 : }
229 : 41 : }
230 : :
231 : : static S2N_RESULT s2n_connection_ktls_enable(struct s2n_connection *conn, s2n_ktls_mode ktls_mode)
232 : 37 : {
233 [ # # ][ - + ]: 37 : RESULT_ENSURE_REF(conn);
234 [ + + ]: 37 : RESULT_GUARD(s2n_ktls_validate(conn, ktls_mode));
235 : :
236 : 22 : int fd = 0;
237 [ - + ]: 22 : RESULT_GUARD(s2n_ktls_get_file_descriptor(conn, ktls_mode, &fd));
238 : :
239 : : /* This call doesn't actually enable ktls or modify the IO behavior of the socket.
240 : : * Instead, this is just a prerequisite for calling setsockopt with SOL_TLS.
241 : : *
242 : : * We intentionally ignore the result of this call. It may fail because ktls
243 : : * is not supported, but it might also fail because ktls has already been enabled
244 : : * for the socket. If SOL_TLS isn't enabled on the socket, our next call to
245 : : * setsockopt with SOL_TLS will also fail, and we DO check that result.
246 : : */
247 : 22 : s2n_setsockopt(fd, S2N_SOL_TCP, S2N_TCP_ULP, S2N_TLS_ULP_NAME, S2N_TLS_ULP_NAME_SIZE);
248 : :
249 : 22 : int tls_tx_rx_mode = 0;
250 [ - + ]: 22 : RESULT_GUARD(s2n_ktls_get_io_mode(ktls_mode, &tls_tx_rx_mode));
251 : :
252 : 22 : struct s2n_ktls_crypto_info crypto_info = { 0 };
253 [ - + ]: 22 : RESULT_GUARD(s2n_ktls_crypto_info_init(conn, ktls_mode, &crypto_info));
254 : :
255 : : /* If this call succeeds, then ktls is enabled for that io mode and will be offloaded */
256 : 22 : int ret = s2n_setsockopt(fd, S2N_SOL_TLS, tls_tx_rx_mode, crypto_info.value.data, crypto_info.value.size);
257 [ + + ][ + - ]: 22 : RESULT_ENSURE(ret == 0, S2N_ERR_KTLS_ENABLE);
258 : :
259 : : /* At this point, ktls is enabled on the socket for the requested IO mode.
260 : : * No further fallible operations may be performed, or else the caller may
261 : : * incorrectly assume that enabling ktls failed and they should therefore
262 : : * fall back to using application layer TLS.
263 : : *
264 : : * That means no calls to RESULT_ENSURE, RESULT_GUARD, etc. after this point.
265 : : */
266 : :
267 : 18 : s2n_ktls_configure_connection(conn, ktls_mode);
268 : 18 : return S2N_RESULT_OK;
269 : 22 : }
270 : :
271 : : int s2n_connection_ktls_enable_send(struct s2n_connection *conn)
272 : 18 : {
273 [ # # ][ - + ]: 18 : POSIX_ENSURE_REF(conn);
274 : :
275 : : /* If already enabled then return success */
276 [ + + ]: 18 : if (conn->ktls_send_enabled) {
277 : 1 : return S2N_SUCCESS;
278 : 1 : }
279 : :
280 [ + + ]: 17 : POSIX_GUARD_RESULT(s2n_connection_ktls_enable(conn, S2N_KTLS_MODE_SEND));
281 : 8 : return S2N_SUCCESS;
282 : 17 : }
283 : :
284 : : int s2n_connection_ktls_enable_recv(struct s2n_connection *conn)
285 : 21 : {
286 [ - + ][ # # ]: 21 : POSIX_ENSURE_REF(conn);
287 : :
288 : : /* If already enabled then return success */
289 [ + + ]: 21 : if (conn->ktls_recv_enabled) {
290 : 1 : return S2N_SUCCESS;
291 : 1 : }
292 : :
293 [ + + ]: 20 : POSIX_GUARD_RESULT(s2n_connection_ktls_enable(conn, S2N_KTLS_MODE_RECV));
294 : 10 : return S2N_SUCCESS;
295 : 20 : }
296 : :
297 : : int s2n_config_ktls_enable_unsafe_tls13(struct s2n_config *config)
298 : 6 : {
299 [ + - ][ + + ]: 6 : POSIX_ENSURE_REF(config);
300 : 5 : config->ktls_tls13_enabled = true;
301 : 5 : return S2N_SUCCESS;
302 : 6 : }
303 : :
304 : : /* The RFC defines the encryption limits in terms of "full-size records" sent.
305 : : * We can estimate the number of "full-sized records" sent by assuming that
306 : : * all records are full-sized.
307 : : */
308 : : static S2N_RESULT s2n_ktls_estimate_records(size_t bytes, uint64_t *estimate)
309 : 88 : {
310 [ - + ][ # # ]: 88 : RESULT_ENSURE_REF(estimate);
311 : 88 : uint64_t records = bytes / S2N_TLS_MAXIMUM_FRAGMENT_LENGTH;
312 [ + + ]: 88 : if (bytes % S2N_TLS_MAXIMUM_FRAGMENT_LENGTH) {
313 : 70 : records++;
314 : 70 : }
315 : 88 : *estimate = records;
316 : 88 : return S2N_RESULT_OK;
317 : 88 : }
318 : :
319 : : S2N_RESULT s2n_ktls_set_estimated_sequence_number(
320 : : struct s2n_connection *conn, size_t bytes_written)
321 : 50693 : {
322 [ - + ][ # # ]: 50693 : RESULT_ENSURE_REF(conn);
323 [ + + ]: 50693 : if (conn->actual_protocol_version < S2N_TLS13) {
324 : 50655 : return S2N_RESULT_OK;
325 : 50655 : }
326 : :
327 : 38 : uint64_t new_records_sent = 0;
328 [ - + ]: 38 : RESULT_GUARD(s2n_ktls_estimate_records(bytes_written, &new_records_sent));
329 : :
330 : 38 : struct s2n_blob seq_num = { 0 };
331 [ - + ]: 38 : RESULT_GUARD(s2n_connection_get_sequence_number(conn, conn->mode, &seq_num));
332 : :
333 [ + + ]: 97 : for (size_t i = 0; i < new_records_sent; i++) {
334 [ - + ]: 59 : RESULT_GUARD_POSIX(s2n_increment_sequence_number(&seq_num));
335 : 59 : }
336 : 38 : return S2N_RESULT_OK;
337 : 38 : }
338 : :
339 : : /* We need to track when the key encryption limit is reached. We could get the current record
340 : : * sequence number from the kernel with getsockopt, but that requires a surprisingly
341 : : * expensive syscall.
342 : : *
343 : : * Instead, we track the estimated sequence number and enforce the limit based
344 : : * on that estimate.
345 : : */
346 : : S2N_RESULT s2n_ktls_check_estimated_record_limit(struct s2n_connection *conn, size_t bytes_requested)
347 : 50710 : {
348 [ # # ][ - + ]: 50710 : RESULT_ENSURE_REF(conn);
349 [ + + ]: 50710 : if (conn->actual_protocol_version < S2N_TLS13) {
350 : 50660 : return S2N_RESULT_OK;
351 : 50660 : }
352 : :
353 : 50 : uint64_t new_records_sent = 0;
354 [ - + ]: 50 : RESULT_GUARD(s2n_ktls_estimate_records(bytes_requested, &new_records_sent));
355 : :
356 : 50 : uint64_t old_records_sent = 0;
357 : 50 : struct s2n_blob seq_num = { 0 };
358 [ - + ]: 50 : RESULT_GUARD(s2n_connection_get_sequence_number(conn, conn->mode, &seq_num));
359 [ - + ]: 50 : RESULT_GUARD_POSIX(s2n_sequence_number_to_uint64(&seq_num, &old_records_sent));
360 : :
361 [ # # ][ + - ]: 50 : RESULT_ENSURE(S2N_ADD_IS_OVERFLOW_SAFE(old_records_sent, new_records_sent, UINT64_MAX),
[ + - ]
362 : 50 : S2N_ERR_KTLS_KEY_LIMIT);
363 : 50 : uint64_t total_records_sent = old_records_sent + new_records_sent;
364 : :
365 [ - + ][ # # ]: 50 : RESULT_ENSURE_REF(conn->secure);
366 [ - + ][ # # ]: 50 : RESULT_ENSURE_REF(conn->secure->cipher_suite);
367 [ - + ][ # # ]: 50 : RESULT_ENSURE_REF(conn->secure->cipher_suite->record_alg);
368 : 50 : uint64_t encryption_limit = conn->secure->cipher_suite->record_alg->encryption_limit;
369 [ + + ]: 50 : if (total_records_sent > encryption_limit) {
370 [ # # ][ - + ]: 12 : RESULT_ENSURE_REF(conn->config);
371 [ + + ][ + - ]: 12 : RESULT_ENSURE(conn->config->ktls_tls13_enabled, S2N_ERR_KTLS_KEY_LIMIT);
372 : :
373 : : /* Check that the data requested for the ktls send call is not going over the encryption limit,
374 : : * as that would require multiple key updates.
375 : : * In TLS1.3, the key limit is 2^24.5 full-size records. (See S2N_TLS13_AES_GCM_MAXIMUM_RECORD_NUMBER)
376 : : * A full-sized record is 2^14 bytes. So essentially 2^24.5 * 2^14 bytes(388 GB) can be sent
377 : : * before you need to key update. We can add logic for multiple key updates in a single ktls
378 : : * send call in the future, but it's not required at the moment. */
379 [ + - ][ + + ]: 5 : RESULT_ENSURE(new_records_sent <= encryption_limit, S2N_ERR_INVALID_ARGUMENT);
380 : 2 : s2n_atomic_flag_set(&conn->key_update_pending);
381 : 2 : }
382 : :
383 : 40 : return S2N_RESULT_OK;
384 : 50 : }
385 : :
386 : : S2N_RESULT s2n_ktls_key_update_send(struct s2n_connection *conn, size_t bytes_requested)
387 : 50703 : {
388 [ - + ][ # # ]: 50703 : RESULT_ENSURE_REF(conn);
389 [ + + ]: 50703 : RESULT_GUARD(s2n_ktls_check_estimated_record_limit(conn, bytes_requested));
390 : :
391 [ - + ]: 50696 : if (s2n_atomic_flag_test(&conn->key_update_pending)) {
392 [ # # ][ # # ]: 0 : RESULT_ENSURE_REF(conn->config);
393 [ # # ][ # # ]: 0 : RESULT_ENSURE(conn->config->ktls_tls13_enabled, S2N_ERR_KTLS_KEYUPDATE);
394 : :
395 : 0 : uint8_t key_update_data[S2N_KEY_UPDATE_MESSAGE_SIZE];
396 : 0 : struct s2n_blob key_update_blob = { 0 };
397 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_blob_init(&key_update_blob, key_update_data, sizeof(key_update_data)));
398 : :
399 : : /* Write Keyupdate message */
400 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_key_update_write(&key_update_blob));
401 : :
402 : : /* Send Keyupdate message */
403 : 0 : const struct iovec iov = {
404 : 0 : .iov_base = (void *) (uintptr_t) key_update_data,
405 : 0 : .iov_len = sizeof(key_update_data),
406 : 0 : };
407 : 0 : s2n_blocked_status blocked = S2N_NOT_BLOCKED;
408 : 0 : size_t bytes_written = 0;
409 [ # # ]: 0 : RESULT_GUARD(s2n_ktls_sendmsg(conn->send_io_context, TLS_HANDSHAKE, &iov, 1, &blocked, &bytes_written));
410 [ # # ][ # # ]: 0 : RESULT_ENSURE_EQ(bytes_written, sizeof(key_update_data));
411 : :
412 : : /* Create new encryption key */
413 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_update_application_traffic_keys(conn, conn->mode, SENDING));
414 : :
415 : 0 : struct s2n_ktls_crypto_info crypto_info = { 0 };
416 [ # # ]: 0 : RESULT_GUARD(s2n_ktls_crypto_info_init(conn, S2N_KTLS_MODE_SEND, &crypto_info));
417 : :
418 : 0 : int fd = 0;
419 [ # # ]: 0 : RESULT_GUARD(s2n_ktls_get_file_descriptor(conn, S2N_KTLS_MODE_SEND, &fd));
420 : :
421 : : /* Update the socket with new key */
422 : 0 : int ret = s2n_setsockopt(fd, S2N_SOL_TLS, S2N_TLS_TX, crypto_info.value.data, crypto_info.value.size);
423 [ # # ][ # # ]: 0 : RESULT_ENSURE(ret == 0, S2N_ERR_KTLS_SOCKOPT);
424 : :
425 : 0 : s2n_atomic_flag_clear(&conn->key_update_pending);
426 : 0 : }
427 : 50696 : return S2N_RESULT_OK;
428 : 50696 : }
429 : :
430 : : S2N_RESULT s2n_ktls_key_update_process(struct s2n_connection *conn)
431 : 1 : {
432 [ # # ][ - + ]: 1 : RESULT_ENSURE_REF(conn);
433 [ - + ][ # # ]: 1 : RESULT_ENSURE_REF(conn->config);
434 [ + - ][ + - ]: 1 : RESULT_ENSURE(conn->config->ktls_tls13_enabled, S2N_ERR_KTLS_KEYUPDATE);
435 : :
436 : 0 : struct s2n_ktls_crypto_info crypto_info = { 0 };
437 [ # # ]: 0 : RESULT_GUARD(s2n_ktls_crypto_info_init(conn, S2N_KTLS_MODE_RECV, &crypto_info));
438 : :
439 : 0 : int fd = 0;
440 [ # # ]: 0 : RESULT_GUARD(s2n_ktls_get_file_descriptor(conn, S2N_KTLS_MODE_RECV, &fd));
441 : :
442 : : /* Update the socket with new key */
443 : 0 : int ret = s2n_setsockopt(fd, S2N_SOL_TLS, S2N_TLS_RX, crypto_info.value.data, crypto_info.value.size);
444 [ # # ][ # # ]: 0 : RESULT_ENSURE(ret == 0, S2N_ERR_KTLS_SOCKOPT);
445 : :
446 : 0 : return S2N_RESULT_OK;
447 : 0 : }
|