LCOV - code coverage report
Current view: top level - tls - s2n_client_hello.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 605 613 98.7 %
Date: 2025-11-15 08:28:27 Functions: 38 38 100.0 %
Branches: 475 840 56.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_client_hello.h"
      17                 :            : 
      18                 :            : #include <stdint.h>
      19                 :            : #include <stdlib.h>
      20                 :            : #include <sys/param.h>
      21                 :            : #include <time.h>
      22                 :            : 
      23                 :            : #include "api/unstable/fingerprint.h"
      24                 :            : #include "crypto/s2n_fips.h"
      25                 :            : #include "crypto/s2n_hash.h"
      26                 :            : #include "crypto/s2n_pq.h"
      27                 :            : #include "error/s2n_errno.h"
      28                 :            : #include "stuffer/s2n_stuffer.h"
      29                 :            : #include "tls/extensions/s2n_client_server_name.h"
      30                 :            : #include "tls/extensions/s2n_client_supported_groups.h"
      31                 :            : #include "tls/extensions/s2n_extension_list.h"
      32                 :            : #include "tls/extensions/s2n_server_key_share.h"
      33                 :            : #include "tls/s2n_alerts.h"
      34                 :            : #include "tls/s2n_auth_selection.h"
      35                 :            : #include "tls/s2n_cipher_preferences.h"
      36                 :            : #include "tls/s2n_cipher_suites.h"
      37                 :            : #include "tls/s2n_connection.h"
      38                 :            : #include "tls/s2n_handshake_type.h"
      39                 :            : #include "tls/s2n_security_policies.h"
      40                 :            : #include "tls/s2n_signature_algorithms.h"
      41                 :            : #include "tls/s2n_tls.h"
      42                 :            : #include "utils/s2n_bitmap.h"
      43                 :            : #include "utils/s2n_random.h"
      44                 :            : #include "utils/s2n_safety.h"
      45                 :            : 
      46                 :            : struct s2n_client_hello *s2n_connection_get_client_hello(struct s2n_connection *conn)
      47                 :        175 : {
      48         [ +  + ]:        175 :     if (conn->client_hello.parsed != 1) {
      49                 :          3 :         return NULL;
      50                 :          3 :     }
      51                 :            : 
      52                 :        172 :     return &conn->client_hello;
      53                 :        175 : }
      54                 :            : 
      55                 :            : static uint32_t min_size(struct s2n_blob *blob, uint32_t max_length)
      56                 :         44 : {
      57         [ +  + ]:         44 :     return blob->size < max_length ? blob->size : max_length;
      58                 :         44 : }
      59                 :            : 
      60                 :            : static S2N_RESULT s2n_generate_client_session_id(struct s2n_connection *conn)
      61                 :       7662 : {
      62 [ -  + ][ #  # ]:       7662 :     RESULT_ENSURE_REF(conn);
      63 [ -  + ][ #  # ]:       7662 :     RESULT_ENSURE_REF(conn->config);
      64                 :            : 
      65                 :            :     /* Session id already generated - no-op */
      66         [ +  + ]:       7662 :     if (conn->session_id_len) {
      67                 :        667 :         return S2N_RESULT_OK;
      68                 :        667 :     }
      69                 :            : 
      70                 :            :     /* Only generate the session id if using tickets */
      71                 :       6995 :     bool generate = conn->config->use_tickets;
      72                 :            : 
      73                 :            :     /* TLS1.3 doesn't require session ids. The field is actually renamed to legacy_session_id.
      74                 :            :      * However, we still set a session id if dealing with troublesome middleboxes
      75                 :            :      * (middlebox compatibility mode) or if trying to use a TLS1.2 ticket.
      76                 :            :      */
      77         [ +  + ]:       6995 :     if (conn->client_protocol_version >= S2N_TLS13) {
      78 [ +  + ][ +  + ]:       5136 :         generate = s2n_is_middlebox_compat_enabled(conn) || conn->resume_protocol_version;
      79                 :       5136 :     }
      80                 :            : 
      81                 :            :     /* Session id not needed - no-op */
      82         [ +  + ]:       6995 :     if (!generate) {
      83                 :       2059 :         return S2N_RESULT_OK;
      84                 :       2059 :     }
      85                 :            : 
      86                 :            :     /* QUIC should not allow session ids for any reason.
      87                 :            :      *
      88                 :            :      *= https://www.rfc-editor.org/rfc/rfc9001#section-8.4
      89                 :            :      *# A server SHOULD treat the receipt of a TLS ClientHello with a non-empty
      90                 :            :      *# legacy_session_id field as a connection error of type PROTOCOL_VIOLATION.
      91                 :            :      */
      92 [ +  - ][ +  + ]:       4936 :     RESULT_ENSURE(!conn->quic_enabled, S2N_ERR_UNSUPPORTED_WITH_QUIC);
      93                 :            : 
      94                 :       4935 :     struct s2n_blob session_id = { 0 };
      95         [ -  + ]:       4935 :     RESULT_GUARD_POSIX(s2n_blob_init(&session_id, conn->session_id, S2N_TLS_SESSION_ID_MAX_LEN));
      96         [ -  + ]:       4935 :     RESULT_GUARD(s2n_get_public_random_data(&session_id));
      97                 :       4935 :     conn->session_id_len = S2N_TLS_SESSION_ID_MAX_LEN;
      98                 :       4935 :     return S2N_RESULT_OK;
      99                 :       4935 : }
     100                 :            : 
     101                 :            : ssize_t s2n_client_hello_get_raw_message_length(struct s2n_client_hello *ch)
     102                 :          3 : {
     103 [ +  - ][ +  + ]:          3 :     POSIX_ENSURE_REF(ch);
     104                 :            : 
     105                 :          2 :     return ch->raw_message.size;
     106                 :          3 : }
     107                 :            : 
     108                 :            : ssize_t s2n_client_hello_get_raw_message(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length)
     109                 :          3 : {
     110 [ +  + ][ +  - ]:          3 :     POSIX_ENSURE_REF(ch);
     111 [ -  + ][ #  # ]:          2 :     POSIX_ENSURE_REF(out);
     112                 :            : 
     113                 :          2 :     uint32_t len = min_size(&ch->raw_message, max_length);
     114 [ -  + ][ #  # ]:          2 :     POSIX_CHECKED_MEMCPY(out, ch->raw_message.data, len);
                 [ +  - ]
     115                 :          2 :     return len;
     116                 :          2 : }
     117                 :            : 
     118                 :            : ssize_t s2n_client_hello_get_cipher_suites_length(struct s2n_client_hello *ch)
     119                 :          3 : {
     120 [ +  + ][ +  - ]:          3 :     POSIX_ENSURE_REF(ch);
     121                 :            : 
     122                 :          2 :     return ch->cipher_suites.size;
     123                 :          3 : }
     124                 :            : 
     125                 :            : int s2n_client_hello_cb_done(struct s2n_connection *conn)
     126                 :         28 : {
     127 [ -  + ][ #  # ]:         28 :     POSIX_ENSURE_REF(conn);
     128 [ -  + ][ #  # ]:         28 :     POSIX_ENSURE_REF(conn->config);
     129 [ -  + ][ #  # ]:         28 :     POSIX_ENSURE(conn->config->client_hello_cb_mode == S2N_CLIENT_HELLO_CB_NONBLOCKING, S2N_ERR_INVALID_STATE);
     130 [ -  + ][ #  # ]:         28 :     POSIX_ENSURE(conn->client_hello.callback_invoked == 1, S2N_ERR_ASYNC_NOT_PERFORMED);
     131 [ #  # ][ -  + ]:         28 :     POSIX_ENSURE(conn->client_hello.parsed == 1, S2N_ERR_INVALID_STATE);
     132                 :            : 
     133                 :         28 :     conn->client_hello.callback_async_blocked = 0;
     134                 :         28 :     conn->client_hello.callback_async_done = 1;
     135                 :            : 
     136                 :         28 :     return S2N_SUCCESS;
     137                 :         28 : }
     138                 :            : 
     139                 :            : ssize_t s2n_client_hello_get_cipher_suites(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length)
     140                 :          3 : {
     141 [ +  + ][ +  - ]:          3 :     POSIX_ENSURE_REF(ch);
     142 [ -  + ][ #  # ]:          2 :     POSIX_ENSURE_REF(out);
     143 [ -  + ][ #  # ]:          2 :     POSIX_ENSURE_REF(ch->cipher_suites.data);
     144                 :            : 
     145                 :          2 :     uint32_t len = min_size(&ch->cipher_suites, max_length);
     146                 :            : 
     147 [ -  + ][ #  # ]:          2 :     POSIX_CHECKED_MEMCPY(out, ch->cipher_suites.data, len);
                 [ +  - ]
     148                 :            : 
     149                 :          2 :     return len;
     150                 :          2 : }
     151                 :            : 
     152                 :            : ssize_t s2n_client_hello_get_extensions_length(struct s2n_client_hello *ch)
     153                 :          3 : {
     154 [ +  + ][ +  - ]:          3 :     POSIX_ENSURE_REF(ch);
     155                 :            : 
     156                 :          2 :     return ch->extensions.raw.size;
     157                 :          3 : }
     158                 :            : 
     159                 :            : ssize_t s2n_client_hello_get_extensions(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length)
     160                 :          3 : {
     161 [ +  + ][ +  - ]:          3 :     POSIX_ENSURE_REF(ch);
     162 [ -  + ][ #  # ]:          2 :     POSIX_ENSURE_REF(out);
     163 [ -  + ][ #  # ]:          2 :     POSIX_ENSURE_REF(ch->extensions.raw.data);
     164                 :            : 
     165                 :          2 :     uint32_t len = min_size(&ch->extensions.raw, max_length);
     166                 :            : 
     167 [ -  + ][ #  # ]:          2 :     POSIX_CHECKED_MEMCPY(out, ch->extensions.raw.data, len);
                 [ +  - ]
     168                 :            : 
     169                 :          2 :     return len;
     170                 :          2 : }
     171                 :            : 
     172                 :            : int s2n_client_hello_free_raw_message(struct s2n_client_hello *client_hello)
     173                 :     134387 : {
     174 [ -  + ][ #  # ]:     134387 :     POSIX_ENSURE_REF(client_hello);
     175                 :            : 
     176         [ -  + ]:     134387 :     POSIX_GUARD(s2n_free(&client_hello->raw_message));
     177                 :            : 
     178                 :            :     /* These point to data in the raw_message stuffer,
     179                 :            :        so we don't need to free them */
     180                 :     134387 :     client_hello->cipher_suites.data = NULL;
     181                 :     134387 :     client_hello->extensions.raw.data = NULL;
     182                 :            : 
     183                 :     134387 :     return 0;
     184                 :     134387 : }
     185                 :            : 
     186                 :            : int s2n_client_hello_free(struct s2n_client_hello **ch)
     187                 :        194 : {
     188 [ +  + ][ +  - ]:        194 :     POSIX_ENSURE_REF(ch);
     189         [ +  + ]:        193 :     if (*ch == NULL) {
     190                 :         88 :         return S2N_SUCCESS;
     191                 :         88 :     }
     192                 :            : 
     193 [ +  - ][ +  + ]:        105 :     POSIX_ENSURE((*ch)->alloced, S2N_ERR_INVALID_ARGUMENT);
     194         [ -  + ]:         93 :     POSIX_GUARD(s2n_client_hello_free_raw_message(*ch));
     195         [ -  + ]:         93 :     POSIX_GUARD(s2n_free_object((uint8_t **) ch, sizeof(struct s2n_client_hello)));
     196                 :         93 :     *ch = NULL;
     197                 :         93 :     return S2N_SUCCESS;
     198                 :         93 : }
     199                 :            : 
     200                 :            : int s2n_collect_client_hello(struct s2n_client_hello *ch, struct s2n_stuffer *source)
     201                 :       7805 : {
     202 [ -  + ][ #  # ]:       7805 :     POSIX_ENSURE_REF(ch);
     203 [ #  # ][ -  + ]:       7805 :     POSIX_ENSURE_REF(source);
     204                 :            : 
     205                 :       7805 :     uint32_t size = s2n_stuffer_data_available(source);
     206 [ -  + ][ #  # ]:       7805 :     S2N_ERROR_IF(size == 0, S2N_ERR_BAD_MESSAGE);
     207                 :            : 
     208         [ -  + ]:       7805 :     POSIX_GUARD(s2n_realloc(&ch->raw_message, size));
     209         [ -  + ]:       7805 :     POSIX_GUARD(s2n_stuffer_read(source, &ch->raw_message));
     210                 :            : 
     211                 :       7805 :     return 0;
     212                 :       7805 : }
     213                 :            : 
     214                 :            : static S2N_RESULT s2n_client_hello_verify_for_retry(struct s2n_connection *conn,
     215                 :            :         struct s2n_client_hello *old_ch, struct s2n_client_hello *new_ch,
     216                 :            :         uint8_t *previous_client_random)
     217                 :       7707 : {
     218 [ -  + ][ #  # ]:       7707 :     RESULT_ENSURE_REF(conn);
     219 [ #  # ][ -  + ]:       7707 :     RESULT_ENSURE_REF(old_ch);
     220 [ -  + ][ #  # ]:       7707 :     RESULT_ENSURE_REF(new_ch);
     221 [ #  # ][ -  + ]:       7707 :     RESULT_ENSURE_REF(previous_client_random);
     222                 :            : 
     223         [ +  + ]:       7707 :     if (!s2n_is_hello_retry_handshake(conn)) {
     224                 :       7052 :         return S2N_RESULT_OK;
     225                 :       7052 :     }
     226                 :            : 
     227                 :            :     /*
     228                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.2
     229                 :            :      *# The client will also send a
     230                 :            :      *# ClientHello when the server has responded to its ClientHello with a
     231                 :            :      *# HelloRetryRequest.  In that case, the client MUST send the same
     232                 :            :      *# ClientHello without modification, except as follows:
     233                 :            :      *
     234                 :            :      * All of the exceptions that follow are extensions.
     235                 :            :      */
     236 [ +  - ][ +  + ]:        655 :     RESULT_ENSURE(old_ch->legacy_version == new_ch->legacy_version, S2N_ERR_BAD_MESSAGE);
     237 [ -  + ][ #  # ]:        654 :     RESULT_ENSURE(old_ch->compression_methods.size == new_ch->compression_methods.size, S2N_ERR_BAD_MESSAGE);
     238 [ +  - ][ +  + ]:        654 :     RESULT_ENSURE(s2n_constant_time_equals(old_ch->compression_methods.data, new_ch->compression_methods.data,
     239                 :        653 :                           new_ch->compression_methods.size),
     240                 :        653 :             S2N_ERR_BAD_MESSAGE);
     241                 :            : 
     242                 :            :     /* Some clients are not compliant with TLS 1.3 RFC, and send mismatching values in their second
     243                 :            :      * ClientHello. For increased compatibility, these checks are skipped outside of tests. The
     244                 :            :      * checks are still included in tests to ensure the s2n-tls client remains compliant.
     245                 :            :      */
     246         [ +  + ]:        653 :     if (s2n_in_test()) {
     247                 :            :         /* In the past, the s2n-tls client updated the client random in the second ClientHello
     248                 :            :          * which is not allowed by RFC8446: https://github.com/aws/s2n-tls/pull/3311. Although the
     249                 :            :          * issue was addressed, its existence means that old versions of the s2n-tls client will
     250                 :            :          * fail this validation.
     251                 :            :          */
     252 [ +  + ][ +  - ]:        649 :         RESULT_ENSURE(s2n_constant_time_equals(
     253                 :        648 :                               previous_client_random,
     254                 :        648 :                               conn->handshake_params.client_random,
     255                 :        648 :                               S2N_TLS_RANDOM_DATA_LEN),
     256                 :        648 :                 S2N_ERR_BAD_MESSAGE);
     257                 :            : 
     258                 :            :         /* Some clients have been found to send a mismatching legacy session ID. */
     259 [ #  # ][ -  + ]:        648 :         RESULT_ENSURE(old_ch->session_id.size == new_ch->session_id.size, S2N_ERR_BAD_MESSAGE);
     260 [ +  + ][ +  - ]:        648 :         RESULT_ENSURE(s2n_constant_time_equals(old_ch->session_id.data, new_ch->session_id.data,
     261                 :        647 :                               new_ch->session_id.size),
     262                 :        647 :                 S2N_ERR_BAD_MESSAGE);
     263                 :            : 
     264                 :            :         /* Some clients have been found to send a mismatching cipher suite list. */
     265 [ #  # ][ -  + ]:        647 :         RESULT_ENSURE(old_ch->cipher_suites.size == new_ch->cipher_suites.size, S2N_ERR_BAD_MESSAGE);
     266 [ +  - ][ +  + ]:        647 :         RESULT_ENSURE(s2n_constant_time_equals(old_ch->cipher_suites.data, new_ch->cipher_suites.data,
     267                 :        647 :                               new_ch->cipher_suites.size),
     268                 :        647 :                 S2N_ERR_BAD_MESSAGE);
     269                 :        647 :     }
     270                 :            : 
     271                 :            :     /*
     272                 :            :      * Now enforce that the extensions also exactly match,
     273                 :            :      * except for the exceptions described in the RFC.
     274                 :            :      */
     275         [ +  + ]:      14243 :     for (size_t i = 0; i < s2n_array_len(s2n_supported_extensions); i++) {
     276                 :      13596 :         s2n_parsed_extension *old_extension = &old_ch->extensions.parsed_extensions[i];
     277                 :      13596 :         uint32_t old_size = old_extension->extension.size;
     278                 :      13596 :         s2n_parsed_extension *new_extension = &new_ch->extensions.parsed_extensions[i];
     279                 :      13596 :         uint32_t new_size = new_extension->extension.size;
     280                 :            : 
     281                 :            :         /* The extension type is only set if the extension is present.
     282                 :            :          * Look for a non-zero-length extension.
     283                 :            :          */
     284                 :      13596 :         uint16_t extension_type = 0;
     285         [ +  + ]:      13596 :         if (old_size != 0) {
     286                 :       4179 :             extension_type = old_extension->extension_type;
     287         [ +  + ]:       9417 :         } else if (new_size != 0) {
     288                 :         38 :             extension_type = new_extension->extension_type;
     289                 :       9379 :         } else {
     290                 :       9379 :             continue;
     291                 :       9379 :         }
     292                 :            : 
     293                 :       4217 :         switch (extension_type) {
     294                 :            :             /*
     295                 :            :              *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.2
     296                 :            :              *#    -  If a "key_share" extension was supplied in the HelloRetryRequest,
     297                 :            :              *#       replacing the list of shares with a list containing a single
     298                 :            :              *#       KeyShareEntry from the indicated group.
     299                 :            :              */
     300         [ +  + ]:        647 :             case TLS_EXTENSION_KEY_SHARE:
     301                 :            :                 /* Handled when parsing the key share extension */
     302                 :        647 :                 break;
     303                 :            :             /*
     304                 :            :              *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.2
     305                 :            :              *#    -  Removing the "early_data" extension (Section 4.2.10) if one was
     306                 :            :              *#       present.  Early data is not permitted after a HelloRetryRequest.
     307                 :            :              */
     308         [ -  + ]:          0 :             case TLS_EXTENSION_EARLY_DATA:
     309 [ #  # ][ #  # ]:          0 :                 RESULT_ENSURE(new_size == 0, S2N_ERR_BAD_MESSAGE);
     310                 :          0 :                 break;
     311                 :            :             /*
     312                 :            :              *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.2
     313                 :            :              *#    -  Including a "cookie" extension if one was provided in the
     314                 :            :              *#       HelloRetryRequest.
     315                 :            :              */
     316         [ +  + ]:         37 :             case TLS_EXTENSION_COOKIE:
     317                 :            :                 /* Handled when parsing the cookie extension */
     318                 :         37 :                 break;
     319                 :            :             /*
     320                 :            :              *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.2
     321                 :            :              *#    -  Updating the "pre_shared_key" extension if present by recomputing
     322                 :            :              *#       the "obfuscated_ticket_age" and binder values and (optionally)
     323                 :            :              *#       removing any PSKs which are incompatible with the server's
     324                 :            :              *#       indicated cipher suite.
     325                 :            :              */
     326         [ +  + ]:        462 :             case TLS_EXTENSION_PRE_SHARED_KEY:
     327                 :            :                 /* Handled when parsing the psk extension */
     328                 :        462 :                 break;
     329                 :            : 
     330                 :            :             /* Some clients have been found to send mismatching supported versions in their second
     331                 :            :              * ClientHello. The extension isn't compared byte-for-byte for increased compatibility
     332                 :            :              * with these clients.
     333                 :            :              */
     334         [ +  + ]:        647 :             case TLS_EXTENSION_SUPPORTED_VERSIONS:
     335                 :            :                 /* Additional HRR validation for the supported versions extension is performed when
     336                 :            :                  * parsing the extension.
     337                 :            :                  */
     338                 :        647 :                 break;
     339                 :            : 
     340                 :            :             /*
     341                 :            :              * No more exceptions.
     342                 :            :              * All other extensions must match.
     343                 :            :              */
     344         [ +  + ]:       2424 :             default:
     345 [ +  - ][ +  + ]:       2424 :                 RESULT_ENSURE(old_size == new_size, S2N_ERR_BAD_MESSAGE);
     346 [ +  - ][ +  + ]:       4217 :                 RESULT_ENSURE(s2n_constant_time_equals(
     347                 :       4217 :                                       new_extension->extension.data,
     348                 :       4217 :                                       old_extension->extension.data,
     349                 :       4217 :                                       old_size),
     350                 :       4217 :                         S2N_ERR_BAD_MESSAGE);
     351                 :       4217 :         }
     352                 :       4217 :     }
     353                 :            : 
     354                 :        647 :     return S2N_RESULT_OK;
     355                 :        650 : }
     356                 :            : 
     357                 :            : S2N_RESULT s2n_client_hello_parse_raw(struct s2n_client_hello *client_hello,
     358                 :            :         uint8_t client_random[S2N_TLS_RANDOM_DATA_LEN])
     359                 :       7798 : {
     360 [ -  + ][ #  # ]:       7798 :     RESULT_ENSURE_REF(client_hello);
     361                 :            : 
     362                 :       7798 :     struct s2n_stuffer in_stuffer = { 0 };
     363         [ -  + ]:       7798 :     RESULT_GUARD_POSIX(s2n_stuffer_init_written(&in_stuffer, &client_hello->raw_message));
     364                 :       7798 :     struct s2n_stuffer *in = &in_stuffer;
     365                 :            : 
     366                 :            :     /**
     367                 :            :      * https://tools.ietf.org/rfc/rfc8446#4.1.2
     368                 :            :      * Structure of this message:
     369                 :            :      *
     370                 :            :      *    uint16 ProtocolVersion;
     371                 :            :      *    opaque Random[32];
     372                 :            :      *
     373                 :            :      *    uint8 CipherSuite[2];
     374                 :            :      *
     375                 :            :      *    struct {
     376                 :            :      *        ProtocolVersion legacy_version = 0x0303;
     377                 :            :      *        Random random;
     378                 :            :      *        opaque legacy_session_id<0..32>;
     379                 :            :      *        CipherSuite cipher_suites<2..2^16-2>;
     380                 :            :      *        opaque legacy_compression_methods<1..2^8-1>;
     381                 :            :      *        Extension extensions<8..2^16-1>;
     382                 :            :      *    } ClientHello;
     383                 :            :      **/
     384                 :            : 
     385                 :            :     /* legacy_version */
     386                 :       7798 :     uint8_t client_protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN] = { 0 };
     387         [ +  + ]:       7798 :     RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(in, client_protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
     388                 :            : 
     389                 :            :     /* Encode the version as a 1 byte representation of the two protocol version bytes, with the
     390                 :            :      * major version in the tens place and the minor version in the ones place. For example, the
     391                 :            :      * TLS 1.2 protocol version is 0x0303, which is encoded as S2N_TLS12 (33).
     392                 :            :      */
     393                 :       7797 :     client_hello->legacy_version = (client_protocol_version[0] * 10) + client_protocol_version[1];
     394                 :            : 
     395                 :            :     /* random */
     396         [ -  + ]:       7797 :     RESULT_GUARD_POSIX(s2n_stuffer_erase_and_read_bytes(in, client_random, S2N_TLS_RANDOM_DATA_LEN));
     397                 :            : 
     398                 :            :     /* legacy_session_id */
     399                 :       7797 :     uint8_t session_id_len = 0;
     400         [ -  + ]:       7797 :     RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(in, &session_id_len));
     401 [ +  - ][ +  + ]:       7797 :     RESULT_ENSURE(session_id_len <= S2N_TLS_SESSION_ID_MAX_LEN, S2N_ERR_BAD_MESSAGE);
     402                 :       7796 :     uint8_t *session_id = s2n_stuffer_raw_read(in, session_id_len);
     403 [ -  + ][ #  # ]:       7796 :     RESULT_ENSURE(session_id != NULL, S2N_ERR_BAD_MESSAGE);
     404         [ -  + ]:       7796 :     RESULT_GUARD_POSIX(s2n_blob_init(&client_hello->session_id, session_id, session_id_len));
     405                 :            : 
     406                 :            :     /* cipher suites */
     407                 :       7796 :     uint16_t cipher_suites_length = 0;
     408         [ -  + ]:       7796 :     RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(in, &cipher_suites_length));
     409 [ +  - ][ +  + ]:       7796 :     RESULT_ENSURE(cipher_suites_length > 0, S2N_ERR_BAD_MESSAGE);
     410 [ -  + ][ #  # ]:       7794 :     RESULT_ENSURE(cipher_suites_length % S2N_TLS_CIPHER_SUITE_LEN == 0, S2N_ERR_BAD_MESSAGE);
     411                 :       7794 :     uint8_t *cipher_suites = s2n_stuffer_raw_read(in, cipher_suites_length);
     412 [ -  + ][ #  # ]:       7794 :     RESULT_ENSURE(cipher_suites != NULL, S2N_ERR_BAD_MESSAGE);
     413         [ -  + ]:       7794 :     RESULT_GUARD_POSIX(s2n_blob_init(&client_hello->cipher_suites, cipher_suites, cipher_suites_length));
     414                 :            : 
     415                 :            :     /* legacy_compression_methods */
     416                 :       7794 :     uint8_t compression_methods_len = 0;
     417         [ -  + ]:       7794 :     RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(in, &compression_methods_len));
     418                 :       7794 :     uint8_t *compression_methods = s2n_stuffer_raw_read(in, compression_methods_len);
     419 [ -  + ][ #  # ]:       7794 :     RESULT_ENSURE(compression_methods != NULL, S2N_ERR_BAD_MESSAGE);
     420         [ -  + ]:       7794 :     RESULT_GUARD_POSIX(s2n_blob_init(&client_hello->compression_methods, compression_methods, compression_methods_len));
     421                 :            : 
     422                 :            :     /* extensions */
     423         [ +  + ]:       7794 :     RESULT_GUARD_POSIX(s2n_extension_list_parse(in, &client_hello->extensions));
     424                 :            : 
     425                 :       7793 :     return S2N_RESULT_OK;
     426                 :       7794 : }
     427                 :            : 
     428                 :            : int s2n_parse_client_hello(struct s2n_connection *conn)
     429                 :       7721 : {
     430 [ #  # ][ -  + ]:       7721 :     POSIX_ENSURE_REF(conn);
     431                 :            : 
     432                 :            :     /* SSLv2 ClientHellos are not allowed during a HelloRetryRequest */
     433         [ +  + ]:       7721 :     if (s2n_is_hello_retry_handshake(conn)) {
     434 [ +  + ][ +  - ]:        656 :         POSIX_ENSURE(!conn->client_hello.sslv2, S2N_ERR_BAD_MESSAGE);
     435                 :        656 :     }
     436                 :            : 
     437                 :            :     /* If a retry, move the old version of the client hello
     438                 :            :      * somewhere safe so we can compare it to the new client hello later.
     439                 :            :      */
     440                 :       7720 :     DEFER_CLEANUP(struct s2n_client_hello previous_hello_retry = conn->client_hello,
     441                 :       7720 :             s2n_client_hello_free_raw_message);
     442         [ +  + ]:       7720 :     if (s2n_is_hello_retry_handshake(conn)) {
     443 [ #  # ][ -  + ]:        655 :         POSIX_CHECKED_MEMSET(&conn->client_hello, 0, sizeof(struct s2n_client_hello));
                 [ +  - ]
     444                 :        655 :     }
     445                 :            : 
     446         [ -  + ]:       7720 :     POSIX_GUARD(s2n_collect_client_hello(&conn->client_hello, &conn->handshake.io));
     447                 :            : 
     448         [ +  + ]:       7720 :     if (conn->client_hello.sslv2) {
     449         [ +  + ]:          7 :         POSIX_GUARD(s2n_sslv2_client_hello_parse(conn));
     450                 :          6 :         return S2N_SUCCESS;
     451                 :          7 :     }
     452                 :            : 
     453                 :            :     /* Save the current client_random for comparison in the case of a retry */
     454                 :       7713 :     uint8_t previous_client_random[S2N_TLS_RANDOM_DATA_LEN] = { 0 };
     455 [ -  + ][ #  # ]:       7713 :     POSIX_CHECKED_MEMCPY(previous_client_random, conn->handshake_params.client_random,
                 [ +  - ]
     456                 :       7713 :             S2N_TLS_RANDOM_DATA_LEN);
     457                 :            : 
     458                 :            :     /* Parse raw, collected client hello */
     459         [ +  + ]:       7713 :     POSIX_GUARD_RESULT(s2n_client_hello_parse_raw(&conn->client_hello,
     460                 :       7710 :             conn->handshake_params.client_random));
     461                 :            : 
     462                 :            :     /* Protocol version in the ClientHello is fixed at 0x0303(TLS 1.2) for
     463                 :            :      * future versions of TLS. Therefore, we will negotiate down if a client sends
     464                 :            :      * an unexpected value above 0x0303.
     465                 :            :      */
     466                 :       7710 :     conn->client_protocol_version = MIN(conn->client_hello.legacy_version, S2N_TLS12);
     467                 :            : 
     468                 :            :     /* Copy the session id to the connection. */
     469                 :       7710 :     conn->session_id_len = conn->client_hello.session_id.size;
     470 [ #  # ][ -  + ]:       7710 :     POSIX_CHECKED_MEMCPY(conn->session_id, conn->client_hello.session_id.data, conn->session_id_len);
                 [ +  + ]
     471                 :            : 
     472         [ +  + ]:       7710 :     POSIX_GUARD_RESULT(s2n_client_hello_verify_for_retry(conn,
     473                 :       7702 :             &previous_hello_retry, &conn->client_hello, previous_client_random));
     474                 :       7702 :     return S2N_SUCCESS;
     475                 :       7710 : }
     476                 :            : 
     477                 :            : static S2N_RESULT s2n_client_hello_parse_message_impl(struct s2n_client_hello **result,
     478                 :            :         const uint8_t *raw_message, uint32_t raw_message_size)
     479                 :         93 : {
     480 [ -  + ][ #  # ]:         93 :     RESULT_ENSURE_REF(result);
     481                 :            : 
     482                 :         93 :     DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free);
     483         [ -  + ]:         93 :     RESULT_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_client_hello)));
     484         [ -  + ]:         93 :     RESULT_GUARD_POSIX(s2n_blob_zero(&mem));
     485                 :            : 
     486                 :         93 :     DEFER_CLEANUP(struct s2n_client_hello *client_hello = NULL, s2n_client_hello_free);
     487                 :         93 :     client_hello = (struct s2n_client_hello *) (void *) mem.data;
     488                 :         93 :     client_hello->alloced = true;
     489                 :         93 :     ZERO_TO_DISABLE_DEFER_CLEANUP(mem);
     490                 :            : 
     491                 :         93 :     DEFER_CLEANUP(struct s2n_stuffer in = { 0 }, s2n_stuffer_free);
     492         [ -  + ]:         93 :     RESULT_GUARD_POSIX(s2n_stuffer_alloc(&in, raw_message_size));
     493         [ -  + ]:         93 :     RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&in, raw_message, raw_message_size));
     494                 :            : 
     495                 :         93 :     uint8_t message_type = 0;
     496                 :         93 :     uint32_t message_len = 0;
     497         [ -  + ]:         93 :     RESULT_GUARD(s2n_handshake_parse_header(&in, &message_type, &message_len));
     498 [ +  - ][ +  + ]:         93 :     RESULT_ENSURE(message_type == TLS_CLIENT_HELLO, S2N_ERR_BAD_MESSAGE);
     499 [ +  - ][ +  + ]:         87 :     RESULT_ENSURE(message_len == s2n_stuffer_data_available(&in), S2N_ERR_BAD_MESSAGE);
     500                 :            : 
     501         [ -  + ]:         85 :     RESULT_GUARD_POSIX(s2n_collect_client_hello(client_hello, &in));
     502 [ #  # ][ -  + ]:         85 :     RESULT_ENSURE(s2n_stuffer_data_available(&in) == 0, S2N_ERR_BAD_MESSAGE);
     503                 :            : 
     504                 :         85 :     uint8_t random[S2N_TLS_RANDOM_DATA_LEN] = { 0 };
     505         [ +  + ]:         85 :     RESULT_GUARD(s2n_client_hello_parse_raw(client_hello, random));
     506                 :            : 
     507                 :         83 :     *result = client_hello;
     508                 :         83 :     ZERO_TO_DISABLE_DEFER_CLEANUP(client_hello);
     509                 :         83 :     return S2N_RESULT_OK;
     510                 :         85 : }
     511                 :            : 
     512                 :            : struct s2n_client_hello *s2n_client_hello_parse_message(const uint8_t *raw_message, uint32_t raw_message_size)
     513                 :         93 : {
     514                 :         93 :     struct s2n_client_hello *result = NULL;
     515         [ +  + ]:         93 :     PTR_GUARD_RESULT(s2n_client_hello_parse_message_impl(&result, raw_message, raw_message_size));
     516                 :         83 :     return result;
     517                 :         93 : }
     518                 :            : 
     519                 :            : int s2n_process_client_hello(struct s2n_connection *conn)
     520                 :       7692 : {
     521 [ -  + ][ #  # ]:       7692 :     POSIX_ENSURE_REF(conn);
     522 [ -  + ][ #  # ]:       7692 :     POSIX_ENSURE_REF(conn->secure);
     523 [ #  # ][ -  + ]:       7692 :     POSIX_ENSURE_REF(conn->secure->cipher_suite);
     524                 :            : 
     525                 :            :     /* Client hello is parsed and config is finalized.
     526                 :            :      * Negotiate protocol version, cipher suite, ALPN, select a cert, etc. */
     527                 :       7692 :     struct s2n_client_hello *client_hello = &conn->client_hello;
     528                 :            : 
     529                 :       7692 :     const struct s2n_security_policy *security_policy = NULL;
     530         [ -  + ]:       7692 :     POSIX_GUARD(s2n_connection_get_security_policy(conn, &security_policy));
     531                 :            : 
     532 [ -  + ][ +  + ]:       7692 :     if (!s2n_connection_supports_tls13(conn) || !s2n_security_policy_supports_tls13(security_policy)) {
     533                 :       2310 :         conn->server_protocol_version = MIN(conn->server_protocol_version, S2N_TLS12);
     534                 :       2310 :         conn->actual_protocol_version = MIN(conn->server_protocol_version, S2N_TLS12);
     535                 :       2310 :     }
     536                 :            : 
     537                 :            :     /* Set default key exchange curve.
     538                 :            :      * This is going to be our fallback if the client has no preference.
     539                 :            :      *
     540                 :            :      * P-256 is our preferred fallback option because the TLS1.3 RFC requires
     541                 :            :      * all implementations to support it:
     542                 :            :      *
     543                 :            :      *     https://tools.ietf.org/rfc/rfc8446#section-9.1
     544                 :            :      *     A TLS-compliant application MUST support key exchange with secp256r1 (NIST P-256)
     545                 :            :      *     and SHOULD support key exchange with X25519 [RFC7748]
     546                 :            :      *
     547                 :            :      *= https://www.rfc-editor.org/rfc/rfc4492#section-4
     548                 :            :      *# A client that proposes ECC cipher suites may choose not to include these extensions.
     549                 :            :      *# In this case, the server is free to choose any one of the elliptic curves or point formats listed in Section 5.
     550                 :            :      *
     551                 :            :      */
     552                 :       7692 :     const struct s2n_ecc_preferences *ecc_pref = NULL;
     553         [ -  + ]:       7692 :     POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
     554 [ #  # ][ -  + ]:       7692 :     POSIX_ENSURE_REF(ecc_pref);
     555                 :            : 
     556         [ -  + ]:       7692 :     if (ecc_pref->count == 0) {
     557                 :          0 :         conn->kex_params.server_ecc_evp_params.negotiated_curve = NULL;
     558         [ +  + ]:       7692 :     } else if (s2n_ecc_preferences_includes_curve(ecc_pref, TLS_EC_CURVE_SECP_256_R1)) {
     559                 :       7669 :         conn->kex_params.server_ecc_evp_params.negotiated_curve = &s2n_ecc_curve_secp256r1;
     560                 :       7669 :     } else {
     561                 :            :         /* If P-256 isn't allowed by the current security policy, choose the first / most preferred curve. */
     562                 :         23 :         conn->kex_params.server_ecc_evp_params.negotiated_curve = ecc_pref->ecc_curves[0];
     563                 :         23 :     }
     564                 :            : 
     565         [ +  + ]:       7692 :     POSIX_GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_CLIENT_HELLO, conn, &conn->client_hello.extensions));
     566                 :            : 
     567                 :            :     /* After parsing extensions, select a curve and corresponding keyshare to use */
     568         [ +  + ]:       7684 :     if (conn->actual_protocol_version >= S2N_TLS13) {
     569         [ -  + ]:       5186 :         POSIX_GUARD(s2n_extensions_server_key_share_select(conn));
     570                 :       5186 :     }
     571                 :            : 
     572                 :            :     /* for pre TLS 1.3 connections, protocol selection is not done in supported_versions extensions, so do it here */
     573         [ +  + ]:       7684 :     if (conn->actual_protocol_version < S2N_TLS13) {
     574                 :       2498 :         conn->actual_protocol_version = MIN(conn->server_protocol_version, conn->client_protocol_version);
     575                 :       2498 :     }
     576                 :            : 
     577         [ +  + ]:       7684 :     if (conn->client_protocol_version < security_policy->minimum_protocol_version) {
     578         [ -  + ]:          2 :         POSIX_GUARD(s2n_queue_reader_unsupported_protocol_version_alert(conn));
     579         [ +  - ]:          2 :         POSIX_BAIL(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
     580                 :          2 :     }
     581                 :            : 
     582         [ +  + ]:       7682 :     if (s2n_connection_is_quic_enabled(conn)) {
     583 [ +  + ][ +  - ]:         12 :         POSIX_ENSURE(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
     584                 :         12 :     }
     585                 :            : 
     586                 :            :     /* Find potential certificate matches before we choose the cipher. */
     587         [ -  + ]:       7681 :     POSIX_GUARD(s2n_conn_find_name_matching_certs(conn));
     588                 :            : 
     589                 :            :     /* Save the previous cipher suite */
     590                 :       7681 :     uint8_t previous_cipher_suite_iana[S2N_TLS_CIPHER_SUITE_LEN] = { 0 };
     591 [ -  + ][ #  # ]:       7681 :     POSIX_CHECKED_MEMCPY(previous_cipher_suite_iana, conn->secure->cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN);
                 [ +  - ]
     592                 :            : 
     593                 :            :     /* Now choose the ciphers we have certs for. */
     594         [ +  + ]:       7681 :     if (conn->client_hello.sslv2) {
     595         [ -  + ]:          5 :         POSIX_GUARD(s2n_set_cipher_as_sslv2_server(conn, client_hello->cipher_suites.data,
     596                 :          5 :                 client_hello->cipher_suites.size / S2N_SSLv2_CIPHER_SUITE_LEN));
     597                 :       7676 :     } else {
     598         [ +  + ]:       7676 :         POSIX_GUARD(s2n_set_cipher_as_tls_server(conn, client_hello->cipher_suites.data,
     599                 :       7676 :                 client_hello->cipher_suites.size / 2));
     600                 :       7676 :     }
     601                 :            : 
     602                 :            :     /* Check if this is the second client hello in a hello retry handshake */
     603 [ +  + ][ +  + ]:       7664 :     if (s2n_is_hello_retry_handshake(conn) && conn->handshake.message_number > 0) {
     604                 :            :         /**
     605                 :            :          *= https://www.rfc-editor.org/rfc/rfc8446#4.1.4
     606                 :            :          *# Servers MUST ensure that they negotiate the
     607                 :            :          *# same cipher suite when receiving a conformant updated ClientHello (if
     608                 :            :          *# the server selects the cipher suite as the first step in the
     609                 :            :          *# negotiation, then this will happen automatically).
     610                 :            :          **/
     611 [ +  + ][ +  - ]:        643 :         POSIX_ENSURE(s2n_constant_time_equals(previous_cipher_suite_iana, conn->secure->cipher_suite->iana_value,
     612                 :        643 :                              S2N_TLS_CIPHER_SUITE_LEN),
     613                 :        643 :                 S2N_ERR_BAD_MESSAGE);
     614                 :        643 :     }
     615                 :            : 
     616                 :            :     /* If we're using a PSK, we don't need to choose a signature algorithm or certificate,
     617                 :            :      * because no additional auth is required. */
     618         [ +  + ]:       7662 :     if (conn->psk_params.chosen_psk != NULL) {
     619                 :       1066 :         return S2N_SUCCESS;
     620                 :       1066 :     }
     621                 :            : 
     622                 :            :     /* And set the signature and hash algorithm used for key exchange signatures */
     623         [ +  + ]:       6596 :     POSIX_GUARD_RESULT(s2n_signature_algorithm_select(conn));
     624                 :            : 
     625                 :            :     /* And finally, set the certs specified by the final auth + sig_alg combo. */
     626         [ +  + ]:       6593 :     POSIX_GUARD(s2n_select_certs_for_server_auth(conn, &conn->handshake_params.our_chain_and_key));
     627                 :            : 
     628                 :       6591 :     return S2N_SUCCESS;
     629                 :       6593 : }
     630                 :            : 
     631                 :            : static S2N_RESULT s2n_client_hello_process_cb_response(struct s2n_connection *conn, int rc)
     632                 :        122 : {
     633         [ +  + ]:        122 :     if (rc < 0) {
     634                 :          4 :         goto fail;
     635                 :          4 :     }
     636         [ -  + ]:        118 :     switch (conn->config->client_hello_cb_mode) {
     637         [ +  + ]:         90 :         case S2N_CLIENT_HELLO_CB_BLOCKING: {
     638         [ +  + ]:         90 :             if (rc) {
     639                 :          5 :                 conn->server_name_used = 1;
     640                 :          5 :             }
     641                 :         90 :             return S2N_RESULT_OK;
     642                 :          0 :         }
     643         [ +  + ]:         28 :         case S2N_CLIENT_HELLO_CB_NONBLOCKING: {
     644         [ +  + ]:         28 :             if (conn->client_hello.callback_async_done) {
     645                 :          9 :                 return S2N_RESULT_OK;
     646                 :          9 :             }
     647                 :         19 :             conn->client_hello.callback_async_blocked = 1;
     648         [ +  - ]:         19 :             RESULT_BAIL(S2N_ERR_ASYNC_BLOCKED);
     649                 :         19 :         }
     650                 :        118 :     }
     651                 :          4 : fail:
     652                 :            :     /* rc < 0 */
     653         [ -  + ]:          4 :     RESULT_GUARD_POSIX(s2n_queue_reader_handshake_failure_alert(conn));
     654         [ +  - ]:          4 :     RESULT_BAIL(S2N_ERR_CANCELLED);
     655                 :          4 : }
     656                 :            : 
     657                 :            : int s2n_client_hello_recv(struct s2n_connection *conn)
     658                 :       7741 : {
     659 [ +  + ][ +  - ]:       7741 :     POSIX_ENSURE(!conn->client_hello.callback_async_blocked, S2N_ERR_ASYNC_BLOCKED);
     660                 :            : 
     661                 :            :     /* Only parse the ClientHello once */
     662         [ +  + ]:       7730 :     if (!conn->client_hello.parsed) {
     663         [ +  + ]:       7706 :         POSIX_GUARD(s2n_parse_client_hello(conn));
     664                 :            :         /* Mark the collected client hello as available when parsing is done and before the client hello callback */
     665                 :       7694 :         conn->client_hello.parsed = true;
     666                 :       7694 :     }
     667                 :            : 
     668                 :            :     /* Only invoke the ClientHello callback once.
     669                 :            :      * This means that we do NOT invoke the callback again on the second ClientHello
     670                 :            :      * in a TLS1.3 retry handshake. We explicitly check for a retry because the
     671                 :            :      * callback state may have been cleared while parsing the second ClientHello.
     672                 :            :      */
     673 [ +  + ][ +  + ]:       7718 :     if (!conn->client_hello.callback_invoked && !IS_HELLO_RETRY_HANDSHAKE(conn)) {
     674                 :            :         /* Mark the client hello callback as invoked to avoid calling it again. */
     675                 :       7051 :         conn->client_hello.callback_invoked = true;
     676                 :            : 
     677                 :            :         /* Do NOT move this null check. A test exists to assert that a server connection can get
     678                 :            :          * as far as the client hello callback without using its config. To do this we need a
     679                 :            :          * specific error for a null config just before the client hello callback. The test's
     680                 :            :          * assertions are weakened if this check is moved. */
     681 [ +  - ][ +  + ]:       7051 :         POSIX_ENSURE(conn->config, S2N_ERR_CONFIG_NULL_BEFORE_CH_CALLBACK);
     682                 :            : 
     683                 :            :         /* Call client_hello_cb if exists, letting application to modify s2n_connection or swap s2n_config */
     684         [ +  + ]:       7048 :         if (conn->config->client_hello_cb) {
     685                 :        124 :             int rc = conn->config->client_hello_cb(conn, conn->config->client_hello_cb_ctx);
     686         [ +  + ]:        124 :             POSIX_GUARD_RESULT(s2n_client_hello_process_cb_response(conn, rc));
     687                 :        124 :         }
     688                 :       7048 :     }
     689                 :            : 
     690         [ +  + ]:       7692 :     POSIX_GUARD(s2n_process_client_hello(conn));
     691                 :            : 
     692                 :       7657 :     return 0;
     693                 :       7692 : }
     694                 :            : 
     695                 :            : S2N_RESULT s2n_cipher_suite_validate_available(struct s2n_connection *conn, struct s2n_cipher_suite *cipher)
     696                 :     161553 : {
     697 [ #  # ][ -  + ]:     161553 :     RESULT_ENSURE_REF(conn);
     698 [ -  + ][ #  # ]:     161553 :     RESULT_ENSURE_REF(cipher);
     699 [ +  + ][ +  - ]:     161553 :     RESULT_ENSURE_EQ(cipher->available, true);
     700 [ +  + ][ +  - ]:     159593 :     RESULT_ENSURE_LTE(cipher->minimum_required_tls_version, conn->client_protocol_version);
     701         [ +  + ]:     159150 :     if (s2n_connection_is_quic_enabled(conn)) {
     702 [ +  + ][ +  - ]:        251 :         RESULT_ENSURE_GTE(cipher->minimum_required_tls_version, S2N_TLS13);
     703                 :        251 :     }
     704                 :     158938 :     return S2N_RESULT_OK;
     705                 :     159150 : }
     706                 :            : 
     707                 :            : int s2n_client_hello_send(struct s2n_connection *conn)
     708                 :       7665 : {
     709 [ #  # ][ -  + ]:       7665 :     POSIX_ENSURE_REF(conn);
     710                 :            : 
     711                 :       7665 :     const struct s2n_security_policy *security_policy = NULL;
     712         [ -  + ]:       7665 :     POSIX_GUARD(s2n_connection_get_security_policy(conn, &security_policy));
     713                 :            : 
     714                 :       7665 :     const struct s2n_cipher_preferences *cipher_preferences = security_policy->cipher_preferences;
     715 [ #  # ][ -  + ]:       7665 :     POSIX_ENSURE_REF(cipher_preferences);
     716                 :            : 
     717 [ -  + ][ +  + ]:       7665 :     if (!s2n_connection_supports_tls13(conn) || !s2n_security_policy_supports_tls13(security_policy)) {
     718                 :       1835 :         conn->client_protocol_version = MIN(conn->client_protocol_version, S2N_TLS12);
     719                 :       1835 :         conn->actual_protocol_version = MIN(conn->actual_protocol_version, S2N_TLS12);
     720                 :       1835 :     }
     721                 :            : 
     722                 :       7665 :     struct s2n_stuffer *out = &conn->handshake.io;
     723                 :       7665 :     uint8_t client_protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN] = { 0 };
     724                 :            : 
     725                 :       7665 :     uint8_t reported_protocol_version = MIN(conn->client_protocol_version, S2N_TLS12);
     726                 :       7665 :     conn->client_hello.legacy_version = reported_protocol_version;
     727                 :       7665 :     client_protocol_version[0] = reported_protocol_version / 10;
     728                 :       7665 :     client_protocol_version[1] = reported_protocol_version % 10;
     729         [ -  + ]:       7665 :     POSIX_GUARD(s2n_stuffer_write_bytes(out, client_protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
     730                 :            : 
     731                 :       7665 :     struct s2n_blob client_random = { 0 };
     732         [ -  + ]:       7665 :     POSIX_GUARD(s2n_blob_init(&client_random, conn->handshake_params.client_random, S2N_TLS_RANDOM_DATA_LEN));
     733         [ +  + ]:       7665 :     if (!s2n_is_hello_retry_handshake(conn)) {
     734                 :            :         /* Only generate the random data for our first client hello.
     735                 :            :          * If we retry, we'll reuse the value. */
     736         [ -  + ]:       7007 :         POSIX_GUARD_RESULT(s2n_get_public_random_data(&client_random));
     737                 :       7007 :     }
     738         [ -  + ]:       7665 :     POSIX_GUARD(s2n_stuffer_write(out, &client_random));
     739                 :            : 
     740         [ +  + ]:       7665 :     POSIX_GUARD_RESULT(s2n_generate_client_session_id(conn));
     741         [ -  + ]:       7664 :     POSIX_GUARD(s2n_stuffer_write_uint8(out, conn->session_id_len));
     742         [ +  + ]:       7664 :     if (conn->session_id_len > 0) {
     743         [ -  + ]:       5602 :         POSIX_GUARD(s2n_stuffer_write_bytes(out, conn->session_id, conn->session_id_len));
     744                 :       5602 :     }
     745                 :            : 
     746                 :            :     /* Reserve space for size of the list of available ciphers */
     747                 :       7664 :     struct s2n_stuffer_reservation available_cipher_suites_size;
     748         [ -  + ]:       7664 :     POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &available_cipher_suites_size));
     749                 :            : 
     750                 :            :     /* Now, write the IANA values of every available cipher suite in our list */
     751                 :       7664 :     struct s2n_cipher_suite *cipher = NULL;
     752                 :       7664 :     bool tls12_is_possible = false;
     753         [ +  + ]:     169217 :     for (size_t i = 0; i < security_policy->cipher_preferences->count; i++) {
     754                 :     161553 :         cipher = cipher_preferences->suites[i];
     755         [ +  + ]:     161553 :         if (s2n_result_is_error(s2n_cipher_suite_validate_available(conn, cipher))) {
     756                 :       2615 :             continue;
     757                 :       2615 :         }
     758         [ +  + ]:     158938 :         if (cipher->minimum_required_tls_version < S2N_TLS13) {
     759                 :     141677 :             tls12_is_possible = true;
     760                 :     141677 :         }
     761         [ -  + ]:     158938 :         POSIX_GUARD(s2n_stuffer_write_bytes(out, cipher->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
     762                 :     158938 :     }
     763                 :            : 
     764                 :            :     /**
     765                 :            :      * For initial handshakes:
     766                 :            :      *= https://www.rfc-editor.org/rfc/rfc5746#3.4
     767                 :            :      *# o  The client MUST include either an empty "renegotiation_info"
     768                 :            :      *#    extension, or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling
     769                 :            :      *#    cipher suite value in the ClientHello.  Including both is NOT
     770                 :            :      *#    RECOMMENDED.
     771                 :            :      * For maximum backwards compatibility, we choose to use the TLS_EMPTY_RENEGOTIATION_INFO_SCSV cipher suite
     772                 :            :      * rather than the "renegotiation_info" extension.
     773                 :            :      *
     774                 :            :      * For renegotiation handshakes:
     775                 :            :      *= https://www.rfc-editor.org/rfc/rfc5746#3.5
     776                 :            :      *# The SCSV MUST NOT be included.
     777                 :            :      */
     778 [ +  + ][ +  + ]:       7664 :     if (tls12_is_possible && !s2n_handshake_is_renegotiation(conn)) {
     779                 :       7323 :         uint8_t renegotiation_info_scsv[S2N_TLS_CIPHER_SUITE_LEN] = { TLS_EMPTY_RENEGOTIATION_INFO_SCSV };
     780         [ -  + ]:       7323 :         POSIX_GUARD(s2n_stuffer_write_bytes(out, renegotiation_info_scsv, S2N_TLS_CIPHER_SUITE_LEN));
     781                 :       7323 :     }
     782                 :            : 
     783                 :            :     /* Write size of the list of available ciphers */
     784                 :       7664 :     uint32_t ciphers_size = 0;
     785         [ -  + ]:       7664 :     POSIX_GUARD(s2n_stuffer_get_vector_size(&available_cipher_suites_size, &ciphers_size));
     786 [ +  + ][ +  - ]:       7664 :     POSIX_ENSURE(ciphers_size > 0, S2N_ERR_INVALID_CIPHER_PREFERENCES);
     787         [ -  + ]:       7663 :     POSIX_GUARD(s2n_stuffer_write_reservation(&available_cipher_suites_size, ciphers_size));
     788                 :            : 
     789                 :            :     /* Zero compression methods */
     790         [ -  + ]:       7663 :     POSIX_GUARD(s2n_stuffer_write_uint8(out, 1));
     791         [ -  + ]:       7663 :     POSIX_GUARD(s2n_stuffer_write_uint8(out, 0));
     792                 :            : 
     793                 :            :     /* Write the extensions */
     794         [ -  + ]:       7663 :     POSIX_GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_CLIENT_HELLO, conn, out));
     795                 :            : 
     796                 :            :     /* Once the message is complete, finish calculating the PSK binders.
     797                 :            :      *
     798                 :            :      * The PSK binders require all the sizes in the ClientHello to be written correctly,
     799                 :            :      * including the extension size and extension list size, and therefore have
     800                 :            :      * to be calculated AFTER we finish writing the entire extension list. */
     801         [ -  + ]:       7663 :     POSIX_GUARD_RESULT(s2n_finish_psk_extension(conn));
     802                 :            : 
     803                 :            :     /* If early data was not requested as part of the ClientHello, it never will be. */
     804         [ +  + ]:       7663 :     if (conn->early_data_state == S2N_UNKNOWN_EARLY_DATA_STATE) {
     805         [ -  + ]:       6466 :         POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_NOT_REQUESTED));
     806                 :       6466 :     }
     807                 :            : 
     808                 :       7663 :     return S2N_SUCCESS;
     809                 :       7663 : }
     810                 :            : 
     811                 :            : /*
     812                 :            :  * s2n-tls does NOT support SSLv2. However, it does support SSLv2 ClientHellos.
     813                 :            :  * Clients may send SSLv2 ClientHellos advertising higher protocol versions for
     814                 :            :  * backwards compatibility reasons. See https://tools.ietf.org/rfc/rfc2246 Appendix E.
     815                 :            :  *
     816                 :            :  * In this case, conn->client_hello.legacy_version and conn->client_protocol_version
     817                 :            :  * will be higher than SSLv2.
     818                 :            :  *
     819                 :            :  * See http://www-archive.mozilla.org/projects/security/pki/nss/ssl/draft02.html Section 2.5
     820                 :            :  * for a description of the expected SSLv2 format.
     821                 :            :  * Alternatively, the TLS1.0 RFC includes a more modern description of the format:
     822                 :            :  * https://tools.ietf.org/rfc/rfc2246 Appendix E.1
     823                 :            :  */
     824                 :            : int s2n_sslv2_client_hello_parse(struct s2n_connection *conn)
     825                 :          7 : {
     826                 :          7 :     struct s2n_client_hello *client_hello = &conn->client_hello;
     827                 :          7 :     conn->client_protocol_version = MIN(client_hello->legacy_version, S2N_TLS12);
     828                 :            : 
     829                 :          7 :     struct s2n_stuffer in_stuffer = { 0 };
     830         [ -  + ]:          7 :     POSIX_GUARD(s2n_stuffer_init(&in_stuffer, &client_hello->raw_message));
     831         [ -  + ]:          7 :     POSIX_GUARD(s2n_stuffer_skip_write(&in_stuffer, client_hello->raw_message.size));
     832                 :          7 :     struct s2n_stuffer *in = &in_stuffer;
     833                 :            : 
     834                 :            :     /* We start 5 bytes into the record */
     835                 :          7 :     uint16_t cipher_suites_length = 0;
     836         [ -  + ]:          7 :     POSIX_GUARD(s2n_stuffer_read_uint16(in, &cipher_suites_length));
     837 [ +  + ][ +  - ]:          7 :     POSIX_ENSURE(cipher_suites_length > 0, S2N_ERR_BAD_MESSAGE);
     838 [ #  # ][ -  + ]:          6 :     POSIX_ENSURE(cipher_suites_length % S2N_SSLv2_CIPHER_SUITE_LEN == 0, S2N_ERR_BAD_MESSAGE);
     839                 :            : 
     840                 :          6 :     uint16_t session_id_length = 0;
     841         [ -  + ]:          6 :     POSIX_GUARD(s2n_stuffer_read_uint16(in, &session_id_length));
     842                 :            : 
     843                 :          6 :     uint16_t challenge_length = 0;
     844         [ -  + ]:          6 :     POSIX_GUARD(s2n_stuffer_read_uint16(in, &challenge_length));
     845                 :            : 
     846 [ -  + ][ #  # ]:          6 :     S2N_ERROR_IF(challenge_length > S2N_TLS_RANDOM_DATA_LEN, S2N_ERR_BAD_MESSAGE);
     847                 :            : 
     848                 :          6 :     client_hello->cipher_suites.size = cipher_suites_length;
     849                 :          6 :     client_hello->cipher_suites.data = s2n_stuffer_raw_read(in, cipher_suites_length);
     850 [ -  + ][ #  # ]:          6 :     POSIX_ENSURE_REF(client_hello->cipher_suites.data);
     851                 :            : 
     852 [ -  + ][ #  # ]:          6 :     S2N_ERROR_IF(session_id_length > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE);
     853         [ -  + ]:          6 :     POSIX_GUARD(s2n_blob_init(&client_hello->session_id, s2n_stuffer_raw_read(in, session_id_length), session_id_length));
     854 [ -  + ][ #  # ]:          6 :     if (session_id_length > 0 && session_id_length <= S2N_TLS_SESSION_ID_MAX_LEN) {
     855 [ #  # ][ #  # ]:          0 :         POSIX_CHECKED_MEMCPY(conn->session_id, client_hello->session_id.data, session_id_length);
                 [ #  # ]
     856                 :          0 :         conn->session_id_len = (uint8_t) session_id_length;
     857                 :          0 :     }
     858                 :            : 
     859                 :          6 :     struct s2n_blob b = { 0 };
     860         [ -  + ]:          6 :     POSIX_GUARD(s2n_blob_init(&b, conn->handshake_params.client_random, S2N_TLS_RANDOM_DATA_LEN));
     861                 :            : 
     862                 :          6 :     b.data += S2N_TLS_RANDOM_DATA_LEN - challenge_length;
     863                 :          6 :     b.size -= S2N_TLS_RANDOM_DATA_LEN - challenge_length;
     864                 :            : 
     865         [ -  + ]:          6 :     POSIX_GUARD(s2n_stuffer_read(in, &b));
     866                 :            : 
     867                 :          6 :     return 0;
     868                 :          6 : }
     869                 :            : 
     870                 :            : int s2n_client_hello_get_parsed_extension(s2n_tls_extension_type extension_type,
     871                 :            :         s2n_parsed_extensions_list *parsed_extension_list, s2n_parsed_extension **parsed_extension)
     872                 :        745 : {
     873 [ -  + ][ #  # ]:        745 :     POSIX_ENSURE_REF(parsed_extension_list);
     874 [ #  # ][ -  + ]:        745 :     POSIX_ENSURE_REF(parsed_extension);
     875                 :            : 
     876                 :        745 :     s2n_extension_type_id extension_type_id = 0;
     877         [ -  + ]:        745 :     POSIX_GUARD(s2n_extension_supported_iana_value_to_id(extension_type, &extension_type_id));
     878                 :            : 
     879                 :        745 :     s2n_parsed_extension *found_parsed_extension = &parsed_extension_list->parsed_extensions[extension_type_id];
     880 [ +  - ][ +  + ]:        745 :     POSIX_ENSURE(found_parsed_extension->extension.data, S2N_ERR_EXTENSION_NOT_RECEIVED);
     881 [ +  + ][ +  - ]:        324 :     POSIX_ENSURE(found_parsed_extension->extension_type == extension_type, S2N_ERR_INVALID_PARSED_EXTENSIONS);
     882                 :            : 
     883                 :        323 :     *parsed_extension = found_parsed_extension;
     884                 :        323 :     return S2N_SUCCESS;
     885                 :        324 : }
     886                 :            : 
     887                 :            : ssize_t s2n_client_hello_get_extension_length(struct s2n_client_hello *ch, s2n_tls_extension_type extension_type)
     888                 :         41 : {
     889 [ +  - ][ +  + ]:         41 :     POSIX_ENSURE_REF(ch);
     890                 :            : 
     891                 :         39 :     s2n_parsed_extension *parsed_extension = NULL;
     892         [ +  + ]:         39 :     if (s2n_client_hello_get_parsed_extension(extension_type, &ch->extensions, &parsed_extension) != S2N_SUCCESS) {
     893                 :          2 :         return 0;
     894                 :          2 :     }
     895                 :            : 
     896                 :         37 :     return parsed_extension->extension.size;
     897                 :         39 : }
     898                 :            : 
     899                 :            : ssize_t s2n_client_hello_get_extension_by_id(struct s2n_client_hello *ch, s2n_tls_extension_type extension_type, uint8_t *out, uint32_t max_length)
     900                 :         42 : {
     901 [ +  + ][ +  - ]:         42 :     POSIX_ENSURE_REF(ch);
     902 [ -  + ][ #  # ]:         40 :     POSIX_ENSURE_REF(out);
     903                 :            : 
     904                 :         40 :     s2n_parsed_extension *parsed_extension = NULL;
     905         [ +  + ]:         40 :     if (s2n_client_hello_get_parsed_extension(extension_type, &ch->extensions, &parsed_extension) != S2N_SUCCESS) {
     906                 :          3 :         return 0;
     907                 :          3 :     }
     908                 :            : 
     909                 :         37 :     uint32_t len = min_size(&parsed_extension->extension, max_length);
     910 [ #  # ][ -  + ]:         37 :     POSIX_CHECKED_MEMCPY(out, parsed_extension->extension.data, len);
                 [ +  - ]
     911                 :         37 :     return len;
     912                 :         37 : }
     913                 :            : 
     914                 :            : int s2n_client_hello_get_session_id_length(struct s2n_client_hello *ch, uint32_t *out_length)
     915                 :          2 : {
     916 [ #  # ][ -  + ]:          2 :     POSIX_ENSURE_REF(ch);
     917 [ -  + ][ #  # ]:          2 :     POSIX_ENSURE_REF(out_length);
     918                 :          2 :     *out_length = ch->session_id.size;
     919                 :          2 :     return S2N_SUCCESS;
     920                 :          2 : }
     921                 :            : 
     922                 :            : int s2n_client_hello_get_session_id(struct s2n_client_hello *ch, uint8_t *out, uint32_t *out_length, uint32_t max_length)
     923                 :          1 : {
     924 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_REF(ch);
     925 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_REF(out);
     926 [ #  # ][ -  + ]:          1 :     POSIX_ENSURE_REF(out_length);
     927                 :            : 
     928                 :          1 :     uint32_t len = min_size(&ch->session_id, max_length);
     929 [ -  + ][ #  # ]:          1 :     POSIX_CHECKED_MEMCPY(out, ch->session_id.data, len);
                 [ +  - ]
     930                 :          1 :     *out_length = len;
     931                 :            : 
     932                 :          1 :     return S2N_SUCCESS;
     933                 :          1 : }
     934                 :            : 
     935                 :            : int s2n_client_hello_get_compression_methods_length(struct s2n_client_hello *ch, uint32_t *out_length)
     936                 :          4 : {
     937 [ +  + ][ +  - ]:          4 :     POSIX_ENSURE_REF(ch);
     938 [ +  - ][ +  + ]:          3 :     POSIX_ENSURE_REF(out_length);
     939                 :          2 :     *out_length = ch->compression_methods.size;
     940                 :          2 :     return S2N_SUCCESS;
     941                 :          3 : }
     942                 :            : 
     943                 :            : int s2n_client_hello_get_compression_methods(struct s2n_client_hello *ch, uint8_t *list, uint32_t list_length, uint32_t *out_length)
     944                 :          6 : {
     945 [ +  + ][ +  - ]:          6 :     POSIX_ENSURE_REF(ch);
     946 [ +  - ][ +  + ]:          5 :     POSIX_ENSURE_REF(list);
     947 [ +  - ][ +  + ]:          4 :     POSIX_ENSURE_REF(out_length);
     948                 :            : 
     949 [ +  + ][ +  - ]:          3 :     POSIX_ENSURE(list_length >= ch->compression_methods.size, S2N_ERR_INSUFFICIENT_MEM_SIZE);
     950 [ -  + ][ #  # ]:          2 :     POSIX_CHECKED_MEMCPY(list, ch->compression_methods.data, ch->compression_methods.size);
                 [ +  - ]
     951                 :          2 :     *out_length = ch->compression_methods.size;
     952                 :          2 :     return S2N_SUCCESS;
     953                 :          2 : }
     954                 :            : 
     955                 :            : int s2n_client_hello_get_legacy_protocol_version(struct s2n_client_hello *ch, uint8_t *out)
     956                 :          3 : {
     957 [ +  + ][ +  - ]:          3 :     POSIX_ENSURE_REF(ch);
     958 [ +  - ][ +  + ]:          2 :     POSIX_ENSURE_REF(out);
     959                 :          1 :     *out = ch->legacy_version;
     960                 :          1 :     return S2N_SUCCESS;
     961                 :          2 : }
     962                 :            : 
     963                 :            : int s2n_client_hello_get_legacy_record_version(struct s2n_client_hello *ch, uint8_t *out)
     964                 :          3 : {
     965 [ +  + ][ +  - ]:          3 :     POSIX_ENSURE_REF(ch);
     966 [ +  - ][ +  + ]:          2 :     POSIX_ENSURE_REF(out);
     967 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE(ch->record_version_recorded, S2N_ERR_INVALID_ARGUMENT);
     968                 :          1 :     *out = ch->legacy_record_version;
     969                 :          1 :     return S2N_SUCCESS;
     970                 :          1 : }
     971                 :            : 
     972                 :            : S2N_RESULT s2n_client_hello_get_raw_extension(uint16_t extension_iana,
     973                 :            :         struct s2n_blob *raw_extensions, struct s2n_blob *extension)
     974                 :          6 : {
     975 [ -  + ][ #  # ]:          6 :     RESULT_ENSURE_REF(raw_extensions);
     976 [ #  # ][ -  + ]:          6 :     RESULT_ENSURE_REF(extension);
     977                 :            : 
     978                 :          6 :     *extension = (struct s2n_blob){ 0 };
     979                 :            : 
     980                 :          6 :     struct s2n_stuffer raw_extensions_stuffer = { 0 };
     981         [ -  + ]:          6 :     RESULT_GUARD_POSIX(s2n_stuffer_init(&raw_extensions_stuffer, raw_extensions));
     982         [ -  + ]:          6 :     RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&raw_extensions_stuffer, raw_extensions->size));
     983                 :            : 
     984         [ +  + ]:         12 :     while (s2n_stuffer_data_available(&raw_extensions_stuffer) > 0) {
     985                 :         10 :         uint16_t extension_type = 0;
     986         [ -  + ]:         10 :         RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(&raw_extensions_stuffer, &extension_type));
     987                 :            : 
     988                 :         10 :         uint16_t extension_size = 0;
     989         [ -  + ]:         10 :         RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(&raw_extensions_stuffer, &extension_size));
     990                 :            : 
     991                 :         10 :         uint8_t *extension_data = s2n_stuffer_raw_read(&raw_extensions_stuffer, extension_size);
     992 [ -  + ][ #  # ]:         10 :         RESULT_ENSURE_REF(extension_data);
     993                 :            : 
     994         [ +  + ]:         10 :         if (extension_iana == extension_type) {
     995         [ -  + ]:          4 :             RESULT_GUARD_POSIX(s2n_blob_init(extension, extension_data, extension_size));
     996                 :          4 :             return S2N_RESULT_OK;
     997                 :          4 :         }
     998                 :         10 :     }
     999                 :          2 :     return S2N_RESULT_OK;
    1000                 :          6 : }
    1001                 :            : 
    1002                 :            : int s2n_client_hello_has_extension(struct s2n_client_hello *ch, uint16_t extension_iana, bool *exists)
    1003                 :        237 : {
    1004 [ +  + ][ +  - ]:        237 :     POSIX_ENSURE_REF(ch);
    1005 [ #  # ][ -  + ]:        236 :     POSIX_ENSURE_REF(exists);
    1006                 :            : 
    1007                 :        236 :     *exists = false;
    1008                 :            : 
    1009                 :        236 :     s2n_extension_type_id extension_type_id = s2n_unsupported_extension;
    1010         [ +  + ]:        236 :     if (s2n_extension_supported_iana_value_to_id(extension_iana, &extension_type_id) == S2N_SUCCESS) {
    1011                 :        233 :         s2n_parsed_extension *parsed_extension = NULL;
    1012         [ +  + ]:        233 :         if (s2n_client_hello_get_parsed_extension(extension_iana, &ch->extensions, &parsed_extension) == S2N_SUCCESS) {
    1013                 :         89 :             *exists = true;
    1014                 :         89 :         }
    1015                 :        233 :         return S2N_SUCCESS;
    1016                 :        233 :     }
    1017                 :            : 
    1018                 :          3 :     struct s2n_blob extension = { 0 };
    1019         [ -  + ]:          3 :     POSIX_GUARD_RESULT(s2n_client_hello_get_raw_extension(extension_iana, &ch->extensions.raw, &extension));
    1020         [ +  + ]:          3 :     if (extension.data != NULL) {
    1021                 :          2 :         *exists = true;
    1022                 :          2 :     }
    1023                 :          3 :     return S2N_SUCCESS;
    1024                 :          3 : }
    1025                 :            : 
    1026                 :            : int s2n_client_hello_get_supported_groups(struct s2n_client_hello *ch, uint16_t *groups,
    1027                 :            :         uint16_t groups_count_max, uint16_t *groups_count_out)
    1028                 :         34 : {
    1029 [ +  + ][ +  - ]:         34 :     POSIX_ENSURE_REF(groups_count_out);
    1030                 :         33 :     *groups_count_out = 0;
    1031 [ +  + ][ +  - ]:         33 :     POSIX_ENSURE_REF(ch);
    1032 [ +  + ][ +  - ]:         32 :     POSIX_ENSURE_REF(groups);
    1033                 :            : 
    1034                 :         31 :     s2n_parsed_extension *supported_groups_extension = NULL;
    1035         [ +  + ]:         31 :     POSIX_GUARD(s2n_client_hello_get_parsed_extension(S2N_EXTENSION_SUPPORTED_GROUPS, &ch->extensions, &supported_groups_extension));
    1036 [ -  + ][ #  # ]:         29 :     POSIX_ENSURE_REF(supported_groups_extension);
    1037                 :            : 
    1038                 :         29 :     struct s2n_stuffer extension_stuffer = { 0 };
    1039         [ -  + ]:         29 :     POSIX_GUARD(s2n_stuffer_init_written(&extension_stuffer, &supported_groups_extension->extension));
    1040                 :            : 
    1041                 :         29 :     uint16_t supported_groups_count = 0;
    1042         [ +  + ]:         29 :     POSIX_GUARD_RESULT(s2n_supported_groups_parse_count(&extension_stuffer, &supported_groups_count));
    1043 [ +  + ][ +  - ]:         27 :     POSIX_ENSURE(supported_groups_count <= groups_count_max, S2N_ERR_INSUFFICIENT_MEM_SIZE);
    1044                 :            : 
    1045         [ +  + ]:        199 :     for (size_t i = 0; i < supported_groups_count; i++) {
    1046                 :            :         /* s2n_stuffer_read_uint16 is used to read each of the supported groups in network-order
    1047                 :            :          * endianness.
    1048                 :            :          */
    1049         [ -  + ]:        173 :         POSIX_GUARD(s2n_stuffer_read_uint16(&extension_stuffer, &groups[i]));
    1050                 :        173 :     }
    1051                 :            : 
    1052                 :         26 :     *groups_count_out = supported_groups_count;
    1053                 :            : 
    1054                 :         26 :     return S2N_SUCCESS;
    1055                 :         26 : }
    1056                 :            : 
    1057                 :            : int s2n_client_hello_get_server_name_length(struct s2n_client_hello *ch, uint16_t *length)
    1058                 :          3 : {
    1059 [ +  + ][ +  - ]:          3 :     POSIX_ENSURE_REF(ch);
    1060 [ +  + ][ +  - ]:          2 :     POSIX_ENSURE_REF(length);
    1061                 :          1 :     *length = 0;
    1062                 :            : 
    1063                 :          1 :     s2n_parsed_extension *server_name_extension = NULL;
    1064         [ -  + ]:          1 :     POSIX_GUARD(s2n_client_hello_get_parsed_extension(S2N_EXTENSION_SERVER_NAME, &ch->extensions, &server_name_extension));
    1065 [ #  # ][ -  + ]:          1 :     POSIX_ENSURE_REF(server_name_extension);
    1066                 :            : 
    1067                 :          1 :     struct s2n_stuffer extension_stuffer = { 0 };
    1068         [ -  + ]:          1 :     POSIX_GUARD(s2n_stuffer_init_written(&extension_stuffer, &server_name_extension->extension));
    1069                 :            : 
    1070                 :          1 :     struct s2n_blob blob = { 0 };
    1071         [ -  + ]:          1 :     POSIX_GUARD_RESULT(s2n_client_server_name_parse(&extension_stuffer, &blob));
    1072                 :          1 :     *length = blob.size;
    1073                 :            : 
    1074                 :          1 :     return S2N_SUCCESS;
    1075                 :          1 : }
    1076                 :            : 
    1077                 :            : int s2n_client_hello_get_server_name(struct s2n_client_hello *ch, uint8_t *server_name, uint16_t length, uint16_t *out_length)
    1078                 :          5 : {
    1079 [ +  - ][ +  + ]:          5 :     POSIX_ENSURE_REF(out_length);
    1080 [ +  + ][ +  - ]:          4 :     POSIX_ENSURE_REF(ch);
    1081 [ +  - ][ +  + ]:          3 :     POSIX_ENSURE_REF(server_name);
    1082                 :          2 :     *out_length = 0;
    1083                 :            : 
    1084                 :          2 :     s2n_parsed_extension *server_name_extension = NULL;
    1085         [ -  + ]:          2 :     POSIX_GUARD(s2n_client_hello_get_parsed_extension(S2N_EXTENSION_SERVER_NAME, &ch->extensions, &server_name_extension));
    1086 [ #  # ][ -  + ]:          2 :     POSIX_ENSURE_REF(server_name_extension);
    1087                 :            : 
    1088                 :          2 :     struct s2n_stuffer extension_stuffer = { 0 };
    1089         [ -  + ]:          2 :     POSIX_GUARD(s2n_stuffer_init_written(&extension_stuffer, &server_name_extension->extension));
    1090                 :            : 
    1091                 :          2 :     struct s2n_blob blob = { 0 };
    1092         [ -  + ]:          2 :     POSIX_GUARD_RESULT(s2n_client_server_name_parse(&extension_stuffer, &blob));
    1093 [ +  + ][ +  - ]:          2 :     POSIX_ENSURE_LTE(blob.size, length);
    1094 [ -  + ][ #  # ]:          1 :     POSIX_CHECKED_MEMCPY(server_name, blob.data, blob.size);
                 [ +  - ]
    1095                 :            : 
    1096                 :          1 :     *out_length = blob.size;
    1097                 :            : 
    1098                 :          1 :     return S2N_SUCCESS;
    1099                 :          1 : }

Generated by: LCOV version 1.14