LCOV - code coverage report
Current view: top level - tls - s2n_client_key_exchange.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 122 174 70.1 %
Date: 2026-10-06 07:26:09 Functions: 11 16 68.8 %
Branches: 69 224 30.8 %

           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 "api/s2n.h"
      17                 :            : #include "crypto/s2n_dhe.h"
      18                 :            : #include "crypto/s2n_pkey.h"
      19                 :            : #include "error/s2n_errno.h"
      20                 :            : #include "stuffer/s2n_stuffer.h"
      21                 :            : #include "tls/s2n_async_pkey.h"
      22                 :            : #include "tls/s2n_cipher_suites.h"
      23                 :            : #include "tls/s2n_connection.h"
      24                 :            : #include "tls/s2n_handshake.h"
      25                 :            : #include "tls/s2n_kem.h"
      26                 :            : #include "tls/s2n_kex.h"
      27                 :            : #include "tls/s2n_key_log.h"
      28                 :            : #include "tls/s2n_resume.h"
      29                 :            : #include "utils/s2n_random.h"
      30                 :            : #include "utils/s2n_safety.h"
      31                 :            : 
      32                 :            : typedef S2N_RESULT s2n_kex_client_key_method(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key);
      33                 :            : typedef void *s2n_stuffer_action(struct s2n_stuffer *stuffer, uint32_t data_len);
      34                 :            : 
      35                 :            : static int s2n_rsa_client_key_recv_complete(struct s2n_connection *conn, bool rsa_failed, struct s2n_blob *shared_key);
      36                 :            : 
      37                 :            : /*
      38                 :            :  *= https://www.rfc-editor.org/rfc/rfc5246#section-7.4.7.1
      39                 :            :  *#   client_version
      40                 :            :  *#      The latest (newest) version supported by the client.  This is
      41                 :            :  *#      used to detect version rollback attacks.
      42                 :            :  *
      43                 :            :  * However, TLS1.2 rsa kex does not account for the existence of TLS1.3.
      44                 :            :  * Therefore "latest" actually means "latest up to TLS1.2".
      45                 :            :  */
      46                 :            : static S2N_RESULT s2n_client_key_exchange_get_rsa_client_version(struct s2n_connection *conn,
      47                 :            :         uint8_t client_version[S2N_TLS_PROTOCOL_VERSION_LEN])
      48                 :       3154 : {
      49 [ -  + ][ #  # ]:       3154 :     RESULT_ENSURE_REF(conn);
      50 [ #  # ][ -  + ]:       3154 :     RESULT_ENSURE_REF(client_version);
      51         [ +  + ]:       3154 :     uint8_t client_version_for_rsa = S2N_MIN(conn->client_protocol_version, S2N_TLS12);
      52                 :       3154 :     client_version[0] = client_version_for_rsa / 10;
      53                 :       3154 :     client_version[1] = client_version_for_rsa % 10;
      54                 :       3154 :     return S2N_RESULT_OK;
      55                 :       3154 : }
      56                 :            : 
      57                 :            : static int s2n_hybrid_client_action(struct s2n_connection *conn, struct s2n_blob *combined_shared_key,
      58                 :            :         s2n_kex_client_key_method kex_method, uint32_t *cursor, s2n_stuffer_action stuffer_action)
      59                 :          0 : {
      60 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(conn);
      61 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(conn->secure);
      62 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(kex_method);
      63 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(stuffer_action);
      64                 :            : 
      65                 :          0 :     struct s2n_stuffer *io = &conn->handshake.io;
      66                 :          0 :     const struct s2n_kex *hybrid_kex_0 = conn->secure->cipher_suite->key_exchange_alg->hybrid[0];
      67                 :          0 :     const struct s2n_kex *hybrid_kex_1 = conn->secure->cipher_suite->key_exchange_alg->hybrid[1];
      68                 :            : 
      69                 :            :     /* Keep a copy to the start of the entire hybrid client key exchange message for the hybrid PRF */
      70                 :          0 :     struct s2n_blob *client_key_exchange_message = &conn->kex_params.client_key_exchange_message;
      71                 :          0 :     client_key_exchange_message->data = stuffer_action(io, 0);
      72 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(client_key_exchange_message->data);
      73                 :          0 :     const uint32_t start_cursor = *cursor;
      74                 :            : 
      75                 :          0 :     DEFER_CLEANUP(struct s2n_blob shared_key_0 = { 0 }, s2n_free);
      76         [ #  # ]:          0 :     POSIX_GUARD_RESULT(kex_method(hybrid_kex_0, conn, &shared_key_0));
      77                 :            : 
      78                 :          0 :     struct s2n_blob *shared_key_1 = &(conn->kex_params.kem_params.shared_secret);
      79         [ #  # ]:          0 :     POSIX_GUARD_RESULT(kex_method(hybrid_kex_1, conn, shared_key_1));
      80                 :            : 
      81                 :          0 :     const uint32_t end_cursor = *cursor;
      82 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_GTE(end_cursor, start_cursor);
      83                 :          0 :     client_key_exchange_message->size = end_cursor - start_cursor;
      84                 :            : 
      85         [ #  # ]:          0 :     POSIX_GUARD(s2n_alloc(combined_shared_key, shared_key_0.size + shared_key_1->size));
      86                 :          0 :     struct s2n_stuffer stuffer_combiner = { 0 };
      87         [ #  # ]:          0 :     POSIX_GUARD(s2n_stuffer_init(&stuffer_combiner, combined_shared_key));
      88         [ #  # ]:          0 :     POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, &shared_key_0));
      89         [ #  # ]:          0 :     POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, shared_key_1));
      90                 :            : 
      91         [ #  # ]:          0 :     POSIX_GUARD(s2n_kem_free(&conn->kex_params.kem_params));
      92                 :            : 
      93                 :          0 :     return 0;
      94                 :          0 : }
      95                 :            : 
      96                 :            : static int s2n_calculate_keys(struct s2n_connection *conn, struct s2n_blob *shared_key)
      97                 :       4524 : {
      98 [ -  + ][ #  # ]:       4524 :     POSIX_ENSURE_REF(conn);
      99 [ -  + ][ #  # ]:       4524 :     POSIX_ENSURE_REF(conn->secure);
     100 [ #  # ][ -  + ]:       4524 :     POSIX_ENSURE_REF(conn->secure->cipher_suite);
     101                 :            : 
     102                 :            :     /* Turn the pre-master secret into a master secret */
     103         [ -  + ]:       4524 :     POSIX_GUARD_RESULT(s2n_kex_tls_prf(conn->secure->cipher_suite->key_exchange_alg, conn, shared_key));
     104                 :            : 
     105                 :            :     /* Expand the keys */
     106         [ -  + ]:       4524 :     POSIX_GUARD(s2n_prf_key_expansion(conn));
     107                 :            :     /* Save the master secret in the cache.
     108                 :            :      * Failing to cache the session should not affect the current handshake.
     109                 :            :      */
     110         [ +  + ]:       4524 :     if (s2n_allowed_to_cache_connection(conn)) {
     111                 :          7 :         s2n_result_ignore(s2n_store_to_cache(conn));
     112                 :          7 :     }
     113                 :            :     /* log the secret, if needed */
     114                 :       4524 :     s2n_result_ignore(s2n_key_log_tls12_secret(conn));
     115                 :       4524 :     return 0;
     116                 :       4524 : }
     117                 :            : 
     118                 :            : int s2n_rsa_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key)
     119                 :       1515 : {
     120                 :            :     /* Set shared_key before async guard to pass the proper shared_key to the caller upon async completion */
     121 [ -  + ][ #  # ]:       1515 :     POSIX_ENSURE_REF(shared_key);
     122                 :       1515 :     shared_key->data = conn->secrets.version.tls12.rsa_premaster_secret;
     123                 :       1515 :     shared_key->size = S2N_TLS_SECRET_LEN;
     124                 :            : 
     125 [ -  + ][ +  + ]:       1515 :     S2N_ASYNC_PKEY_GUARD(conn);
         [ +  + ][ +  + ]
         [ -  + ][ +  - ]
     126                 :            : 
     127                 :       1454 :     struct s2n_stuffer *in = &conn->handshake.io;
     128                 :       1454 :     uint16_t length = 0;
     129                 :            : 
     130         [ +  + ]:       1454 :     if (conn->actual_protocol_version == S2N_SSLv3) {
     131                 :         36 :         length = s2n_stuffer_data_available(in);
     132                 :       1418 :     } else {
     133         [ -  + ]:       1418 :         POSIX_GUARD(s2n_stuffer_read_uint16(in, &length));
     134                 :       1418 :     }
     135                 :            : 
     136 [ -  + ][ #  # ]:       1454 :     S2N_ERROR_IF(length > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE);
     137                 :            : 
     138                 :       1454 :     uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN] = { 0 };
     139         [ -  + ]:       1454 :     POSIX_GUARD_RESULT(s2n_client_key_exchange_get_rsa_client_version(conn, protocol_version));
     140                 :            : 
     141                 :            :     /* Decrypt the pre-master secret */
     142                 :       1454 :     struct s2n_blob encrypted = { 0 };
     143         [ -  + ]:       1454 :     POSIX_GUARD(s2n_blob_init(&encrypted, s2n_stuffer_raw_read(in, length), length));
     144 [ #  # ][ -  + ]:       1454 :     POSIX_ENSURE_REF(encrypted.data);
     145 [ #  # ][ -  + ]:       1454 :     POSIX_ENSURE_GT(encrypted.size, 0);
     146                 :            : 
     147                 :            :     /* First: use a random pre-master secret */
     148         [ -  + ]:       1454 :     POSIX_GUARD_RESULT(s2n_get_private_random_data(shared_key));
     149                 :       1454 :     conn->secrets.version.tls12.rsa_premaster_secret[0] = protocol_version[0];
     150                 :       1454 :     conn->secrets.version.tls12.rsa_premaster_secret[1] = protocol_version[1];
     151                 :            : 
     152         [ +  + ]:       1454 :     S2N_ASYNC_PKEY_DECRYPT(conn, &encrypted, shared_key, s2n_rsa_client_key_recv_complete);
     153                 :          0 : }
     154                 :            : 
     155                 :            : int s2n_rsa_client_key_recv_complete(struct s2n_connection *conn, bool rsa_failed, struct s2n_blob *decrypted)
     156                 :       1452 : {
     157 [ -  + ][ #  # ]:       1452 :     S2N_ERROR_IF(decrypted->size != S2N_TLS_SECRET_LEN, S2N_ERR_SIZE_MISMATCH);
     158                 :            : 
     159                 :            :     /* Avoid copying the same buffer for the case where async pkey is not used */
     160         [ +  + ]:       1452 :     if (conn->secrets.version.tls12.rsa_premaster_secret != decrypted->data) {
     161                 :            :         /* Copy (maybe) decrypted data into shared key */
     162 [ -  + ][ #  # ]:        837 :         POSIX_CHECKED_MEMCPY(conn->secrets.version.tls12.rsa_premaster_secret, decrypted->data, S2N_TLS_SECRET_LEN);
                 [ +  - ]
     163                 :        837 :     }
     164                 :            : 
     165                 :            :     /* Get client hello protocol version for comparison with decrypted data */
     166                 :       1452 :     uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN] = { 0 };
     167         [ -  + ]:       1452 :     POSIX_GUARD_RESULT(s2n_client_key_exchange_get_rsa_client_version(conn, protocol_version));
     168                 :            : 
     169                 :       1452 :     conn->handshake.rsa_failed = rsa_failed;
     170                 :            : 
     171                 :            :     /* Set rsa_failed to true, if it isn't already, if the protocol version isn't what we expect */
     172                 :       1452 :     conn->handshake.rsa_failed |= !s2n_constant_time_equals(protocol_version,
     173                 :       1452 :             conn->secrets.version.tls12.rsa_premaster_secret, S2N_TLS_PROTOCOL_VERSION_LEN);
     174                 :            : 
     175                 :            :     /* Required to protect against Bleichenbacher attack.
     176                 :            :      * See https://www.rfc-editor.org/rfc/rfc5246#section-7.4.7.1
     177                 :            :      * We choose the first option: always setting the version in the rsa_premaster_secret
     178                 :            :      * from our local view of the client_hello value.
     179                 :            :      */
     180                 :       1452 :     conn->secrets.version.tls12.rsa_premaster_secret[0] = protocol_version[0];
     181                 :       1452 :     conn->secrets.version.tls12.rsa_premaster_secret[1] = protocol_version[1];
     182                 :            : 
     183                 :       1452 :     return 0;
     184                 :       1452 : }
     185                 :            : 
     186                 :            : int s2n_dhe_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key)
     187                 :         24 : {
     188                 :         24 :     struct s2n_stuffer *in = &conn->handshake.io;
     189                 :            : 
     190                 :            :     /* Get the shared key */
     191         [ -  + ]:         24 :     POSIX_GUARD(s2n_dh_compute_shared_secret_as_server(&conn->kex_params.server_dh_params, in, shared_key));
     192                 :            :     /* We don't need the server params any more */
     193         [ -  + ]:         24 :     POSIX_GUARD(s2n_dh_params_free(&conn->kex_params.server_dh_params));
     194                 :         24 :     return 0;
     195                 :         24 : }
     196                 :            : 
     197                 :            : int s2n_ecdhe_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key)
     198                 :        800 : {
     199                 :        800 :     struct s2n_stuffer *in = &conn->handshake.io;
     200                 :            : 
     201                 :            :     /* Get the shared key */
     202         [ -  + ]:        800 :     POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_as_server(&conn->kex_params.server_ecc_evp_params, in, shared_key));
     203                 :            :     /* We don't need the server params any more */
     204         [ -  + ]:        800 :     POSIX_GUARD(s2n_ecc_evp_params_free(&conn->kex_params.server_ecc_evp_params));
     205                 :        800 :     return 0;
     206                 :        800 : }
     207                 :            : 
     208                 :            : int s2n_kem_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key)
     209                 :          0 : {
     210                 :            :     /* s2n_kem_recv_ciphertext() writes the KEM shared secret directly to
     211                 :            :      * conn->kex_params.kem_params. However, the calling function
     212                 :            :      * likely expects *shared_key to point to the shared secret. We 
     213                 :            :      * can't reassign *shared_key to point to kem_params.shared_secret,
     214                 :            :      * because that would require us to take struct s2n_blob **shared_key
     215                 :            :      * as the argument, but we can't (easily) change the function signature
     216                 :            :      * because it has to be consistent with what is defined in s2n_kex.
     217                 :            :      *
     218                 :            :      * So, we assert that the caller already has *shared_key pointing
     219                 :            :      * to kem_params.shared_secret. */
     220 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(shared_key);
     221 [ #  # ][ #  # ]:          0 :     S2N_ERROR_IF(shared_key != &(conn->kex_params.kem_params.shared_secret), S2N_ERR_SAFETY);
     222                 :          0 :     kem_ciphertext_key_size ciphertext_length = 0;
     223         [ #  # ]:          0 :     POSIX_GUARD(s2n_stuffer_read_uint16(&conn->handshake.io, &ciphertext_length));
     224 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE(ciphertext_length == conn->kex_params.kem_params.kem->ciphertext_length, S2N_ERR_BAD_MESSAGE);
     225                 :            : 
     226         [ #  # ]:          0 :     POSIX_GUARD(s2n_kem_recv_ciphertext(&(conn->handshake.io), &(conn->kex_params.kem_params)));
     227                 :            : 
     228                 :          0 :     return 0;
     229                 :          0 : }
     230                 :            : 
     231                 :            : int s2n_hybrid_client_key_recv(struct s2n_connection *conn, struct s2n_blob *combined_shared_key)
     232                 :          0 : {
     233                 :          0 :     return s2n_hybrid_client_action(conn, combined_shared_key, &s2n_kex_client_key_recv, &conn->handshake.io.read_cursor,
     234                 :          0 :             &s2n_stuffer_raw_read);
     235                 :          0 : }
     236                 :            : 
     237                 :            : int s2n_client_key_recv(struct s2n_connection *conn)
     238                 :       2339 : {
     239 [ -  + ][ #  # ]:       2339 :     POSIX_ENSURE_REF(conn);
     240 [ -  + ][ #  # ]:       2339 :     POSIX_ENSURE_REF(conn->secure);
     241 [ -  + ][ #  # ]:       2339 :     POSIX_ENSURE_REF(conn->secure->cipher_suite);
     242                 :            : 
     243                 :       2339 :     const struct s2n_kex *key_exchange = conn->secure->cipher_suite->key_exchange_alg;
     244                 :       2339 :     DEFER_CLEANUP(struct s2n_blob shared_key = { 0 }, s2n_free_or_wipe);
     245         [ +  + ]:       2339 :     POSIX_GUARD_RESULT(s2n_kex_client_key_recv(key_exchange, conn, &shared_key));
     246                 :            : 
     247         [ -  + ]:       2276 :     POSIX_GUARD(s2n_calculate_keys(conn, &shared_key));
     248                 :       2276 :     return 0;
     249                 :       2276 : }
     250                 :            : 
     251                 :            : int s2n_dhe_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key)
     252                 :         24 : {
     253                 :         24 :     struct s2n_stuffer *out = &conn->handshake.io;
     254         [ -  + ]:         24 :     POSIX_GUARD(s2n_dh_compute_shared_secret_as_client(&conn->kex_params.server_dh_params, out, shared_key));
     255                 :            : 
     256                 :            :     /* We don't need the server params any more */
     257         [ -  + ]:         24 :     POSIX_GUARD(s2n_dh_params_free(&conn->kex_params.server_dh_params));
     258                 :         24 :     return 0;
     259                 :         24 : }
     260                 :            : 
     261                 :            : int s2n_ecdhe_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key)
     262                 :        770 : {
     263                 :        770 :     struct s2n_stuffer *out = &conn->handshake.io;
     264         [ -  + ]:        770 :     POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_as_client(&conn->kex_params.server_ecc_evp_params, out, shared_key));
     265                 :            : 
     266                 :            :     /* We don't need the server params any more */
     267         [ -  + ]:        770 :     POSIX_GUARD(s2n_ecc_evp_params_free(&conn->kex_params.server_ecc_evp_params));
     268                 :        770 :     return 0;
     269                 :        770 : }
     270                 :            : 
     271                 :            : int s2n_rsa_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key)
     272                 :        248 : {
     273                 :        248 :     uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN] = { 0 };
     274         [ -  + ]:        248 :     POSIX_GUARD_RESULT(s2n_client_key_exchange_get_rsa_client_version(conn, protocol_version));
     275                 :            : 
     276                 :        248 :     shared_key->data = conn->secrets.version.tls12.rsa_premaster_secret;
     277                 :        248 :     shared_key->size = S2N_TLS_SECRET_LEN;
     278                 :            : 
     279         [ -  + ]:        248 :     POSIX_GUARD_RESULT(s2n_get_private_random_data(shared_key));
     280                 :            : 
     281                 :            :     /* Over-write the first two bytes with the client hello version, per RFC2246/RFC4346/RFC5246 7.4.7.1.
     282                 :            :      * The latest version supported by client (as seen from the the client hello version) are <= TLS1.2
     283                 :            :      * for all clients, because TLS 1.3 clients freezes the TLS1.2 legacy version in client hello.
     284                 :            :      */
     285 [ #  # ][ -  + ]:        248 :     POSIX_CHECKED_MEMCPY(conn->secrets.version.tls12.rsa_premaster_secret, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN);
                 [ +  - ]
     286                 :            : 
     287                 :        248 :     uint32_t encrypted_size = 0;
     288         [ -  + ]:        248 :     POSIX_GUARD_RESULT(s2n_pkey_size(&conn->handshake_params.server_public_key, &encrypted_size));
     289 [ -  + ][ #  # ]:        248 :     S2N_ERROR_IF(encrypted_size > 0xffff, S2N_ERR_SIZE_MISMATCH);
     290                 :            : 
     291         [ +  + ]:        248 :     if (conn->actual_protocol_version > S2N_SSLv3) {
     292         [ -  + ]:        212 :         POSIX_GUARD(s2n_stuffer_write_uint16(&conn->handshake.io, encrypted_size));
     293                 :        212 :     }
     294                 :            : 
     295                 :        248 :     struct s2n_blob encrypted = { 0 };
     296                 :        248 :     encrypted.data = s2n_stuffer_raw_write(&conn->handshake.io, encrypted_size);
     297                 :        248 :     encrypted.size = encrypted_size;
     298 [ -  + ][ #  # ]:        248 :     POSIX_ENSURE_REF(encrypted.data);
     299                 :            : 
     300                 :            :     /* Encrypt the secret and send it on */
     301         [ -  + ]:        248 :     POSIX_GUARD(s2n_pkey_encrypt(&conn->handshake_params.server_public_key, shared_key, &encrypted));
     302                 :            : 
     303                 :            :     /* We don't need the key any more, so free it */
     304         [ -  + ]:        248 :     POSIX_GUARD(s2n_pkey_free(&conn->handshake_params.server_public_key));
     305                 :        248 :     return 0;
     306                 :        248 : }
     307                 :            : 
     308                 :            : int s2n_kem_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key)
     309                 :          0 : {
     310                 :            :     /* s2n_kem_send_ciphertext() writes the KEM shared secret directly to
     311                 :            :      * conn->kex_params.kem_params. However, the calling function
     312                 :            :      * likely expects *shared_key to point to the shared secret. We
     313                 :            :      * can't reassign *shared_key to point to kem_params.shared_secret,
     314                 :            :      * because that would require us to take struct s2n_blob **shared_key
     315                 :            :      * as the argument, but we can't (easily) change the function signature
     316                 :            :      * because it has to be consistent with what is defined in s2n_kex.
     317                 :            :      *
     318                 :            :      * So, we assert that the caller already has *shared_key pointing
     319                 :            :      * to kem_params.shared_secret. */
     320 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(shared_key);
     321 [ #  # ][ #  # ]:          0 :     S2N_ERROR_IF(shared_key != &(conn->kex_params.kem_params.shared_secret), S2N_ERR_SAFETY);
     322                 :            : 
     323         [ #  # ]:          0 :     POSIX_GUARD(s2n_stuffer_write_uint16(&conn->handshake.io, conn->kex_params.kem_params.kem->ciphertext_length));
     324                 :            : 
     325         [ #  # ]:          0 :     POSIX_GUARD(s2n_kem_send_ciphertext(&(conn->handshake.io), &(conn->kex_params.kem_params)));
     326                 :            : 
     327                 :          0 :     return 0;
     328                 :          0 : }
     329                 :            : 
     330                 :            : int s2n_hybrid_client_key_send(struct s2n_connection *conn, struct s2n_blob *combined_shared_key)
     331                 :          0 : {
     332                 :          0 :     return s2n_hybrid_client_action(conn, combined_shared_key, &s2n_kex_client_key_send, &conn->handshake.io.write_cursor,
     333                 :          0 :             s2n_stuffer_raw_write);
     334                 :          0 : }
     335                 :            : 
     336                 :            : int s2n_client_key_send(struct s2n_connection *conn)
     337                 :       2248 : {
     338 [ -  + ][ #  # ]:       2248 :     POSIX_ENSURE_REF(conn);
     339 [ #  # ][ -  + ]:       2248 :     POSIX_ENSURE_REF(conn->secure);
     340 [ -  + ][ #  # ]:       2248 :     POSIX_ENSURE_REF(conn->secure->cipher_suite);
     341                 :            : 
     342                 :       2248 :     const struct s2n_kex *key_exchange = conn->secure->cipher_suite->key_exchange_alg;
     343                 :       2248 :     DEFER_CLEANUP(struct s2n_blob shared_key = { 0 }, s2n_free_or_wipe);
     344                 :            : 
     345         [ -  + ]:       2248 :     POSIX_GUARD_RESULT(s2n_kex_client_key_send(key_exchange, conn, &shared_key));
     346                 :            : 
     347         [ -  + ]:       2248 :     POSIX_GUARD(s2n_calculate_keys(conn, &shared_key));
     348                 :       2248 :     return 0;
     349                 :       2248 : }

Generated by: LCOV version 1.14