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_connection_serialize.h"
17 : :
18 : : #include "crypto/s2n_sequence.h"
19 : : #include "tls/s2n_connection.h"
20 : : #include "tls/s2n_tls.h"
21 : : #include "tls/s2n_tls13_key_schedule.h"
22 : :
23 : : static bool s2n_libcrypto_supports_evp_aead_tls(void)
24 : 17 : {
25 : : #ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_AEAD_TLS
26 : : return true;
27 : : #else
28 : 17 : return false;
29 : 17 : #endif
30 : 17 : }
31 : :
32 : : int s2n_connection_serialization_length(struct s2n_connection *conn, uint32_t *length)
33 : 76 : {
34 [ + + ][ + - ]: 76 : POSIX_ENSURE_REF(conn);
35 [ - + ][ # # ]: 75 : POSIX_ENSURE_REF(conn->config);
36 [ # # ][ - + ]: 75 : POSIX_ENSURE_REF(conn->secure);
37 [ - + ][ # # ]: 75 : POSIX_ENSURE_REF(conn->secure->cipher_suite);
38 [ + + ][ + - ]: 75 : POSIX_ENSURE_REF(length);
39 : :
40 [ - + ][ # # ]: 74 : POSIX_ENSURE(conn->config->serialized_connection_version != S2N_SERIALIZED_CONN_NONE,
41 : 74 : S2N_ERR_INVALID_STATE);
42 : :
43 [ + + ]: 74 : if (conn->actual_protocol_version >= S2N_TLS13) {
44 : 57 : uint8_t secret_size = 0;
45 [ - + ]: 57 : POSIX_GUARD(s2n_hmac_digest_size(conn->secure->cipher_suite->prf_alg, &secret_size));
46 : 57 : *length = S2N_SERIALIZED_CONN_FIXED_SIZE + (secret_size * 3);
47 : 57 : } else {
48 : 17 : *length = S2N_SERIALIZED_CONN_TLS12_SIZE;
49 : 17 : }
50 : :
51 : 74 : return S2N_SUCCESS;
52 : 74 : }
53 : :
54 : : static S2N_RESULT s2n_connection_serialize_tls13_secrets(struct s2n_connection *conn, struct s2n_stuffer *output)
55 : 19 : {
56 [ # # ][ - + ]: 19 : RESULT_ENSURE_REF(conn);
57 [ - + ][ # # ]: 19 : RESULT_ENSURE_REF(conn->secure);
58 [ # # ][ - + ]: 19 : RESULT_ENSURE_REF(conn->secure->cipher_suite);
59 : :
60 : 19 : uint8_t secret_size = 0;
61 [ - + ]: 19 : RESULT_GUARD_POSIX(s2n_hmac_digest_size(conn->secure->cipher_suite->prf_alg, &secret_size));
62 : :
63 [ - + ]: 19 : RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->secrets.version.tls13.client_app_secret,
64 : 19 : secret_size));
65 [ - + ]: 19 : RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->secrets.version.tls13.server_app_secret,
66 : 19 : secret_size));
67 [ - + ]: 19 : RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->secrets.version.tls13.resumption_master_secret,
68 : 19 : secret_size));
69 : 19 : return S2N_RESULT_OK;
70 : 19 : }
71 : :
72 : : static S2N_RESULT s2n_connection_serialize_secrets(struct s2n_connection *conn, struct s2n_stuffer *output)
73 : 15 : {
74 [ - + ][ # # ]: 15 : RESULT_ENSURE_REF(conn);
75 : :
76 [ - + ]: 15 : RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->secrets.version.tls12.master_secret,
77 : 15 : S2N_TLS_SECRET_LEN));
78 [ - + ]: 15 : RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->handshake_params.client_random,
79 : 15 : S2N_TLS_RANDOM_DATA_LEN));
80 [ - + ]: 15 : RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->handshake_params.server_random,
81 : 15 : S2N_TLS_RANDOM_DATA_LEN));
82 : 15 : return S2N_RESULT_OK;
83 : 15 : }
84 : :
85 : : int s2n_connection_serialize(struct s2n_connection *conn, uint8_t *buffer, uint32_t buffer_length)
86 : 41 : {
87 [ + + ][ + - ]: 41 : POSIX_ENSURE_REF(conn);
88 [ - + ][ # # ]: 40 : POSIX_ENSURE_REF(conn->secure);
89 [ # # ][ - + ]: 40 : POSIX_ENSURE_REF(conn->secure->cipher_suite);
90 [ # # ][ - + ]: 40 : POSIX_ENSURE_REF(conn->config);
91 [ + - ][ + + ]: 40 : POSIX_ENSURE_REF(buffer);
92 : :
93 [ + - ][ + + ]: 39 : POSIX_ENSURE(conn->config->serialized_connection_version != S2N_SERIALIZED_CONN_NONE,
94 : 38 : S2N_ERR_INVALID_STATE);
95 : :
96 : : /* This method must be called after negotiation */
97 [ + - ][ + + ]: 38 : POSIX_ENSURE(s2n_handshake_is_complete(conn), S2N_ERR_HANDSHAKE_NOT_COMPLETE);
98 : :
99 : : /* The connection must not be closed already. Otherwise, we might have an alert
100 : : * queued up that would be sent in cleartext after we disable encryption. */
101 : 37 : s2n_io_status status = S2N_IO_FULL_DUPLEX;
102 [ + + ][ + - ]: 37 : POSIX_ENSURE(s2n_connection_check_io_status(conn, status), S2N_ERR_CLOSED);
103 : :
104 : : /* Best effort check for pending input or output data.
105 : : * This method should not be called until the application has stopped sending and receiving.
106 : : * Saving partial read or partial write state would complicate this problem.
107 : : */
108 [ + + ][ + - ]: 36 : POSIX_ENSURE(s2n_stuffer_data_available(&conn->header_in) == 0, S2N_ERR_INVALID_STATE);
109 [ # # ][ - + ]: 35 : POSIX_ENSURE(s2n_stuffer_data_available(&conn->in) == 0, S2N_ERR_INVALID_STATE);
110 [ - + ][ # # ]: 35 : POSIX_ENSURE(s2n_stuffer_data_available(&conn->out) == 0, S2N_ERR_INVALID_STATE);
111 : :
112 : 35 : uint32_t context_length = 0;
113 [ - + ]: 35 : POSIX_GUARD(s2n_connection_serialization_length(conn, &context_length));
114 [ + - ][ + + ]: 35 : POSIX_ENSURE(buffer_length >= context_length, S2N_ERR_INSUFFICIENT_MEM_SIZE);
115 : :
116 : 34 : struct s2n_blob context_blob = { 0 };
117 [ - + ]: 34 : POSIX_GUARD(s2n_blob_init(&context_blob, buffer, buffer_length));
118 : 34 : struct s2n_stuffer output = { 0 };
119 [ - + ]: 34 : POSIX_GUARD(s2n_stuffer_init(&output, &context_blob));
120 : :
121 [ - + ]: 34 : POSIX_GUARD(s2n_stuffer_write_uint64(&output, S2N_SERIALIZED_CONN_V1));
122 : :
123 [ - + ]: 34 : POSIX_GUARD(s2n_stuffer_write_uint8(&output, conn->actual_protocol_version / 10));
124 [ - + ]: 34 : POSIX_GUARD(s2n_stuffer_write_uint8(&output, conn->actual_protocol_version % 10));
125 [ - + ]: 34 : POSIX_GUARD(s2n_stuffer_write_bytes(&output, conn->secure->cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
126 : :
127 [ - + ]: 34 : POSIX_GUARD(s2n_stuffer_write_bytes(&output, conn->secure->client_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
128 [ - + ]: 34 : POSIX_GUARD(s2n_stuffer_write_bytes(&output, conn->secure->server_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
129 : :
130 [ - + ]: 34 : POSIX_GUARD(s2n_stuffer_write_uint16(&output, conn->max_outgoing_fragment_length));
131 : :
132 [ + + ]: 34 : if (conn->actual_protocol_version >= S2N_TLS13) {
133 [ - + ]: 19 : POSIX_GUARD_RESULT(s2n_connection_serialize_tls13_secrets(conn, &output));
134 : 19 : } else {
135 [ - + ]: 15 : POSIX_GUARD_RESULT(s2n_connection_serialize_secrets(conn, &output));
136 : 15 : }
137 : :
138 : : /* Users should not be able to send/recv on the connection after serialization as that
139 : : * could lead to nonce reuse. We close the connection to prevent the application from sending
140 : : * more application data. However, the application could still send a close_notify alert record
141 : : * to shutdown the connection, so we also intentionally wipe keys and disable encryption.
142 : : *
143 : : * A plaintext close_notify alert is not a security concern, although the peer will likely consider
144 : : * it an error.
145 : : */
146 [ - + ]: 34 : POSIX_GUARD_RESULT(s2n_connection_set_closed(conn));
147 [ - + ]: 34 : POSIX_GUARD_RESULT(s2n_crypto_parameters_wipe(conn->secure));
148 : :
149 : 34 : return S2N_SUCCESS;
150 : 34 : }
151 : :
152 : : struct s2n_connection_deserialize {
153 : : uint8_t protocol_version;
154 : : struct s2n_cipher_suite *cipher_suite;
155 : : uint8_t client_sequence_number[S2N_TLS_SEQUENCE_NUM_LEN];
156 : : uint8_t server_sequence_number[S2N_TLS_SEQUENCE_NUM_LEN];
157 : : uint16_t max_fragment_len;
158 : : union {
159 : : struct {
160 : : uint8_t master_secret[S2N_TLS_SECRET_LEN];
161 : : uint8_t client_random[S2N_TLS_RANDOM_DATA_LEN];
162 : : uint8_t server_random[S2N_TLS_RANDOM_DATA_LEN];
163 : : } tls12;
164 : : struct {
165 : : uint8_t secret_size;
166 : : uint8_t client_application_secret[S2N_TLS_SECRET_LEN];
167 : : uint8_t server_application_secret[S2N_TLS_SECRET_LEN];
168 : : uint8_t resumption_master_secret[S2N_TLS_SECRET_LEN];
169 : : } tls13;
170 : : } version;
171 : : };
172 : :
173 : : static S2N_RESULT s2n_connection_deserialize_tls13_secrets(struct s2n_stuffer *input,
174 : : struct s2n_connection_deserialize *parsed_values)
175 : 17 : {
176 [ - + ][ # # ]: 17 : RESULT_ENSURE_REF(input);
177 [ - + ][ # # ]: 17 : RESULT_ENSURE_REF(parsed_values);
178 : :
179 [ - + ]: 17 : RESULT_GUARD_POSIX(s2n_hmac_digest_size(parsed_values->cipher_suite->prf_alg,
180 : 17 : &parsed_values->version.tls13.secret_size));
181 [ - + ]: 17 : RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls13.client_application_secret,
182 : 17 : parsed_values->version.tls13.secret_size));
183 [ - + ]: 17 : RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls13.server_application_secret,
184 : 17 : parsed_values->version.tls13.secret_size));
185 [ - + ]: 17 : RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls13.resumption_master_secret,
186 : 17 : parsed_values->version.tls13.secret_size));
187 : :
188 : 17 : return S2N_RESULT_OK;
189 : 17 : }
190 : :
191 : : static S2N_RESULT s2n_connection_deserialize_secrets(struct s2n_stuffer *input,
192 : : struct s2n_connection_deserialize *parsed_values)
193 : 16 : {
194 [ - + ][ # # ]: 16 : RESULT_ENSURE_REF(input);
195 [ # # ][ - + ]: 16 : RESULT_ENSURE_REF(parsed_values);
196 : :
197 [ - + ]: 16 : RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls12.master_secret, S2N_TLS_SECRET_LEN));
198 [ - + ]: 16 : RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls12.client_random, S2N_TLS_RANDOM_DATA_LEN));
199 [ - + ]: 16 : RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls12.server_random, S2N_TLS_RANDOM_DATA_LEN));
200 : :
201 : 16 : return S2N_RESULT_OK;
202 : 16 : }
203 : :
204 : : static S2N_RESULT s2n_connection_deserialize_parse(uint8_t *buffer, uint32_t buffer_length,
205 : : struct s2n_connection_deserialize *parsed_values)
206 : 36 : {
207 [ # # ][ - + ]: 36 : RESULT_ENSURE_REF(parsed_values);
208 : :
209 : 36 : struct s2n_blob context_blob = { 0 };
210 [ - + ]: 36 : RESULT_GUARD_POSIX(s2n_blob_init(&context_blob, buffer, buffer_length));
211 : 36 : struct s2n_stuffer input = { 0 };
212 [ - + ]: 36 : RESULT_GUARD_POSIX(s2n_stuffer_init_written(&input, &context_blob));
213 : :
214 : 36 : uint64_t serialized_version = 0;
215 [ - + ]: 36 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint64(&input, &serialized_version));
216 : : /* No other version is supported currently */
217 [ + + ][ + - ]: 36 : RESULT_ENSURE_EQ(serialized_version, S2N_SERIALIZED_CONN_V1);
218 : :
219 : 35 : uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN] = { 0 };
220 [ - + ]: 35 : RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(&input, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
221 : 35 : parsed_values->protocol_version = (protocol_version[0] * 10) + protocol_version[1];
222 : :
223 [ + - ][ + + ]: 35 : RESULT_ENSURE(parsed_values->protocol_version >= S2N_SSLv3 && parsed_values->protocol_version <= s2n_highest_protocol_version,
[ + + ]
224 : 33 : S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
225 : :
226 : 33 : uint8_t cipher_suite[S2N_TLS_CIPHER_SUITE_LEN] = { 0 };
227 [ - + ]: 33 : RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(&input, cipher_suite, S2N_TLS_CIPHER_SUITE_LEN));
228 [ - + ]: 33 : RESULT_GUARD(s2n_cipher_suite_from_iana(cipher_suite, S2N_TLS_CIPHER_SUITE_LEN, &parsed_values->cipher_suite));
229 : :
230 [ - + ]: 33 : RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(&input, parsed_values->client_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
231 [ - + ]: 33 : RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(&input, parsed_values->server_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
232 : :
233 [ - + ]: 33 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(&input, &parsed_values->max_fragment_len));
234 : :
235 [ + + ]: 33 : if (parsed_values->protocol_version >= S2N_TLS13) {
236 [ - + ]: 17 : RESULT_GUARD(s2n_connection_deserialize_tls13_secrets(&input, parsed_values));
237 : 17 : } else {
238 [ - + ]: 16 : RESULT_GUARD(s2n_connection_deserialize_secrets(&input, parsed_values));
239 : 16 : }
240 : :
241 : 33 : return S2N_RESULT_OK;
242 : 33 : }
243 : :
244 : : /* Boringssl and AWS-LC do a special check in tls13 during the first call to encrypt after
245 : : * initialization. In the first call they assume that the sequence number will be 0, and therefore
246 : : * the provided nonce is equivalent to the implicit IV because 0 ^ iv = iv. The recovered implicit IV
247 : : * is stored and used later on to ensure the monotonicity of sequence numbers.
248 : : *
249 : : * In the case of deserialization, in the first call the sequence number may not be 0.
250 : : * Therefore the provided nonce cannot be considered to be the implicit IV because n ^ iv != iv.
251 : : * This inability to get the correct implicit IV causes issues with encryption later on.
252 : : *
253 : : * To resolve this we preform one throwaway encryption call with a zero sequence number after
254 : : * deserialization. This allows the libcrypto to recover the implicit IV correctly.
255 : : */
256 : : static S2N_RESULT s2n_initialize_implicit_iv(struct s2n_connection *conn, struct s2n_connection_deserialize *parsed_values)
257 : 17 : {
258 [ # # ][ - + ]: 17 : RESULT_ENSURE_REF(conn);
259 [ - + ][ # # ]: 17 : RESULT_ENSURE_REF(parsed_values);
260 [ # # ][ - + ]: 17 : RESULT_ENSURE_REF(conn->secure);
261 [ - + ][ # # ]: 17 : RESULT_ENSURE_REF(conn->server);
262 [ - + ][ # # ]: 17 : RESULT_ENSURE_REF(conn->client);
263 : :
264 [ + - ]: 17 : if (!s2n_libcrypto_supports_evp_aead_tls()) {
265 : 17 : return S2N_RESULT_OK;
266 : 17 : }
267 : :
268 : 0 : uint8_t *seq_num = parsed_values->server_sequence_number;
269 : 0 : uint8_t *implicit_iv = conn->server->server_implicit_iv;
270 : 0 : struct s2n_session_key key = conn->server->server_key;
271 [ # # ]: 0 : if (conn->mode == S2N_CLIENT) {
272 : 0 : seq_num = parsed_values->client_sequence_number;
273 : 0 : implicit_iv = conn->client->client_implicit_iv;
274 : 0 : key = conn->client->client_key;
275 : 0 : }
276 : :
277 : 0 : uint64_t parsed_sequence_num = 0;
278 : 0 : struct s2n_blob seq_num_blob = { 0 };
279 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_blob_init(&seq_num_blob, seq_num, S2N_TLS_SEQUENCE_NUM_LEN));
280 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_sequence_number_to_uint64(&seq_num_blob, &parsed_sequence_num));
281 : :
282 : : /* we don't need to initialize the context when the sequence number is 0 */
283 [ # # ]: 0 : if (parsed_sequence_num == 0) {
284 : 0 : return S2N_RESULT_OK;
285 : 0 : }
286 : :
287 : 0 : uint8_t in_data[S2N_TLS_GCM_TAG_LEN] = { 0 };
288 : 0 : struct s2n_blob in_blob = { 0 };
289 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_blob_init(&in_blob, in_data, sizeof(in_data)));
290 : :
291 : 0 : struct s2n_blob iv_blob = { 0 };
292 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_blob_init(&iv_blob, implicit_iv, S2N_TLS13_FIXED_IV_LEN));
293 : :
294 : 0 : struct s2n_blob aad_blob = { 0 };
295 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_blob_init(&aad_blob, NULL, 0));
296 : :
297 [ # # ][ # # ]: 0 : RESULT_ENSURE_REF(conn->secure->cipher_suite);
298 [ # # ][ # # ]: 0 : RESULT_ENSURE_REF(conn->secure->cipher_suite->record_alg);
299 [ # # ][ # # ]: 0 : RESULT_ENSURE_REF(conn->secure->cipher_suite->record_alg->cipher);
300 [ # # ]: 0 : RESULT_GUARD_POSIX(conn->secure->cipher_suite->record_alg->cipher->io.aead.encrypt(&key,
301 : 0 : &iv_blob, &aad_blob, &in_blob, &in_blob));
302 : :
303 : 0 : return S2N_RESULT_OK;
304 : 0 : }
305 : :
306 : : static S2N_RESULT s2n_restore_tls13_secrets(struct s2n_connection *conn, struct s2n_connection_deserialize *parsed_values)
307 : 17 : {
308 [ # # ][ - + ]: 17 : RESULT_ENSURE_REF(conn);
309 [ - + ][ # # ]: 17 : RESULT_ENSURE_REF(parsed_values);
310 : :
311 [ # # ][ - + ]: 17 : RESULT_CHECKED_MEMCPY(conn->secrets.version.tls13.client_app_secret,
[ + - ]
312 : 17 : parsed_values->version.tls13.client_application_secret, parsed_values->version.tls13.secret_size);
313 [ - + ][ # # ]: 17 : RESULT_CHECKED_MEMCPY(conn->secrets.version.tls13.server_app_secret,
[ + - ]
314 : 17 : parsed_values->version.tls13.server_application_secret, parsed_values->version.tls13.secret_size);
315 [ - + ][ # # ]: 17 : RESULT_CHECKED_MEMCPY(conn->secrets.version.tls13.resumption_master_secret,
[ + - ]
316 : 17 : parsed_values->version.tls13.resumption_master_secret, parsed_values->version.tls13.secret_size);
317 : :
318 [ - + ]: 17 : RESULT_GUARD(s2n_tls13_key_schedule_set_key(conn, S2N_MASTER_SECRET, S2N_SERVER));
319 [ - + ]: 17 : RESULT_GUARD(s2n_tls13_key_schedule_set_key(conn, S2N_MASTER_SECRET, S2N_CLIENT));
320 : :
321 [ - + ]: 17 : RESULT_GUARD(s2n_initialize_implicit_iv(conn, parsed_values));
322 : :
323 : 17 : return S2N_RESULT_OK;
324 : 17 : }
325 : :
326 : : static S2N_RESULT s2n_restore_secrets(struct s2n_connection *conn, struct s2n_connection_deserialize *parsed_values)
327 : 16 : {
328 [ - + ][ # # ]: 16 : RESULT_ENSURE_REF(conn);
329 [ - + ][ # # ]: 16 : RESULT_ENSURE_REF(parsed_values);
330 : :
331 [ - + ][ # # ]: 16 : RESULT_CHECKED_MEMCPY(conn->secrets.version.tls12.master_secret, parsed_values->version.tls12.master_secret,
[ + - ]
332 : 16 : S2N_TLS_SECRET_LEN);
333 [ - + ][ # # ]: 16 : RESULT_CHECKED_MEMCPY(conn->handshake_params.client_random, parsed_values->version.tls12.client_random,
[ + - ]
334 : 16 : S2N_TLS_RANDOM_DATA_LEN);
335 [ - + ][ # # ]: 16 : RESULT_CHECKED_MEMCPY(conn->handshake_params.server_random, parsed_values->version.tls12.server_random,
[ + - ]
336 : 16 : S2N_TLS_RANDOM_DATA_LEN);
337 [ - + ]: 16 : RESULT_GUARD_POSIX(s2n_prf_key_expansion(conn));
338 : :
339 : 16 : return S2N_RESULT_OK;
340 : 16 : }
341 : :
342 : : int s2n_connection_deserialize(struct s2n_connection *conn, uint8_t *buffer, uint32_t buffer_length)
343 : 38 : {
344 [ + + ][ + - ]: 38 : POSIX_ENSURE_REF(conn);
345 [ - + ][ # # ]: 37 : POSIX_ENSURE_REF(conn->secure);
346 [ + + ][ + - ]: 37 : POSIX_ENSURE_REF(buffer);
347 : :
348 : : /* Read parsed values into a temporary struct so that the connection is unaltered if parsing fails */
349 : 36 : struct s2n_connection_deserialize parsed_values = { 0 };
350 [ + + ][ + - ]: 36 : POSIX_ENSURE(s2n_result_is_ok(s2n_connection_deserialize_parse(buffer, buffer_length, &parsed_values)),
351 : 33 : S2N_ERR_INVALID_SERIALIZED_CONNECTION);
352 : :
353 : : /* Rehydrate fields now that parsing has completed successfully */
354 : 33 : conn->actual_protocol_version = parsed_values.protocol_version;
355 : 33 : conn->secure->cipher_suite = parsed_values.cipher_suite;
356 [ - + ]: 33 : POSIX_GUARD_RESULT(s2n_connection_set_max_fragment_length(conn, parsed_values.max_fragment_len));
357 : :
358 : : /* Mark the connection as having been deserialized */
359 : 33 : conn->deserialized_conn = true;
360 : :
361 : : /* Key expansion */
362 [ + + ]: 33 : if (parsed_values.protocol_version >= S2N_TLS13) {
363 [ - + ]: 17 : POSIX_GUARD_RESULT(s2n_restore_tls13_secrets(conn, &parsed_values));
364 : 17 : } else {
365 [ - + ]: 16 : POSIX_GUARD_RESULT(s2n_restore_secrets(conn, &parsed_values));
366 : 16 : }
367 : :
368 : : /* Wait until after key generation to restore sequence numbers since they get zeroed during
369 : : * key expansion */
370 [ - + ][ # # ]: 33 : POSIX_CHECKED_MEMCPY(conn->secure->client_sequence_number, parsed_values.client_sequence_number,
[ + - ]
371 : 33 : S2N_TLS_SEQUENCE_NUM_LEN);
372 [ - + ][ # # ]: 33 : POSIX_CHECKED_MEMCPY(conn->secure->server_sequence_number, parsed_values.server_sequence_number,
[ + - ]
373 : 33 : S2N_TLS_SEQUENCE_NUM_LEN);
374 : :
375 : 33 : conn->client = conn->secure;
376 : 33 : conn->server = conn->secure;
377 : :
378 : 33 : return S2N_SUCCESS;
379 : 33 : }
|