LCOV - code coverage report
Current view: top level - tls - s2n_connection_serialize.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 187 216 86.6 %
Date: 2025-08-15 07:28:39 Functions: 12 12 100.0 %
Branches: 139 344 40.4 %

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

Generated by: LCOV version 1.14