LCOV - code coverage report
Current view: top level - tls - s2n_handshake.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 201 210 95.7 %
Date: 2025-08-15 07:28:39 Functions: 18 18 100.0 %
Branches: 123 208 59.1 %

           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 <stdint.h>
      17                 :            : 
      18                 :            : #include "error/s2n_errno.h"
      19                 :            : #include "stuffer/s2n_stuffer.h"
      20                 :            : #include "tls/s2n_cipher_suites.h"
      21                 :            : #include "tls/s2n_connection.h"
      22                 :            : #include "tls/s2n_record.h"
      23                 :            : #include "tls/s2n_tls.h"
      24                 :            : #include "utils/s2n_map.h"
      25                 :            : #include "utils/s2n_safety.h"
      26                 :            : 
      27                 :            : int s2n_handshake_write_header(struct s2n_stuffer *out, uint8_t message_type)
      28                 :      42192 : {
      29 [ -  + ][ #  # ]:      42192 :     S2N_ERROR_IF(s2n_stuffer_data_available(out), S2N_ERR_HANDSHAKE_STATE);
      30                 :            : 
      31                 :            :     /* Write the message header */
      32         [ -  + ]:      42192 :     POSIX_GUARD(s2n_stuffer_write_uint8(out, message_type));
      33                 :            : 
      34                 :            :     /* Leave the length blank for now */
      35                 :      42192 :     uint16_t length = 0;
      36         [ -  + ]:      42192 :     POSIX_GUARD(s2n_stuffer_write_uint24(out, length));
      37                 :            : 
      38                 :      42192 :     return S2N_SUCCESS;
      39                 :      42192 : }
      40                 :            : 
      41                 :            : int s2n_handshake_finish_header(struct s2n_stuffer *out)
      42                 :      45415 : {
      43                 :      45415 :     uint32_t length = s2n_stuffer_data_available(out);
      44 [ -  + ][ #  # ]:      45415 :     S2N_ERROR_IF(length < TLS_HANDSHAKE_HEADER_LENGTH, S2N_ERR_SIZE_MISMATCH);
      45                 :            : 
      46                 :      45415 :     uint32_t payload = length - TLS_HANDSHAKE_HEADER_LENGTH;
      47                 :            : 
      48                 :            :     /* Write the message header */
      49         [ -  + ]:      45415 :     POSIX_GUARD(s2n_stuffer_rewrite(out));
      50         [ -  + ]:      45415 :     POSIX_GUARD(s2n_stuffer_skip_write(out, 1));
      51         [ +  + ]:      45415 :     POSIX_GUARD(s2n_stuffer_write_uint24(out, payload));
      52         [ -  + ]:      45414 :     POSIX_GUARD(s2n_stuffer_skip_write(out, payload));
      53                 :            : 
      54                 :      45414 :     return S2N_SUCCESS;
      55                 :      45414 : }
      56                 :            : 
      57                 :            : S2N_RESULT s2n_handshake_parse_header(struct s2n_stuffer *io, uint8_t *message_type, uint32_t *length)
      58                 :      74187 : {
      59 [ -  + ][ #  # ]:      74187 :     RESULT_ENSURE(s2n_stuffer_data_available(io) >= TLS_HANDSHAKE_HEADER_LENGTH, S2N_ERR_SIZE_MISMATCH);
      60                 :            : 
      61                 :            :     /* read the message header */
      62         [ -  + ]:      74187 :     RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(io, message_type));
      63         [ -  + ]:      74187 :     RESULT_GUARD_POSIX(s2n_stuffer_read_uint24(io, length));
      64                 :            : 
      65                 :      74187 :     return S2N_RESULT_OK;
      66                 :      74187 : }
      67                 :            : 
      68                 :            : static int s2n_handshake_get_hash_state_ptr(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, struct s2n_hash_state **hash_state)
      69                 :      47876 : {
      70 [ -  + ][ #  # ]:      47876 :     POSIX_ENSURE_REF(conn);
      71 [ #  # ][ -  + ]:      47876 :     POSIX_ENSURE_REF(conn->handshake.hashes);
      72                 :            : 
      73                 :      47876 :     switch (hash_alg) {
      74         [ +  + ]:        537 :         case S2N_HASH_MD5:
      75                 :        537 :             *hash_state = &conn->handshake.hashes->md5;
      76                 :        537 :             break;
      77         [ +  + ]:        537 :         case S2N_HASH_SHA1:
      78                 :        537 :             *hash_state = &conn->handshake.hashes->sha1;
      79                 :        537 :             break;
      80         [ -  + ]:          0 :         case S2N_HASH_SHA224:
      81                 :          0 :             *hash_state = &conn->handshake.hashes->sha224;
      82                 :          0 :             break;
      83         [ +  + ]:      45572 :         case S2N_HASH_SHA256:
      84                 :      45572 :             *hash_state = &conn->handshake.hashes->sha256;
      85                 :      45572 :             break;
      86         [ +  + ]:       1229 :         case S2N_HASH_SHA384:
      87                 :       1229 :             *hash_state = &conn->handshake.hashes->sha384;
      88                 :       1229 :             break;
      89         [ -  + ]:          0 :         case S2N_HASH_SHA512:
      90                 :          0 :             *hash_state = &conn->handshake.hashes->sha512;
      91                 :          0 :             break;
      92         [ +  + ]:          1 :         case S2N_HASH_MD5_SHA1:
      93                 :          1 :             *hash_state = &conn->handshake.hashes->md5_sha1;
      94                 :          1 :             break;
      95         [ -  + ]:          0 :         default:
      96         [ #  # ]:          0 :             POSIX_BAIL(S2N_ERR_HASH_INVALID_ALGORITHM);
      97                 :          0 :             break;
      98                 :      47876 :     }
      99                 :            : 
     100                 :      47876 :     return S2N_SUCCESS;
     101                 :      47876 : }
     102                 :            : 
     103                 :            : S2N_RESULT s2n_handshake_reset_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg)
     104                 :       1300 : {
     105                 :       1300 :     struct s2n_hash_state *hash_state = NULL;
     106         [ -  + ]:       1300 :     RESULT_GUARD_POSIX(s2n_handshake_get_hash_state_ptr(conn, hash_alg, &hash_state));
     107         [ -  + ]:       1300 :     RESULT_GUARD_POSIX(s2n_hash_reset(hash_state));
     108                 :       1300 :     return S2N_RESULT_OK;
     109                 :       1300 : }
     110                 :            : 
     111                 :            : S2N_RESULT s2n_handshake_copy_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, struct s2n_hash_state *copy)
     112                 :      46576 : {
     113                 :      46576 :     struct s2n_hash_state *hash_state = NULL;
     114         [ -  + ]:      46576 :     RESULT_GUARD_POSIX(s2n_handshake_get_hash_state_ptr(conn, hash_alg, &hash_state));
     115         [ -  + ]:      46576 :     RESULT_GUARD_POSIX(s2n_hash_copy(copy, hash_state));
     116                 :      46576 :     return S2N_RESULT_OK;
     117                 :      46576 : }
     118                 :            : 
     119                 :            : int s2n_handshake_require_all_hashes(struct s2n_handshake *handshake)
     120                 :    3427259 : {
     121                 :    3427259 :     memset(handshake->required_hash_algs, 1, sizeof(handshake->required_hash_algs));
     122                 :    3427259 :     return S2N_SUCCESS;
     123                 :    3427259 : }
     124                 :            : 
     125                 :            : static int s2n_handshake_require_hash(struct s2n_handshake *handshake, s2n_hash_algorithm hash_alg)
     126                 :       7572 : {
     127                 :       7572 :     handshake->required_hash_algs[hash_alg] = 1;
     128                 :       7572 :     return S2N_SUCCESS;
     129                 :       7572 : }
     130                 :            : 
     131                 :            : uint8_t s2n_handshake_is_hash_required(struct s2n_handshake *handshake, s2n_hash_algorithm hash_alg)
     132                 :     627013 : {
     133                 :     627013 :     return handshake->required_hash_algs[hash_alg];
     134                 :     627013 : }
     135                 :            : 
     136                 :            : /* Update the required handshake hash algs depending on current handshake session state.
     137                 :            :  * This function must called at the end of a handshake message handler. Additionally it must be called after the
     138                 :            :  * ClientHello or ServerHello is processed in client and server mode respectively. The relevant handshake parameters
     139                 :            :  * are not available until those messages are processed.
     140                 :            :  */
     141                 :            : int s2n_conn_update_required_handshake_hashes(struct s2n_connection *conn)
     142                 :      13935 : {
     143 [ -  + ][ #  # ]:      13935 :     POSIX_ENSURE_REF(conn);
     144 [ -  + ][ #  # ]:      13935 :     POSIX_ENSURE_REF(conn->secure);
     145                 :            : 
     146                 :            :     /* Clear all of the required hashes */
     147                 :      13935 :     memset(conn->handshake.required_hash_algs, 0, sizeof(conn->handshake.required_hash_algs));
     148                 :            : 
     149                 :      13935 :     message_type_t handshake_message = s2n_conn_get_current_message_type(conn);
     150         [ +  + ]:      13935 :     const uint8_t client_cert_verify_done = (handshake_message >= CLIENT_CERT_VERIFY) ? 1 : 0;
     151                 :      13935 :     s2n_cert_auth_type client_cert_auth_type;
     152         [ -  + ]:      13935 :     POSIX_GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
     153                 :            : 
     154                 :            :     /* If client authentication is possible, all hashes are needed until we're past CLIENT_CERT_VERIFY. */
     155 [ +  + ][ +  + ]:      13935 :     if ((client_cert_auth_type != S2N_CERT_AUTH_NONE) && !client_cert_verify_done) {
     156         [ -  + ]:       6673 :         POSIX_GUARD(s2n_handshake_require_all_hashes(&conn->handshake));
     157                 :       6673 :         return S2N_SUCCESS;
     158                 :       6673 :     }
     159                 :            : 
     160                 :            :     /* We don't need all of the hashes. Set the hash alg(s) required for the PRF */
     161         [ -  + ]:       7262 :     switch (conn->actual_protocol_version) {
     162         [ +  + ]:        110 :         case S2N_SSLv3:
     163         [ +  + ]:        210 :         case S2N_TLS10:
     164         [ +  + ]:        310 :         case S2N_TLS11:
     165         [ -  + ]:        310 :             POSIX_GUARD(s2n_handshake_require_hash(&conn->handshake, S2N_HASH_MD5));
     166         [ -  + ]:        310 :             POSIX_GUARD(s2n_handshake_require_hash(&conn->handshake, S2N_HASH_SHA1));
     167                 :        310 :             break;
     168         [ +  + ]:       2115 :         case S2N_TLS12:
     169                 :            :             /* fall through */
     170         [ +  + ]:       6952 :         case S2N_TLS13: {
     171                 :            :             /* For TLS 1.2 and TLS 1.3, the cipher suite defines the PRF hash alg */
     172                 :       6952 :             s2n_hmac_algorithm prf_alg = conn->secure->cipher_suite->prf_alg;
     173                 :       6952 :             s2n_hash_algorithm hash_alg;
     174         [ -  + ]:       6952 :             POSIX_GUARD(s2n_hmac_hash_alg(prf_alg, &hash_alg));
     175         [ -  + ]:       6952 :             POSIX_GUARD(s2n_handshake_require_hash(&conn->handshake, hash_alg));
     176                 :       6952 :             break;
     177                 :       6952 :         }
     178                 :       7262 :     }
     179                 :            : 
     180                 :       7262 :     return S2N_SUCCESS;
     181                 :       7262 : }
     182                 :            : 
     183                 :            : /*
     184                 :            :  * Take a hostname and return a single "simple" wildcard domain name that matches it.
     185                 :            :  * The output wildcard representation is meant to be compared directly against a wildcard domain in a certificate.
     186                 :            :  * We take a restrictive definition of wildcard here to achieve a single unique wildcard representation
     187                 :            :  * given any input hostname.
     188                 :            :  * No embedded or trailing wildcards are supported. Additionally, we only support one level of wildcard matching.
     189                 :            :  * Thus the output should be a single wildcard character in the first(left-most) DNS label.
     190                 :            :  *
     191                 :            :  * Example:
     192                 :            :  * - my.domain.name -> *.domain.name
     193                 :            :  *
     194                 :            :  * Not supported:
     195                 :            :  * - my.domain.name -> m*.domain.name
     196                 :            :  * - my.domain.name -> my.*.name
     197                 :            :  * etc.
     198                 :            :  *
     199                 :            :  * The motivation for using a constrained definition of wildcard:
     200                 :            :  * - Support for issuing non-simple wildcard certificates is insignificant.
     201                 :            :  * - Certificate selection can be implemented with a constant number of lookups(two).
     202                 :            :  */
     203                 :            : int s2n_create_wildcard_hostname(struct s2n_stuffer *hostname_stuffer, struct s2n_stuffer *output)
     204                 :         67 : {
     205                 :            :     /* Find the end of the first label */
     206         [ -  + ]:         67 :     POSIX_GUARD(s2n_stuffer_skip_to_char(hostname_stuffer, '.'));
     207                 :            : 
     208                 :            :     /* No first label found */
     209         [ +  + ]:         67 :     if (s2n_stuffer_data_available(hostname_stuffer) == 0) {
     210                 :         21 :         return S2N_SUCCESS;
     211                 :         21 :     }
     212                 :            : 
     213                 :            :     /* Slap a single wildcard character to be the first label in output */
     214         [ -  + ]:         46 :     POSIX_GUARD(s2n_stuffer_write_uint8(output, '*'));
     215                 :            : 
     216                 :            :     /* Simply copy the rest of the input to the output. */
     217         [ -  + ]:         46 :     POSIX_GUARD(s2n_stuffer_copy(hostname_stuffer, output, s2n_stuffer_data_available(hostname_stuffer)));
     218                 :            : 
     219                 :         46 :     return S2N_SUCCESS;
     220                 :         46 : }
     221                 :            : 
     222                 :            : static int s2n_find_cert_matches(struct s2n_map *domain_name_to_cert_map,
     223                 :            :         struct s2n_blob *dns_name,
     224                 :            :         struct s2n_cert_chain_and_key *matches[S2N_CERT_TYPE_COUNT],
     225                 :            :         uint8_t *match_exists)
     226                 :        144 : {
     227                 :        144 :     struct s2n_blob map_value = { 0 };
     228                 :        144 :     bool key_found = false;
     229         [ -  + ]:        144 :     POSIX_GUARD_RESULT(s2n_map_lookup(domain_name_to_cert_map, dns_name, &map_value, &key_found));
     230         [ +  + ]:        144 :     if (key_found) {
     231                 :         46 :         struct certs_by_type *value = (void *) map_value.data;
     232         [ +  + ]:        230 :         for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) {
     233                 :        184 :             matches[i] = value->certs[i];
     234                 :        184 :         }
     235                 :         46 :         *match_exists = 1;
     236                 :         46 :     }
     237                 :            : 
     238                 :        144 :     return S2N_SUCCESS;
     239                 :        144 : }
     240                 :            : 
     241                 :            : /* Find certificates that match the ServerName TLS extension sent by the client.
     242                 :            :  * For a given ServerName there can be multiple matching certificates based on the
     243                 :            :  * type of key in the certificate.
     244                 :            :  *
     245                 :            :  * A match is determined using s2n_map lookup by DNS name.
     246                 :            :  * Wildcards that have a single * in the left most label are supported.
     247                 :            :  */
     248                 :            : int s2n_conn_find_name_matching_certs(struct s2n_connection *conn)
     249                 :       7367 : {
     250         [ +  + ]:       7367 :     if (!s2n_server_received_server_name(conn)) {
     251                 :       7263 :         return S2N_SUCCESS;
     252                 :       7263 :     }
     253                 :        104 :     const char *name = conn->server_name;
     254                 :        104 :     struct s2n_blob hostname_blob = { 0 };
     255         [ -  + ]:        104 :     POSIX_GUARD(s2n_blob_init(&hostname_blob, (uint8_t *) (uintptr_t) name, strlen(name)));
     256 [ -  + ][ #  # ]:        104 :     POSIX_ENSURE_LTE(hostname_blob.size, S2N_MAX_SERVER_NAME);
     257                 :        104 :     char normalized_hostname[S2N_MAX_SERVER_NAME + 1] = { 0 };
     258 [ -  + ][ #  # ]:        104 :     POSIX_CHECKED_MEMCPY(normalized_hostname, hostname_blob.data, hostname_blob.size);
                 [ +  - ]
     259                 :        104 :     struct s2n_blob normalized_name = { 0 };
     260         [ -  + ]:        104 :     POSIX_GUARD(s2n_blob_init(&normalized_name, (uint8_t *) normalized_hostname, hostname_blob.size));
     261                 :            : 
     262         [ -  + ]:        104 :     POSIX_GUARD(s2n_blob_char_to_lower(&normalized_name));
     263                 :        104 :     struct s2n_stuffer normalized_hostname_stuffer = { 0 };
     264         [ -  + ]:        104 :     POSIX_GUARD(s2n_stuffer_init(&normalized_hostname_stuffer, &normalized_name));
     265         [ -  + ]:        104 :     POSIX_GUARD(s2n_stuffer_skip_write(&normalized_hostname_stuffer, normalized_name.size));
     266                 :            : 
     267                 :            :     /* Find the exact matches for the ServerName */
     268         [ -  + ]:        104 :     POSIX_GUARD(s2n_find_cert_matches(conn->config->domain_name_to_cert_map,
     269                 :        104 :             &normalized_name,
     270                 :        104 :             conn->handshake_params.exact_sni_matches,
     271                 :        104 :             &(conn->handshake_params.exact_sni_match_exists)));
     272                 :            : 
     273         [ +  + ]:        104 :     if (!conn->handshake_params.exact_sni_match_exists) {
     274                 :            :         /* We have not yet found an exact domain match. Try to find wildcard matches. */
     275                 :         59 :         char wildcard_hostname[S2N_MAX_SERVER_NAME + 1] = { 0 };
     276                 :         59 :         struct s2n_blob wildcard_blob = { 0 };
     277         [ -  + ]:         59 :         POSIX_GUARD(s2n_blob_init(&wildcard_blob, (uint8_t *) wildcard_hostname, sizeof(wildcard_hostname)));
     278                 :         59 :         struct s2n_stuffer wildcard_stuffer = { 0 };
     279         [ -  + ]:         59 :         POSIX_GUARD(s2n_stuffer_init(&wildcard_stuffer, &wildcard_blob));
     280         [ -  + ]:         59 :         POSIX_GUARD(s2n_create_wildcard_hostname(&normalized_hostname_stuffer, &wildcard_stuffer));
     281                 :         59 :         const uint32_t wildcard_len = s2n_stuffer_data_available(&wildcard_stuffer);
     282                 :            : 
     283                 :            :         /* Couldn't create a valid wildcard from the input */
     284         [ +  + ]:         59 :         if (wildcard_len == 0) {
     285                 :         19 :             return S2N_SUCCESS;
     286                 :         19 :         }
     287                 :            : 
     288                 :            :         /* The client's SNI is wildcardified, do an exact match against the set of server certs. */
     289                 :         40 :         wildcard_blob.size = wildcard_len;
     290         [ -  + ]:         40 :         POSIX_GUARD(s2n_find_cert_matches(conn->config->domain_name_to_cert_map,
     291                 :         40 :                 &wildcard_blob,
     292                 :         40 :                 conn->handshake_params.wc_sni_matches,
     293                 :         40 :                 &(conn->handshake_params.wc_sni_match_exists)));
     294                 :         40 :     }
     295                 :            : 
     296                 :            :     /* If we found a suitable cert, we should send back the ServerName extension.
     297                 :            :      * Note that this may have already been set by the client hello callback, so we won't override its value
     298                 :            :      */
     299         [ +  + ]:         85 :     conn->server_name_used = conn->server_name_used
     300         [ +  + ]:         85 :             || conn->handshake_params.exact_sni_match_exists
     301         [ +  + ]:         85 :             || conn->handshake_params.wc_sni_match_exists;
     302                 :            : 
     303                 :         85 :     return S2N_SUCCESS;
     304                 :        104 : }
     305                 :            : 
     306                 :            : /* Find the optimal certificate of a specific type.
     307                 :            :  * The priority of set of certificates to choose from:
     308                 :            :  * 1. Certificates that match the client's ServerName extension.
     309                 :            :  * 2. Default certificates
     310                 :            :  */
     311                 :            : struct s2n_cert_chain_and_key *s2n_get_compatible_cert_chain_and_key(struct s2n_connection *conn, const s2n_pkey_type cert_type)
     312                 :      42999 : {
     313         [ +  + ]:      42999 :     if (conn->handshake_params.exact_sni_match_exists) {
     314                 :            :         /* This may return NULL if there was an SNI match, but not a match the cipher_suite's authentication type. */
     315                 :        508 :         return conn->handshake_params.exact_sni_matches[cert_type];
     316                 :        508 :     }
     317         [ +  + ]:      42491 :     if (conn->handshake_params.wc_sni_match_exists) {
     318                 :         13 :         return conn->handshake_params.wc_sni_matches[cert_type];
     319                 :      42478 :     } else {
     320                 :            :         /* We don't have any name matches. Use the default certificate that works with the key type. */
     321                 :      42478 :         return conn->config->default_certs_by_type.certs[cert_type];
     322                 :      42478 :     }
     323                 :      42491 : }
     324                 :            : 
     325                 :            : /* This method will work when testing S2N, and for the EndOfEarlyData message.
     326                 :            :  *
     327                 :            :  * However, it will NOT work for arbitrary message types when potentially receiving records
     328                 :            :  * that contain multiple messages, like when talking to a non-S2N TLS implementation. If the "end_message"
     329                 :            :  * is not the first message in a multi-message record, negotiation will not stop.
     330                 :            :  * (This is not an issue for EndOfEarlyData because encryption and message order requirements force
     331                 :            :  * EndOfEarlyData to always be the first and only handshake message in its handshake record)
     332                 :            :  */
     333                 :            : S2N_RESULT s2n_negotiate_until_message(struct s2n_connection *conn, s2n_blocked_status *blocked, message_type_t end_message)
     334                 :       7084 : {
     335 [ +  - ][ +  + ]:       7084 :     RESULT_ENSURE_REF(conn);
     336                 :       7083 :     conn->handshake.end_of_messages = end_message;
     337                 :       7083 :     int r = s2n_negotiate(conn, blocked);
     338                 :       7083 :     conn->handshake.end_of_messages = APPLICATION_DATA;
     339         [ +  + ]:       7083 :     RESULT_GUARD_POSIX(r);
     340                 :       5336 :     return S2N_RESULT_OK;
     341                 :       7083 : }
     342                 :            : 
     343                 :            : S2N_RESULT s2n_handshake_validate(const struct s2n_handshake *s2n_handshake)
     344                 :      46832 : {
     345 [ -  + ][ #  # ]:      46832 :     RESULT_ENSURE_REF(s2n_handshake);
     346 [ #  # ][ -  + ]:      46832 :     RESULT_DEBUG_ENSURE(s2n_handshake->handshake_type < 256, S2N_ERR_SAFETY);
     347 [ #  # ][ -  + ]:      46832 :     RESULT_DEBUG_ENSURE(s2n_handshake->message_number >= 0 && s2n_handshake->message_number < 32, S2N_ERR_SAFETY);
         [ +  - ][ +  - ]
     348                 :      46832 :     return S2N_RESULT_OK;
     349                 :      46832 : }
     350                 :            : 
     351                 :            : S2N_RESULT s2n_handshake_set_finished_len(struct s2n_connection *conn, uint8_t len)
     352                 :      23362 : {
     353 [ +  - ][ +  + ]:      23362 :     RESULT_ENSURE_REF(conn);
     354 [ +  + ][ +  - ]:      23361 :     RESULT_ENSURE_GT(len, 0);
     355 [ +  + ][ +  - ]:      23360 :     RESULT_ENSURE_LTE(len, sizeof(conn->handshake.server_finished));
     356 [ -  + ][ #  # ]:      23358 :     RESULT_ENSURE_LTE(len, sizeof(conn->handshake.client_finished));
     357                 :            : 
     358                 :            :     /*
     359                 :            :      * We maintain a version of the "finished" / "verify_data" field
     360                 :            :      * for both the client and server, so this method will be called
     361                 :            :      * once for the client version and once for the server version.
     362                 :            :      *
     363                 :            :      * The lengths of both versions must match, or something has
     364                 :            :      * gone wrong in our implementation.
     365                 :            :      */
     366                 :      23358 :     uint8_t *finished_length = &conn->handshake.finished_len;
     367         [ +  + ]:      23358 :     if (*finished_length == 0) {
     368                 :      11718 :         *finished_length = len;
     369                 :      11718 :     }
     370 [ +  + ][ +  - ]:      23358 :     RESULT_ENSURE_EQ(*finished_length, len);
     371                 :            : 
     372                 :      23355 :     return S2N_RESULT_OK;
     373                 :      23358 : }
     374                 :            : 
     375                 :            : bool s2n_handshake_is_renegotiation(struct s2n_connection *conn)
     376                 :      33752 : {
     377 [ +  - ][ +  + ]:      33752 :     return conn && conn->handshake.renegotiation;
     378                 :      33752 : }

Generated by: LCOV version 1.14