LCOV - code coverage report
Current view: top level - tls - s2n_connection_serialize.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 233 262 88.9 %
Date: 2026-07-04 07:27:58 Functions: 13 13 100.0 %
Branches: 177 422 41.9 %

           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                 :            : /* True if a serialized blob carries the CBC implicit IV state. Only TLS1.0
      33                 :            :  * and SSLv3 chain the implicit IV across records (TLS1.1+ uses an explicit
      34                 :            :  * per-record IV), and only for CBC and composite (CBC + HMAC fused) record
      35                 :            :  * algorithms. */
      36                 :            : static bool s2n_serialization_includes_implicit_iv(uint8_t protocol_version,
      37                 :            :         const struct s2n_cipher_suite *cipher_suite)
      38                 :         76 : {
      39         [ +  + ]:         76 :     if (protocol_version >= S2N_TLS11) {
      40                 :         62 :         return false;
      41                 :         62 :     }
      42                 :         14 :     int type = cipher_suite->record_alg->cipher->type;
      43 [ +  + ][ +  + ]:         14 :     return type == S2N_CBC || type == S2N_COMPOSITE;
      44                 :         76 : }
      45                 :            : 
      46                 :            : int s2n_connection_serialization_length(struct s2n_connection *conn, uint32_t *length)
      47                 :         80 : {
      48 [ +  - ][ +  + ]:         80 :     POSIX_ENSURE_REF(conn);
      49 [ #  # ][ -  + ]:         79 :     POSIX_ENSURE_REF(conn->config);
      50 [ -  + ][ #  # ]:         79 :     POSIX_ENSURE_REF(conn->secure);
      51 [ -  + ][ #  # ]:         79 :     POSIX_ENSURE_REF(conn->secure->cipher_suite);
      52 [ +  + ][ +  - ]:         79 :     POSIX_ENSURE_REF(length);
      53                 :            : 
      54 [ -  + ][ #  # ]:         78 :     POSIX_ENSURE(conn->config->serialized_connection_version != S2N_SERIALIZED_CONN_NONE,
      55                 :         78 :             S2N_ERR_INVALID_STATE);
      56                 :            : 
      57         [ +  + ]:         78 :     if (conn->actual_protocol_version >= S2N_TLS13) {
      58                 :         56 :         uint8_t secret_size = 0;
      59         [ -  + ]:         56 :         POSIX_GUARD(s2n_hmac_digest_size(conn->secure->cipher_suite->prf_alg, &secret_size));
      60                 :         56 :         *length = S2N_SERIALIZED_CONN_FIXED_SIZE + (secret_size * 3);
      61         [ +  + ]:         56 :     } else if (s2n_serialization_includes_implicit_iv(conn->actual_protocol_version,
      62                 :         22 :                        conn->secure->cipher_suite)) {
      63                 :          4 :         *length = S2N_SERIALIZED_CONN_TLS10_SIZE;
      64                 :         18 :     } else {
      65                 :         18 :         *length = S2N_SERIALIZED_CONN_TLS12_SIZE;
      66                 :         18 :     }
      67                 :            : 
      68                 :         78 :     return S2N_SUCCESS;
      69                 :         78 : }
      70                 :            : 
      71                 :            : static S2N_RESULT s2n_connection_serialize_tls13_secrets(struct s2n_connection *conn, struct s2n_stuffer *output)
      72                 :         18 : {
      73 [ #  # ][ -  + ]:         18 :     RESULT_ENSURE_REF(conn);
      74 [ -  + ][ #  # ]:         18 :     RESULT_ENSURE_REF(conn->secure);
      75 [ -  + ][ #  # ]:         18 :     RESULT_ENSURE_REF(conn->secure->cipher_suite);
      76                 :            : 
      77                 :         18 :     uint8_t secret_size = 0;
      78         [ -  + ]:         18 :     RESULT_GUARD_POSIX(s2n_hmac_digest_size(conn->secure->cipher_suite->prf_alg, &secret_size));
      79                 :            : 
      80         [ -  + ]:         18 :     RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->secrets.version.tls13.client_app_secret,
      81                 :         18 :             secret_size));
      82         [ -  + ]:         18 :     RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->secrets.version.tls13.server_app_secret,
      83                 :         18 :             secret_size));
      84         [ -  + ]:         18 :     RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->secrets.version.tls13.resumption_master_secret,
      85                 :         18 :             secret_size));
      86                 :         18 :     return S2N_RESULT_OK;
      87                 :         18 : }
      88                 :            : 
      89                 :            : static S2N_RESULT s2n_connection_serialize_secrets(struct s2n_connection *conn, struct s2n_stuffer *output)
      90                 :         18 : {
      91 [ -  + ][ #  # ]:         18 :     RESULT_ENSURE_REF(conn);
      92 [ #  # ][ -  + ]:         18 :     RESULT_ENSURE_REF(conn->secure);
      93                 :            : 
      94         [ -  + ]:         18 :     RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->secrets.version.tls12.master_secret,
      95                 :         18 :             S2N_TLS_SECRET_LEN));
      96         [ -  + ]:         18 :     RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->client_hello.random,
      97                 :         18 :             S2N_TLS_RANDOM_DATA_LEN));
      98         [ -  + ]:         18 :     RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->handshake_params.server_random,
      99                 :         18 :             S2N_TLS_RANDOM_DATA_LEN));
     100                 :            : 
     101                 :            :     /* TLS1.0 and SSLv3 CBC chain the implicit IV across records; capture it so
     102                 :            :      * the deserialized connection can keep talking to its peer.
     103                 :            :      */
     104         [ +  + ]:         18 :     if (s2n_serialization_includes_implicit_iv(conn->actual_protocol_version,
     105                 :         18 :                 conn->secure->cipher_suite)) {
     106         [ -  + ]:          2 :         RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->secure->client_implicit_iv,
     107                 :          2 :                 S2N_TLS_MAX_IV_LEN));
     108         [ -  + ]:          2 :         RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, conn->secure->server_implicit_iv,
     109                 :          2 :                 S2N_TLS_MAX_IV_LEN));
     110                 :          2 :     }
     111                 :         18 :     return S2N_RESULT_OK;
     112                 :         18 : }
     113                 :            : 
     114                 :            : int s2n_connection_serialize(struct s2n_connection *conn, uint8_t *buffer, uint32_t buffer_length)
     115                 :         43 : {
     116 [ +  + ][ +  - ]:         43 :     POSIX_ENSURE_REF(conn);
     117 [ -  + ][ #  # ]:         42 :     POSIX_ENSURE_REF(conn->secure);
     118 [ #  # ][ -  + ]:         42 :     POSIX_ENSURE_REF(conn->secure->cipher_suite);
     119 [ -  + ][ #  # ]:         42 :     POSIX_ENSURE_REF(conn->config);
     120 [ +  + ][ +  - ]:         42 :     POSIX_ENSURE_REF(buffer);
     121                 :            : 
     122 [ +  + ][ +  - ]:         41 :     POSIX_ENSURE(conn->config->serialized_connection_version != S2N_SERIALIZED_CONN_NONE,
     123                 :         40 :             S2N_ERR_INVALID_STATE);
     124                 :            : 
     125                 :            :     /* This method must be called after negotiation */
     126 [ +  + ][ +  - ]:         40 :     POSIX_ENSURE(s2n_handshake_is_complete(conn), S2N_ERR_HANDSHAKE_NOT_COMPLETE);
     127                 :            : 
     128                 :            :     /* The connection must not be closed already. Otherwise, we might have an alert
     129                 :            :      * queued up that would be sent in cleartext after we disable encryption. */
     130                 :         39 :     s2n_io_status status = S2N_IO_FULL_DUPLEX;
     131 [ +  + ][ +  - ]:         39 :     POSIX_ENSURE(s2n_connection_check_io_status(conn, status), S2N_ERR_CLOSED);
     132                 :            : 
     133                 :            :     /* Best effort check for pending input or output data.
     134                 :            :      * This method should not be called until the application has stopped sending and receiving.
     135                 :            :      * Saving partial read or partial write state would complicate this problem.
     136                 :            :      */
     137 [ +  + ][ +  - ]:         38 :     POSIX_ENSURE(s2n_stuffer_data_available(&conn->header_in) == 0, S2N_ERR_INVALID_STATE);
     138 [ #  # ][ -  + ]:         37 :     POSIX_ENSURE(s2n_stuffer_data_available(&conn->in) == 0, S2N_ERR_INVALID_STATE);
     139 [ -  + ][ #  # ]:         37 :     POSIX_ENSURE(s2n_stuffer_data_available(&conn->out) == 0, S2N_ERR_INVALID_STATE);
     140                 :            : 
     141                 :         37 :     uint32_t context_length = 0;
     142         [ -  + ]:         37 :     POSIX_GUARD(s2n_connection_serialization_length(conn, &context_length));
     143 [ +  + ][ +  - ]:         37 :     POSIX_ENSURE(buffer_length >= context_length, S2N_ERR_INSUFFICIENT_MEM_SIZE);
     144                 :            : 
     145                 :            :     /* Stream ciphers (RC4) hold keystream position in libcrypto state that
     146                 :            :      * this API does not capture, so a deserialized stream-cipher connection
     147                 :            :      * cannot decrypt records from its peer. Reject rather than producing a
     148                 :            :      * blob that can't be used.
     149                 :            :      */
     150 [ -  + ][ #  # ]:         36 :     POSIX_ENSURE_REF(conn->secure->cipher_suite->record_alg);
     151 [ #  # ][ -  + ]:         36 :     POSIX_ENSURE_REF(conn->secure->cipher_suite->record_alg->cipher);
     152 [ #  # ][ -  + ]:         36 :     POSIX_ENSURE(conn->secure->cipher_suite->record_alg->cipher->type != S2N_STREAM,
     153                 :         36 :             S2N_ERR_INVALID_STATE);
     154                 :            : 
     155                 :         36 :     struct s2n_blob context_blob = { 0 };
     156         [ -  + ]:         36 :     POSIX_GUARD(s2n_blob_init(&context_blob, buffer, buffer_length));
     157                 :         36 :     struct s2n_stuffer output = { 0 };
     158         [ -  + ]:         36 :     POSIX_GUARD(s2n_stuffer_init(&output, &context_blob));
     159                 :            : 
     160         [ -  + ]:         36 :     POSIX_GUARD(s2n_stuffer_write_uint64(&output, S2N_SERIALIZED_CONN_V1));
     161                 :            : 
     162         [ -  + ]:         36 :     POSIX_GUARD(s2n_stuffer_write_uint8(&output, conn->actual_protocol_version / 10));
     163         [ -  + ]:         36 :     POSIX_GUARD(s2n_stuffer_write_uint8(&output, conn->actual_protocol_version % 10));
     164         [ -  + ]:         36 :     POSIX_GUARD(s2n_stuffer_write_bytes(&output, conn->secure->cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
     165                 :            : 
     166         [ -  + ]:         36 :     POSIX_GUARD(s2n_stuffer_write_bytes(&output, conn->secure->client_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
     167         [ -  + ]:         36 :     POSIX_GUARD(s2n_stuffer_write_bytes(&output, conn->secure->server_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
     168                 :            : 
     169         [ -  + ]:         36 :     POSIX_GUARD(s2n_stuffer_write_uint16(&output, conn->max_outgoing_fragment_length));
     170                 :            : 
     171         [ +  + ]:         36 :     if (conn->actual_protocol_version >= S2N_TLS13) {
     172         [ -  + ]:         18 :         POSIX_GUARD_RESULT(s2n_connection_serialize_tls13_secrets(conn, &output));
     173                 :         18 :     } else {
     174         [ -  + ]:         18 :         POSIX_GUARD_RESULT(s2n_connection_serialize_secrets(conn, &output));
     175                 :         18 :     }
     176                 :            : 
     177                 :            :     /* Users should not be able to send/recv on the connection after serialization as that
     178                 :            :      * could lead to nonce reuse. We close the connection to prevent the application from sending
     179                 :            :      * more application data. However, the application could still send a close_notify alert record
     180                 :            :      * to shutdown the connection, so we also intentionally wipe keys and disable encryption.
     181                 :            :      *
     182                 :            :      * A plaintext close_notify alert is not a security concern, although the peer will likely consider
     183                 :            :      * it an error.
     184                 :            :      */
     185         [ -  + ]:         36 :     POSIX_GUARD_RESULT(s2n_connection_set_closed(conn));
     186         [ -  + ]:         36 :     POSIX_GUARD_RESULT(s2n_crypto_parameters_wipe(conn->secure));
     187                 :            : 
     188                 :         36 :     return S2N_SUCCESS;
     189                 :         36 : }
     190                 :            : 
     191                 :            : struct s2n_connection_deserialize {
     192                 :            :     uint8_t protocol_version;
     193                 :            :     struct s2n_cipher_suite *cipher_suite;
     194                 :            :     uint8_t client_sequence_number[S2N_TLS_SEQUENCE_NUM_LEN];
     195                 :            :     uint8_t server_sequence_number[S2N_TLS_SEQUENCE_NUM_LEN];
     196                 :            :     uint16_t max_fragment_len;
     197                 :            :     union {
     198                 :            :         struct {
     199                 :            :             uint8_t master_secret[S2N_TLS_SECRET_LEN];
     200                 :            :             uint8_t client_random[S2N_TLS_RANDOM_DATA_LEN];
     201                 :            :             uint8_t server_random[S2N_TLS_RANDOM_DATA_LEN];
     202                 :            :             /* Only set for blobs with protocol_version < S2N_TLS11 + CBC/composite cipher */
     203                 :            :             uint8_t client_implicit_iv[S2N_TLS_MAX_IV_LEN];
     204                 :            :             uint8_t server_implicit_iv[S2N_TLS_MAX_IV_LEN];
     205                 :            :         } tls12;
     206                 :            :         struct {
     207                 :            :             uint8_t secret_size;
     208                 :            :             uint8_t client_application_secret[S2N_TLS_SECRET_LEN];
     209                 :            :             uint8_t server_application_secret[S2N_TLS_SECRET_LEN];
     210                 :            :             uint8_t resumption_master_secret[S2N_TLS_SECRET_LEN];
     211                 :            :         } tls13;
     212                 :            :     } version;
     213                 :            : };
     214                 :            : 
     215                 :            : static S2N_RESULT s2n_connection_deserialize_tls13_secrets(struct s2n_stuffer *input,
     216                 :            :         struct s2n_connection_deserialize *parsed_values)
     217                 :         17 : {
     218 [ #  # ][ -  + ]:         17 :     RESULT_ENSURE_REF(input);
     219 [ -  + ][ #  # ]:         17 :     RESULT_ENSURE_REF(parsed_values);
     220                 :            : 
     221         [ -  + ]:         17 :     RESULT_GUARD_POSIX(s2n_hmac_digest_size(parsed_values->cipher_suite->prf_alg,
     222                 :         17 :             &parsed_values->version.tls13.secret_size));
     223         [ -  + ]:         17 :     RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls13.client_application_secret,
     224                 :         17 :             parsed_values->version.tls13.secret_size));
     225         [ -  + ]:         17 :     RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls13.server_application_secret,
     226                 :         17 :             parsed_values->version.tls13.secret_size));
     227         [ -  + ]:         17 :     RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls13.resumption_master_secret,
     228                 :         17 :             parsed_values->version.tls13.secret_size));
     229                 :            : 
     230                 :         17 :     return S2N_RESULT_OK;
     231                 :         17 : }
     232                 :            : 
     233                 :            : static S2N_RESULT s2n_connection_deserialize_secrets(struct s2n_stuffer *input,
     234                 :            :         struct s2n_connection_deserialize *parsed_values)
     235                 :         18 : {
     236 [ -  + ][ #  # ]:         18 :     RESULT_ENSURE_REF(input);
     237 [ -  + ][ #  # ]:         18 :     RESULT_ENSURE_REF(parsed_values);
     238 [ -  + ][ #  # ]:         18 :     RESULT_ENSURE_REF(parsed_values->cipher_suite);
     239 [ -  + ][ #  # ]:         18 :     RESULT_ENSURE_REF(parsed_values->cipher_suite->record_alg);
     240 [ #  # ][ -  + ]:         18 :     RESULT_ENSURE_REF(parsed_values->cipher_suite->record_alg->cipher);
     241                 :            : 
     242         [ -  + ]:         18 :     RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls12.master_secret, S2N_TLS_SECRET_LEN));
     243         [ -  + ]:         18 :     RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls12.client_random, S2N_TLS_RANDOM_DATA_LEN));
     244         [ -  + ]:         18 :     RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls12.server_random, S2N_TLS_RANDOM_DATA_LEN));
     245                 :            : 
     246                 :            :     /* TLS1.0 and SSLv3 CBC blobs trail the implicit IVs. See
     247                 :            :      * s2n_connection_serialize_secrets. Other blobs end at server_random. */
     248         [ +  + ]:         18 :     if (s2n_serialization_includes_implicit_iv(parsed_values->protocol_version,
     249                 :         18 :                 parsed_values->cipher_suite)) {
     250         [ -  + ]:          2 :         RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls12.client_implicit_iv,
     251                 :          2 :                 S2N_TLS_MAX_IV_LEN));
     252         [ -  + ]:          2 :         RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, parsed_values->version.tls12.server_implicit_iv,
     253                 :          2 :                 S2N_TLS_MAX_IV_LEN));
     254                 :          2 :     }
     255                 :            : 
     256                 :         18 :     return S2N_RESULT_OK;
     257                 :         18 : }
     258                 :            : 
     259                 :            : static S2N_RESULT s2n_connection_deserialize_parse(uint8_t *buffer, uint32_t buffer_length,
     260                 :            :         struct s2n_connection_deserialize *parsed_values)
     261                 :         38 : {
     262 [ #  # ][ -  + ]:         38 :     RESULT_ENSURE_REF(parsed_values);
     263                 :            : 
     264                 :         38 :     struct s2n_blob context_blob = { 0 };
     265         [ -  + ]:         38 :     RESULT_GUARD_POSIX(s2n_blob_init(&context_blob, buffer, buffer_length));
     266                 :         38 :     struct s2n_stuffer input = { 0 };
     267         [ -  + ]:         38 :     RESULT_GUARD_POSIX(s2n_stuffer_init_written(&input, &context_blob));
     268                 :            : 
     269                 :         38 :     uint64_t serialized_version = 0;
     270         [ -  + ]:         38 :     RESULT_GUARD_POSIX(s2n_stuffer_read_uint64(&input, &serialized_version));
     271                 :            :     /* No other version is supported currently */
     272 [ +  + ][ +  - ]:         38 :     RESULT_ENSURE_EQ(serialized_version, S2N_SERIALIZED_CONN_V1);
     273                 :            : 
     274                 :         37 :     uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN] = { 0 };
     275         [ -  + ]:         37 :     RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(&input, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
     276                 :         37 :     parsed_values->protocol_version = (protocol_version[0] * 10) + protocol_version[1];
     277                 :            : 
     278 [ +  - ][ +  + ]:         37 :     RESULT_ENSURE(parsed_values->protocol_version >= S2N_SSLv3 && parsed_values->protocol_version <= s2n_highest_protocol_version,
                 [ +  + ]
     279                 :         35 :             S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
     280                 :            : 
     281                 :         35 :     uint8_t cipher_suite[S2N_TLS_CIPHER_SUITE_LEN] = { 0 };
     282         [ -  + ]:         35 :     RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(&input, cipher_suite, S2N_TLS_CIPHER_SUITE_LEN));
     283         [ -  + ]:         35 :     RESULT_GUARD(s2n_cipher_suite_from_iana(cipher_suite, S2N_TLS_CIPHER_SUITE_LEN, &parsed_values->cipher_suite));
     284                 :            : 
     285                 :            :     /* SSLv3 uses a cloned cipher suite variant with the SSLv3-specific
     286                 :            :      * record_alg. s2n_cipher_suite_from_iana returns the base; swap to the
     287                 :            :      * variant. Same lookup-then-swap pattern as s2n_set_cipher_as_client and
     288                 :            :      * s2n_set_cipher_as_server during handshake.
     289                 :            :      */
     290         [ +  + ]:         35 :     if (parsed_values->protocol_version == S2N_SSLv3) {
     291 [ #  # ][ -  + ]:          2 :         RESULT_ENSURE_REF(parsed_values->cipher_suite->sslv3_cipher_suite);
     292                 :          2 :         parsed_values->cipher_suite = parsed_values->cipher_suite->sslv3_cipher_suite;
     293                 :          2 :     }
     294                 :            : 
     295         [ -  + ]:         35 :     RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(&input, parsed_values->client_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
     296         [ -  + ]:         35 :     RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(&input, parsed_values->server_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
     297                 :            : 
     298         [ -  + ]:         35 :     RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(&input, &parsed_values->max_fragment_len));
     299                 :            : 
     300         [ +  + ]:         35 :     if (parsed_values->protocol_version >= S2N_TLS13) {
     301         [ -  + ]:         17 :         RESULT_GUARD(s2n_connection_deserialize_tls13_secrets(&input, parsed_values));
     302                 :         18 :     } else {
     303         [ -  + ]:         18 :         RESULT_GUARD(s2n_connection_deserialize_secrets(&input, parsed_values));
     304                 :         18 :     }
     305                 :            : 
     306                 :         35 :     return S2N_RESULT_OK;
     307                 :         35 : }
     308                 :            : 
     309                 :            : /* Boringssl and AWS-LC do a special check in tls13 during the first call to encrypt after
     310                 :            :  * initialization. In the first call they assume that the sequence number will be 0, and therefore
     311                 :            :  * the provided nonce is equivalent to the implicit IV because 0 ^ iv = iv. The recovered implicit IV
     312                 :            :  * is stored and used later on to ensure the monotonicity of sequence numbers.
     313                 :            :  *
     314                 :            :  * In the case of deserialization, in the first call the sequence number may not be 0.
     315                 :            :  * Therefore the provided nonce cannot be considered to be the implicit IV because n ^ iv != iv.
     316                 :            :  * This inability to get the correct implicit IV causes issues with encryption later on.
     317                 :            :  *
     318                 :            :  * To resolve this we perform one throwaway encryption call with a zero sequence number after
     319                 :            :  * deserialization. This allows the libcrypto to recover the implicit IV correctly.
     320                 :            :  */
     321                 :            : static S2N_RESULT s2n_initialize_implicit_iv(struct s2n_connection *conn, struct s2n_connection_deserialize *parsed_values)
     322                 :         17 : {
     323 [ #  # ][ -  + ]:         17 :     RESULT_ENSURE_REF(conn);
     324 [ #  # ][ -  + ]:         17 :     RESULT_ENSURE_REF(parsed_values);
     325 [ #  # ][ -  + ]:         17 :     RESULT_ENSURE_REF(conn->secure);
     326 [ -  + ][ #  # ]:         17 :     RESULT_ENSURE_REF(conn->server);
     327 [ -  + ][ #  # ]:         17 :     RESULT_ENSURE_REF(conn->client);
     328                 :            : 
     329         [ +  - ]:         17 :     if (!s2n_libcrypto_supports_evp_aead_tls()) {
     330                 :         17 :         return S2N_RESULT_OK;
     331                 :         17 :     }
     332                 :            : 
     333                 :          0 :     uint8_t *seq_num = parsed_values->server_sequence_number;
     334                 :          0 :     uint8_t *implicit_iv = conn->server->server_implicit_iv;
     335                 :          0 :     struct s2n_session_key key = conn->server->server_key;
     336         [ #  # ]:          0 :     if (conn->mode == S2N_CLIENT) {
     337                 :          0 :         seq_num = parsed_values->client_sequence_number;
     338                 :          0 :         implicit_iv = conn->client->client_implicit_iv;
     339                 :          0 :         key = conn->client->client_key;
     340                 :          0 :     }
     341                 :            : 
     342                 :          0 :     uint64_t parsed_sequence_num = 0;
     343                 :          0 :     struct s2n_blob seq_num_blob = { 0 };
     344         [ #  # ]:          0 :     RESULT_GUARD_POSIX(s2n_blob_init(&seq_num_blob, seq_num, S2N_TLS_SEQUENCE_NUM_LEN));
     345         [ #  # ]:          0 :     RESULT_GUARD_POSIX(s2n_sequence_number_to_uint64(&seq_num_blob, &parsed_sequence_num));
     346                 :            : 
     347                 :            :     /* we don't need to initialize the context when the sequence number is 0 */
     348         [ #  # ]:          0 :     if (parsed_sequence_num == 0) {
     349                 :          0 :         return S2N_RESULT_OK;
     350                 :          0 :     }
     351                 :            : 
     352                 :          0 :     uint8_t in_data[S2N_TLS_GCM_TAG_LEN] = { 0 };
     353                 :          0 :     struct s2n_blob in_blob = { 0 };
     354         [ #  # ]:          0 :     RESULT_GUARD_POSIX(s2n_blob_init(&in_blob, in_data, sizeof(in_data)));
     355                 :            : 
     356                 :          0 :     struct s2n_blob iv_blob = { 0 };
     357         [ #  # ]:          0 :     RESULT_GUARD_POSIX(s2n_blob_init(&iv_blob, implicit_iv, S2N_TLS13_FIXED_IV_LEN));
     358                 :            : 
     359                 :          0 :     struct s2n_blob aad_blob = { 0 };
     360         [ #  # ]:          0 :     RESULT_GUARD_POSIX(s2n_blob_init(&aad_blob, NULL, 0));
     361                 :            : 
     362 [ #  # ][ #  # ]:          0 :     RESULT_ENSURE_REF(conn->secure->cipher_suite);
     363 [ #  # ][ #  # ]:          0 :     RESULT_ENSURE_REF(conn->secure->cipher_suite->record_alg);
     364 [ #  # ][ #  # ]:          0 :     RESULT_ENSURE_REF(conn->secure->cipher_suite->record_alg->cipher);
     365         [ #  # ]:          0 :     RESULT_GUARD_POSIX(conn->secure->cipher_suite->record_alg->cipher->io.aead.encrypt(&key,
     366                 :          0 :             &iv_blob, &aad_blob, &in_blob, &in_blob));
     367                 :            : 
     368                 :          0 :     return S2N_RESULT_OK;
     369                 :          0 : }
     370                 :            : 
     371                 :            : static S2N_RESULT s2n_restore_tls13_secrets(struct s2n_connection *conn, struct s2n_connection_deserialize *parsed_values)
     372                 :         17 : {
     373 [ #  # ][ -  + ]:         17 :     RESULT_ENSURE_REF(conn);
     374 [ -  + ][ #  # ]:         17 :     RESULT_ENSURE_REF(parsed_values);
     375                 :            : 
     376 [ #  # ][ -  + ]:         17 :     RESULT_CHECKED_MEMCPY(conn->secrets.version.tls13.client_app_secret,
                 [ +  - ]
     377                 :         17 :             parsed_values->version.tls13.client_application_secret, parsed_values->version.tls13.secret_size);
     378 [ #  # ][ -  + ]:         17 :     RESULT_CHECKED_MEMCPY(conn->secrets.version.tls13.server_app_secret,
                 [ +  - ]
     379                 :         17 :             parsed_values->version.tls13.server_application_secret, parsed_values->version.tls13.secret_size);
     380 [ -  + ][ #  # ]:         17 :     RESULT_CHECKED_MEMCPY(conn->secrets.version.tls13.resumption_master_secret,
                 [ +  - ]
     381                 :         17 :             parsed_values->version.tls13.resumption_master_secret, parsed_values->version.tls13.secret_size);
     382                 :            : 
     383         [ -  + ]:         17 :     RESULT_GUARD(s2n_tls13_key_schedule_set_key(conn, S2N_MASTER_SECRET, S2N_SERVER));
     384         [ -  + ]:         17 :     RESULT_GUARD(s2n_tls13_key_schedule_set_key(conn, S2N_MASTER_SECRET, S2N_CLIENT));
     385                 :            : 
     386         [ -  + ]:         17 :     RESULT_GUARD(s2n_initialize_implicit_iv(conn, parsed_values));
     387                 :            : 
     388                 :         17 :     return S2N_RESULT_OK;
     389                 :         17 : }
     390                 :            : 
     391                 :            : static S2N_RESULT s2n_restore_secrets(struct s2n_connection *conn, struct s2n_connection_deserialize *parsed_values)
     392                 :         18 : {
     393 [ #  # ][ -  + ]:         18 :     RESULT_ENSURE_REF(conn);
     394 [ #  # ][ -  + ]:         18 :     RESULT_ENSURE_REF(parsed_values);
     395 [ #  # ][ -  + ]:         18 :     RESULT_ENSURE_REF(conn->secure);
     396                 :            : 
     397 [ -  + ][ #  # ]:         18 :     RESULT_CHECKED_MEMCPY(conn->secrets.version.tls12.master_secret, parsed_values->version.tls12.master_secret,
                 [ +  - ]
     398                 :         18 :             S2N_TLS_SECRET_LEN);
     399 [ -  + ][ #  # ]:         18 :     RESULT_CHECKED_MEMCPY(conn->client_hello.random, parsed_values->version.tls12.client_random,
                 [ +  - ]
     400                 :         18 :             S2N_TLS_RANDOM_DATA_LEN);
     401 [ -  + ][ #  # ]:         18 :     RESULT_CHECKED_MEMCPY(conn->handshake_params.server_random, parsed_values->version.tls12.server_random,
                 [ +  - ]
     402                 :         18 :             S2N_TLS_RANDOM_DATA_LEN);
     403         [ -  + ]:         18 :     RESULT_GUARD_POSIX(s2n_prf_key_expansion(conn));
     404                 :            : 
     405                 :            :     /* PRF key expansion seeds the implicit IVs from the master secret, which is
     406                 :            :      * only correct at record 0. For TLS1.0 and SSLv3 CBC the blob ships the
     407                 :            :      * current IV state so the connection can continue where it left off.
     408                 :            :      */
     409         [ +  + ]:         18 :     if (s2n_serialization_includes_implicit_iv(parsed_values->protocol_version,
     410                 :         18 :                 parsed_values->cipher_suite)) {
     411 [ -  + ][ #  # ]:          2 :         RESULT_CHECKED_MEMCPY(conn->secure->client_implicit_iv,
                 [ +  - ]
     412                 :          2 :                 parsed_values->version.tls12.client_implicit_iv, S2N_TLS_MAX_IV_LEN);
     413 [ -  + ][ #  # ]:          2 :         RESULT_CHECKED_MEMCPY(conn->secure->server_implicit_iv,
                 [ +  - ]
     414                 :          2 :                 parsed_values->version.tls12.server_implicit_iv, S2N_TLS_MAX_IV_LEN);
     415                 :          2 :     }
     416                 :            : 
     417                 :         18 :     return S2N_RESULT_OK;
     418                 :         18 : }
     419                 :            : 
     420                 :            : int s2n_connection_deserialize(struct s2n_connection *conn, uint8_t *buffer, uint32_t buffer_length)
     421                 :         40 : {
     422 [ +  + ][ +  - ]:         40 :     POSIX_ENSURE_REF(conn);
     423 [ -  + ][ #  # ]:         39 :     POSIX_ENSURE_REF(conn->secure);
     424 [ +  + ][ +  - ]:         39 :     POSIX_ENSURE_REF(buffer);
     425                 :            : 
     426                 :            :     /* The serialized blob does not include a MAC or signature. All values from the buffer
     427                 :            :      * are trusted after basic format validation. Callers must verify the integrity of the
     428                 :            :      * buffer before calling this function. See the s2n_connection_deserialize API docs.
     429                 :            :      */
     430                 :            : 
     431                 :            :     /* Read parsed values into a temporary struct so that the connection is unaltered if parsing fails */
     432                 :         38 :     struct s2n_connection_deserialize parsed_values = { 0 };
     433 [ +  + ][ +  - ]:         38 :     POSIX_ENSURE(s2n_result_is_ok(s2n_connection_deserialize_parse(buffer, buffer_length, &parsed_values)),
     434                 :         35 :             S2N_ERR_INVALID_SERIALIZED_CONNECTION);
     435                 :            : 
     436                 :            :     /* Rehydrate fields now that parsing has completed successfully */
     437                 :         35 :     conn->actual_protocol_version = parsed_values.protocol_version;
     438                 :         35 :     conn->secure->cipher_suite = parsed_values.cipher_suite;
     439         [ -  + ]:         35 :     POSIX_GUARD_RESULT(s2n_connection_set_max_fragment_length(conn, parsed_values.max_fragment_len));
     440                 :            : 
     441                 :            :     /* Mark the connection as having been deserialized */
     442                 :         35 :     conn->deserialized_conn = true;
     443                 :            : 
     444                 :            :     /* Key expansion */
     445         [ +  + ]:         35 :     if (parsed_values.protocol_version >= S2N_TLS13) {
     446         [ -  + ]:         17 :         POSIX_GUARD_RESULT(s2n_restore_tls13_secrets(conn, &parsed_values));
     447                 :         18 :     } else {
     448         [ -  + ]:         18 :         POSIX_GUARD_RESULT(s2n_restore_secrets(conn, &parsed_values));
     449                 :         18 :     }
     450                 :            : 
     451                 :            :     /* Wait until after key generation to restore sequence numbers since they get zeroed during
     452                 :            :      * key expansion */
     453 [ #  # ][ -  + ]:         35 :     POSIX_CHECKED_MEMCPY(conn->secure->client_sequence_number, parsed_values.client_sequence_number,
                 [ +  - ]
     454                 :         35 :             S2N_TLS_SEQUENCE_NUM_LEN);
     455 [ -  + ][ #  # ]:         35 :     POSIX_CHECKED_MEMCPY(conn->secure->server_sequence_number, parsed_values.server_sequence_number,
                 [ +  - ]
     456                 :         35 :             S2N_TLS_SEQUENCE_NUM_LEN);
     457                 :            : 
     458                 :         35 :     conn->client = conn->secure;
     459                 :         35 :     conn->server = conn->secure;
     460                 :            : 
     461                 :         35 :     return S2N_SUCCESS;
     462                 :         35 : }

Generated by: LCOV version 1.14