LCOV - code coverage report
Current view: top level - tls - s2n_tls13_handshake.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 126 126 100.0 %
Date: 2025-08-15 07:28:39 Functions: 8 8 100.0 %
Branches: 97 200 48.5 %

           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_tls13_handshake.h"
      17                 :            : 
      18                 :            : #include "tls/s2n_cipher_suites.h"
      19                 :            : #include "tls/s2n_key_log.h"
      20                 :            : #include "tls/s2n_security_policies.h"
      21                 :            : 
      22                 :            : static int s2n_zero_sequence_number(struct s2n_connection *conn, s2n_mode mode)
      23                 :       1800 : {
      24 [ -  + ][ #  # ]:       1800 :     POSIX_ENSURE_REF(conn);
      25 [ #  # ][ -  + ]:       1800 :     POSIX_ENSURE_REF(conn->secure);
      26                 :       1800 :     struct s2n_blob sequence_number = { 0 };
      27         [ -  + ]:       1800 :     POSIX_GUARD_RESULT(s2n_connection_get_sequence_number(conn, mode, &sequence_number));
      28         [ -  + ]:       1800 :     POSIX_GUARD(s2n_blob_zero(&sequence_number));
      29                 :       1800 :     return S2N_SUCCESS;
      30                 :       1800 : }
      31                 :            : 
      32                 :            : int s2n_tls13_mac_verify(struct s2n_tls13_keys *keys, struct s2n_blob *finished_verify, struct s2n_blob *wire_verify)
      33                 :       6490 : {
      34 [ #  # ][ -  + ]:       6490 :     POSIX_ENSURE_REF(wire_verify->data);
      35 [ +  - ][ +  + ]:       6490 :     POSIX_ENSURE_EQ(wire_verify->size, keys->size);
      36                 :            : 
      37 [ +  + ][ +  - ]:       6476 :     S2N_ERROR_IF(!s2n_constant_time_equals(finished_verify->data, wire_verify->data, keys->size), S2N_ERR_BAD_MESSAGE);
      38                 :            : 
      39                 :       6366 :     return S2N_SUCCESS;
      40                 :       6476 : }
      41                 :            : 
      42                 :            : int s2n_tls13_keys_from_conn(struct s2n_tls13_keys *keys, struct s2n_connection *conn)
      43                 :      20597 : {
      44         [ -  + ]:      20597 :     POSIX_GUARD(s2n_tls13_keys_init(keys, conn->secure->cipher_suite->prf_alg));
      45                 :      20597 :     return S2N_SUCCESS;
      46                 :      20597 : }
      47                 :            : 
      48                 :            : int s2n_tls13_compute_ecc_shared_secret(struct s2n_connection *conn, struct s2n_blob *shared_secret)
      49                 :       8849 : {
      50 [ #  # ][ -  + ]:       8849 :     POSIX_ENSURE_REF(conn);
      51                 :            : 
      52                 :       8849 :     const struct s2n_ecc_preferences *ecc_preferences = NULL;
      53         [ -  + ]:       8849 :     POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_preferences));
      54 [ -  + ][ #  # ]:       8849 :     POSIX_ENSURE_REF(ecc_preferences);
      55                 :            : 
      56                 :       8849 :     struct s2n_ecc_evp_params *server_key = &conn->kex_params.server_ecc_evp_params;
      57 [ #  # ][ -  + ]:       8849 :     POSIX_ENSURE_REF(server_key);
      58 [ +  + ][ +  - ]:       8849 :     POSIX_ENSURE_REF(server_key->negotiated_curve);
      59                 :            : 
      60                 :       8848 :     struct s2n_ecc_evp_params *client_key = &conn->kex_params.client_ecc_evp_params;
      61 [ #  # ][ -  + ]:       8848 :     POSIX_ENSURE_REF(client_key);
      62 [ #  # ][ -  + ]:       8848 :     POSIX_ENSURE_REF(client_key->negotiated_curve);
      63                 :            : 
      64 [ -  + ][ #  # ]:       8848 :     POSIX_ENSURE_EQ(server_key->negotiated_curve, client_key->negotiated_curve);
      65                 :            : 
      66         [ +  + ]:       8848 :     if (conn->mode == S2N_CLIENT) {
      67         [ +  + ]:       4419 :         POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_from_params(client_key, server_key, shared_secret));
      68                 :       4429 :     } else {
      69         [ -  + ]:       4429 :         POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_from_params(server_key, client_key, shared_secret));
      70                 :       4429 :     }
      71                 :            : 
      72                 :       8847 :     return S2N_SUCCESS;
      73                 :       8848 : }
      74                 :            : 
      75                 :            : /* Computes the ECDHE+PQKEM hybrid shared secret as defined in
      76                 :            :  * https://tools.ietf.org/html/draft-stebila-tls-hybrid-design */
      77                 :            : int s2n_tls13_compute_pq_hybrid_shared_secret(struct s2n_connection *conn, struct s2n_blob *shared_secret)
      78                 :         80 : {
      79 [ +  + ][ +  - ]:         80 :     POSIX_ENSURE_REF(conn);
      80 [ +  + ][ +  - ]:         76 :     POSIX_ENSURE_REF(shared_secret);
      81                 :            : 
      82                 :            :     /* conn->kex_params.server_ecc_evp_params should be set only during a classic/non-hybrid handshake */
      83 [ +  + ][ +  - ]:         74 :     POSIX_ENSURE_EQ(NULL, conn->kex_params.server_ecc_evp_params.negotiated_curve);
      84 [ +  + ][ +  - ]:         72 :     POSIX_ENSURE_EQ(NULL, conn->kex_params.server_ecc_evp_params.evp_pkey);
      85                 :            : 
      86                 :         70 :     struct s2n_kem_group_params *server_kem_group_params = &conn->kex_params.server_kem_group_params;
      87 [ -  + ][ #  # ]:         70 :     POSIX_ENSURE_REF(server_kem_group_params);
      88                 :         70 :     struct s2n_ecc_evp_params *server_ecc_params = &server_kem_group_params->ecc_params;
      89 [ -  + ][ #  # ]:         70 :     POSIX_ENSURE_REF(server_ecc_params);
      90                 :            : 
      91                 :         70 :     struct s2n_kem_group_params *client_kem_group_params = &conn->kex_params.client_kem_group_params;
      92 [ -  + ][ #  # ]:         70 :     POSIX_ENSURE_REF(client_kem_group_params);
      93                 :         70 :     struct s2n_ecc_evp_params *client_ecc_params = &client_kem_group_params->ecc_params;
      94 [ -  + ][ #  # ]:         70 :     POSIX_ENSURE_REF(client_ecc_params);
      95                 :            : 
      96                 :         70 :     DEFER_CLEANUP(struct s2n_blob ecdhe_shared_secret = { 0 }, s2n_free_or_wipe);
      97                 :            : 
      98                 :            :     /* Compute the ECDHE shared secret, and retrieve the PQ shared secret. */
      99         [ +  + ]:         70 :     if (conn->mode == S2N_CLIENT) {
     100         [ +  + ]:         44 :         POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_from_params(client_ecc_params, server_ecc_params, &ecdhe_shared_secret));
     101                 :         44 :     } else {
     102         [ +  + ]:         26 :         POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_from_params(server_ecc_params, client_ecc_params, &ecdhe_shared_secret));
     103                 :         26 :     }
     104                 :            : 
     105                 :         60 :     struct s2n_blob *pq_shared_secret = &client_kem_group_params->kem_params.shared_secret;
     106 [ #  # ][ -  + ]:         60 :     POSIX_ENSURE_REF(pq_shared_secret);
     107 [ +  - ][ +  + ]:         60 :     POSIX_ENSURE_REF(pq_shared_secret->data);
     108                 :            : 
     109                 :         58 :     const struct s2n_kem_group *negotiated_kem_group = conn->kex_params.server_kem_group_params.kem_group;
     110 [ +  + ][ +  - ]:         58 :     POSIX_ENSURE_REF(negotiated_kem_group);
     111 [ -  + ][ #  # ]:         56 :     POSIX_ENSURE_REF(negotiated_kem_group->kem);
     112                 :            : 
     113 [ #  # ][ -  + ]:         56 :     POSIX_ENSURE_EQ(pq_shared_secret->size, negotiated_kem_group->kem->shared_secret_key_length);
     114                 :            : 
     115                 :            :     /* Construct the concatenated/hybrid shared secret */
     116                 :         56 :     uint32_t hybrid_shared_secret_size = ecdhe_shared_secret.size + negotiated_kem_group->kem->shared_secret_key_length;
     117         [ -  + ]:         56 :     POSIX_GUARD(s2n_alloc(shared_secret, hybrid_shared_secret_size));
     118                 :         56 :     struct s2n_stuffer stuffer_combiner = { 0 };
     119         [ -  + ]:         56 :     POSIX_GUARD(s2n_stuffer_init(&stuffer_combiner, shared_secret));
     120                 :            : 
     121         [ +  + ]:         56 :     if (negotiated_kem_group->send_kem_first) {
     122         [ -  + ]:          6 :         POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, pq_shared_secret));
     123         [ -  + ]:          6 :         POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, &ecdhe_shared_secret));
     124                 :         50 :     } else {
     125         [ -  + ]:         50 :         POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, &ecdhe_shared_secret));
     126         [ -  + ]:         50 :         POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, pq_shared_secret));
     127                 :         50 :     }
     128                 :            : 
     129                 :         56 :     return S2N_SUCCESS;
     130                 :         56 : }
     131                 :            : 
     132                 :            : int s2n_tls13_pq_hybrid_supported(struct s2n_connection *conn)
     133                 :       8955 : {
     134                 :       8955 :     return conn->kex_params.server_kem_group_params.kem_group != NULL;
     135                 :       8955 : }
     136                 :            : 
     137                 :            : int s2n_tls13_compute_shared_secret(struct s2n_connection *conn, struct s2n_blob *shared_secret)
     138                 :       8903 : {
     139 [ -  + ][ #  # ]:       8903 :     POSIX_ENSURE_REF(conn);
     140                 :            : 
     141         [ +  + ]:       8903 :     if (s2n_tls13_pq_hybrid_supported(conn)) {
     142         [ -  + ]:         54 :         POSIX_GUARD(s2n_tls13_compute_pq_hybrid_shared_secret(conn, shared_secret));
     143                 :       8849 :     } else {
     144         [ +  + ]:       8849 :         POSIX_GUARD(s2n_tls13_compute_ecc_shared_secret(conn, shared_secret));
     145                 :       8849 :     }
     146                 :            : 
     147         [ -  + ]:       8901 :     POSIX_GUARD_RESULT(s2n_connection_wipe_all_keyshares(conn));
     148                 :            : 
     149                 :            :     /* It would make more sense to wipe the PSK secrets in s2n_tls13_handle_early_secret,
     150                 :            :      * but at that point we don't know whether or not the server will request a HRR request
     151                 :            :      * and we'll have to use the secrets again.
     152                 :            :      *
     153                 :            :      * Instead, wipe them here when we wipe all the other connection secrets. */
     154         [ -  + ]:       8901 :     POSIX_GUARD_RESULT(s2n_psk_parameters_wipe_secrets(&conn->psk_params));
     155                 :            : 
     156                 :       8901 :     return S2N_SUCCESS;
     157                 :       8901 : }
     158                 :            : 
     159                 :            : int s2n_update_application_traffic_keys(struct s2n_connection *conn, s2n_mode mode, keyupdate_status status)
     160                 :       1801 : {
     161 [ -  + ][ #  # ]:       1801 :     POSIX_ENSURE_REF(conn);
     162 [ #  # ][ -  + ]:       1801 :     POSIX_ENSURE_REF(conn->secure);
     163 [ -  + ][ #  # ]:       1801 :     POSIX_ENSURE_GTE(conn->actual_protocol_version, S2N_TLS13);
     164                 :            : 
     165                 :            :     /* get tls13 key context */
     166         [ -  + ]:       1801 :     s2n_tls13_connection_keys(keys, conn);
     167                 :            : 
     168                 :       1801 :     struct s2n_session_key *old_key = NULL;
     169                 :       1801 :     struct s2n_blob old_app_secret = { 0 };
     170                 :       1801 :     struct s2n_blob app_iv = { 0 };
     171                 :            : 
     172         [ +  + ]:       1801 :     if (mode == S2N_CLIENT) {
     173                 :        903 :         old_key = &conn->secure->client_key;
     174         [ -  + ]:        903 :         POSIX_GUARD(s2n_blob_init(&old_app_secret, conn->secrets.version.tls13.client_app_secret, keys.size));
     175         [ -  + ]:        903 :         POSIX_GUARD(s2n_blob_init(&app_iv, conn->secure->client_implicit_iv, S2N_TLS13_FIXED_IV_LEN));
     176                 :        903 :     } else {
     177                 :        898 :         old_key = &conn->secure->server_key;
     178         [ -  + ]:        898 :         POSIX_GUARD(s2n_blob_init(&old_app_secret, conn->secrets.version.tls13.server_app_secret, keys.size));
     179         [ -  + ]:        898 :         POSIX_GUARD(s2n_blob_init(&app_iv, conn->secure->server_implicit_iv, S2N_TLS13_FIXED_IV_LEN));
     180                 :        898 :     }
     181                 :            : 
     182                 :            :     /* Produce new application secret */
     183 [ -  + ][ #  # ]:       3602 :     s2n_stack_blob(app_secret_update, keys.size, S2N_TLS13_SECRET_MAX_LEN);
                 [ -  + ]
     184                 :            : 
     185                 :            :     /* Derives next generation of traffic secret */
     186         [ -  + ]:       1801 :     POSIX_GUARD(s2n_tls13_update_application_traffic_secret(&keys, &old_app_secret, &app_secret_update));
     187                 :            : 
     188 [ -  + ][ #  # ]:       3602 :     s2n_tls13_key_blob(app_key, conn->secure->cipher_suite->record_alg->cipher->key_material_size);
                 [ -  + ]
     189                 :            : 
     190                 :            :     /* Derives next generation of traffic key */
     191                 :       1801 :     uint8_t *count = NULL;
     192         [ -  + ]:       1801 :     POSIX_GUARD(s2n_tls13_derive_traffic_keys(&keys, &app_secret_update, &app_key, &app_iv));
     193         [ +  + ]:       1801 :     if (status == RECEIVING) {
     194         [ -  + ]:        899 :         POSIX_GUARD_RESULT(conn->secure->cipher_suite->record_alg->cipher->set_decryption_key(old_key, &app_key));
     195                 :        899 :         count = &conn->recv_key_updated;
     196                 :        902 :     } else {
     197         [ -  + ]:        902 :         POSIX_GUARD_RESULT(conn->secure->cipher_suite->record_alg->cipher->set_encryption_key(old_key, &app_key));
     198                 :        902 :         count = &conn->send_key_updated;
     199                 :        902 :     }
     200                 :            : 
     201                 :            :     /* Increment the count.
     202                 :            :      * Don't treat overflows as errors-- we only do best-effort reporting.
     203                 :            :      */
     204                 :       1801 :     *count = MIN(UINT8_MAX, *count + 1);
     205                 :            : 
     206                 :            :     /* According to https://tools.ietf.org/html/rfc8446#section-5.3:
     207                 :            :      * Each sequence number is set to zero at the beginning of a connection and
     208                 :            :      * whenever the key is changed; the first record transmitted under a particular traffic key
     209                 :            :      * MUST use sequence number 0.
     210                 :            :      */
     211         [ -  + ]:       1801 :     POSIX_GUARD(s2n_zero_sequence_number(conn, mode));
     212                 :            : 
     213                 :            :     /* Save updated secret */
     214                 :       1801 :     struct s2n_stuffer old_secret_stuffer = { 0 };
     215         [ -  + ]:       1801 :     POSIX_GUARD(s2n_stuffer_init(&old_secret_stuffer, &old_app_secret));
     216         [ -  + ]:       1801 :     POSIX_GUARD(s2n_stuffer_write_bytes(&old_secret_stuffer, app_secret_update.data, keys.size));
     217                 :            : 
     218                 :       1801 :     return S2N_SUCCESS;
     219                 :       1801 : }

Generated by: LCOV version 1.14