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 612 98.9 %
Date: 2025-08-15 07:28:39 Functions: 38 38 100.0 %
Branches: 475 842 56.4 %

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

Generated by: LCOV version 1.14