LCOV - code coverage report
Current view: top level - tls - s2n_client_hello.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 610 618 98.7 %
Date: 2025-12-31 08:28:16 Functions: 39 39 100.0 %
Branches: 486 858 56.6 %

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

Generated by: LCOV version 1.14