LCOV - code coverage report
Current view: top level - tls/extensions - s2n_client_renegotiation_info.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 55 55 100.0 %
Date: 2026-07-04 07:27:58 Functions: 6 6 100.0 %
Branches: 42 86 48.8 %

           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/extensions/s2n_client_renegotiation_info.h"
      17                 :            : 
      18                 :            : #include <stdint.h>
      19                 :            : 
      20                 :            : #include "tls/s2n_tls.h"
      21                 :            : #include "utils/s2n_safety.h"
      22                 :            : 
      23                 :            : static int s2n_client_renegotiation_send(struct s2n_connection *conn, struct s2n_stuffer *out);
      24                 :            : static int s2n_client_renegotiation_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
      25                 :            : static bool s2n_client_renegotiation_should_send(struct s2n_connection *conn);
      26                 :            : static int s2n_client_renegotiation_if_missing(struct s2n_connection *conn);
      27                 :            : 
      28                 :            : const s2n_extension_type s2n_client_renegotiation_info_extension = {
      29                 :            :     .iana_value = TLS_EXTENSION_RENEGOTIATION_INFO,
      30                 :            :     .is_response = false,
      31                 :            :     .send = s2n_client_renegotiation_send,
      32                 :            :     .recv = s2n_client_renegotiation_recv,
      33                 :            :     .should_send = s2n_client_renegotiation_should_send,
      34                 :            :     .if_missing = s2n_client_renegotiation_if_missing,
      35                 :            : };
      36                 :            : 
      37                 :            : /**
      38                 :            :  *= https://www.rfc-editor.org/rfc/rfc5746#3.5
      39                 :            :  *# o  The client MUST include the "renegotiation_info" extension in the
      40                 :            :  *#    ClientHello
      41                 :            :  */
      42                 :            : static bool s2n_client_renegotiation_should_send(struct s2n_connection *conn)
      43                 :       7723 : {
      44 [ +  - ][ +  + ]:       7723 :     return conn && s2n_handshake_is_renegotiation(conn);
      45                 :       7723 : }
      46                 :            : 
      47                 :            : /**
      48                 :            :  *= https://www.rfc-editor.org/rfc/rfc5746#3.5
      49                 :            :  *# o  The client MUST include the "renegotiation_info" extension in the
      50                 :            :  *#    ClientHello, containing the saved client_verify_data.
      51                 :            :  */
      52                 :            : static int s2n_client_renegotiation_send(struct s2n_connection *conn, struct s2n_stuffer *out)
      53                 :        263 : {
      54 [ -  + ][ #  # ]:        263 :     POSIX_ENSURE_REF(conn);
      55                 :            : 
      56                 :            :     /**
      57                 :            :      *= https://www.rfc-editor.org/rfc/rfc5746#3.5
      58                 :            :      *# This text applies if the connection's "secure_renegotiation" flag is
      59                 :            :      *# set to TRUE (if it is set to FALSE, see Section 4.2).
      60                 :            :      */
      61 [ +  + ][ +  - ]:        263 :     POSIX_ENSURE(conn->secure_renegotiation, S2N_ERR_NO_RENEGOTIATION);
      62                 :            : 
      63                 :        262 :     uint8_t renegotiated_connection_len = conn->handshake.finished_len;
      64 [ #  # ][ -  + ]:        262 :     POSIX_ENSURE_GT(renegotiated_connection_len, 0);
      65         [ -  + ]:        262 :     POSIX_GUARD(s2n_stuffer_write_uint8(out, renegotiated_connection_len));
      66         [ -  + ]:        262 :     POSIX_GUARD(s2n_stuffer_write_bytes(out, conn->handshake.client_finished, renegotiated_connection_len));
      67                 :            : 
      68                 :        262 :     return S2N_SUCCESS;
      69                 :        262 : }
      70                 :            : 
      71                 :            : /**
      72                 :            :  *= https://www.rfc-editor.org/rfc/rfc5746#3.6
      73                 :            :  *# o  The server MUST check if the "renegotiation_info" extension is
      74                 :            :  *# included in the ClientHello.
      75                 :            :  *
      76                 :            :  * Note that this extension must also work for SSLv3:
      77                 :            :  *= https://www.rfc-editor.org/rfc/rfc5746#4.5
      78                 :            :  *# TLS servers that support secure renegotiation and support SSLv3 MUST accept SCSV or the
      79                 :            :  *# "renegotiation_info" extension and respond as described in this
      80                 :            :  *# specification even if the offered client version is {0x03, 0x00}.
      81                 :            :  */
      82                 :            : static int s2n_client_renegotiation_recv_initial(struct s2n_connection *conn, struct s2n_stuffer *extension)
      83                 :         14 : {
      84                 :            :     /**
      85                 :            :      *= https://www.rfc-editor.org/rfc/rfc5746#3.6
      86                 :            :      *# The server MUST then verify
      87                 :            :      *# that the length of the "renegotiated_connection" field is zero,
      88                 :            :      *# and if it is not, MUST abort the handshake.
      89                 :            :      */
      90                 :         14 :     uint8_t renegotiated_connection_len = 0;
      91         [ -  + ]:         14 :     POSIX_GUARD(s2n_stuffer_read_uint8(extension, &renegotiated_connection_len));
      92 [ +  + ][ +  - ]:         14 :     POSIX_ENSURE(s2n_stuffer_data_available(extension) == 0, S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
      93 [ +  - ][ +  + ]:         12 :     POSIX_ENSURE(renegotiated_connection_len == 0, S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
      94                 :            : 
      95                 :            :     /**
      96                 :            :      *= https://www.rfc-editor.org/rfc/rfc5746#3.6
      97                 :            :      *# If the extension is present, set secure_renegotiation flag to TRUE.
      98                 :            :      */
      99                 :         11 :     conn->secure_renegotiation = 1;
     100                 :            : 
     101                 :         11 :     return S2N_SUCCESS;
     102                 :         12 : }
     103                 :            : 
     104                 :            : static int s2n_client_renegotiation_recv_renegotiation(struct s2n_connection *conn, struct s2n_stuffer *extension)
     105                 :        258 : {
     106 [ -  + ][ #  # ]:        258 :     POSIX_ENSURE_REF(conn);
     107                 :            : 
     108                 :            :     /* s2n-tls servers do not support renegotiation.
     109                 :            :      * We add the renegotiation version of this logic only for testing.
     110                 :            :      */
     111 [ #  # ][ -  + ]:        258 :     POSIX_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
     112                 :            : 
     113                 :            :     /**
     114                 :            :      *= https://www.rfc-editor.org/rfc/rfc5746#3.7
     115                 :            :      *# This text applies if the connection's "secure_renegotiation" flag is
     116                 :            :      *# set to TRUE (if it is set to FALSE, see Section 4.4).
     117                 :            :      */
     118 [ +  + ][ +  - ]:        258 :     POSIX_ENSURE(conn->secure_renegotiation, S2N_ERR_NO_RENEGOTIATION);
     119                 :            : 
     120                 :            :     /**
     121                 :            :      *= https://www.rfc-editor.org/rfc/rfc5746#3.7
     122                 :            :      *# o  The server MUST verify that the value of the
     123                 :            :      *#    "renegotiated_connection" field is equal to the saved
     124                 :            :      *#    client_verify_data value; if it is not, the server MUST abort the
     125                 :            :      *#    handshake.
     126                 :            :      */
     127                 :            : 
     128                 :        257 :     uint8_t verify_data_len = conn->handshake.finished_len;
     129 [ #  # ][ -  + ]:        257 :     POSIX_ENSURE_GT(verify_data_len, 0);
     130                 :            : 
     131                 :        257 :     uint8_t renegotiated_connection_len = 0;
     132         [ -  + ]:        257 :     POSIX_GUARD(s2n_stuffer_read_uint8(extension, &renegotiated_connection_len));
     133 [ +  + ][ +  - ]:        257 :     POSIX_ENSURE(verify_data_len == renegotiated_connection_len, S2N_ERR_BAD_MESSAGE);
     134                 :            : 
     135                 :        256 :     uint8_t *renegotiated_connection = s2n_stuffer_raw_read(extension, verify_data_len);
     136 [ #  # ][ -  + ]:        256 :     POSIX_ENSURE_REF(renegotiated_connection);
     137 [ -  + ][ #  # ]:        256 :     POSIX_ENSURE(s2n_constant_time_equals(renegotiated_connection, conn->handshake.client_finished, verify_data_len),
     138                 :        256 :             S2N_ERR_BAD_MESSAGE);
     139                 :            : 
     140                 :        256 :     return S2N_SUCCESS;
     141                 :        256 : }
     142                 :            : 
     143                 :            : static int s2n_client_renegotiation_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
     144                 :        272 : {
     145         [ +  + ]:        272 :     if (s2n_handshake_is_renegotiation(conn)) {
     146         [ +  + ]:        258 :         POSIX_GUARD(s2n_client_renegotiation_recv_renegotiation(conn, extension));
     147                 :        258 :     } else {
     148         [ +  + ]:         14 :         POSIX_GUARD(s2n_client_renegotiation_recv_initial(conn, extension));
     149                 :         14 :     }
     150 [ -  + ][ #  # ]:        267 :     POSIX_ENSURE(s2n_stuffer_data_available(extension) == 0, S2N_ERR_BAD_MESSAGE);
     151                 :        267 :     return S2N_SUCCESS;
     152                 :        267 : }
     153                 :            : 
     154                 :            : static int s2n_client_renegotiation_if_missing(struct s2n_connection *conn)
     155                 :       7474 : {
     156 [ -  + ][ #  # ]:       7474 :     POSIX_ENSURE_REF(conn);
     157         [ +  + ]:       7474 :     if (s2n_handshake_is_renegotiation(conn)) {
     158                 :            :         /* s2n-tls servers do not support renegotiation.
     159                 :            :          * We add the renegotiation version of this logic only for testing.
     160                 :            :          */
     161 [ #  # ][ -  + ]:          2 :         POSIX_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
     162                 :            : 
     163                 :            :         /**
     164                 :            :          *= https://www.rfc-editor.org/rfc/rfc5746#3.7
     165                 :            :          *# This text applies if the connection's "secure_renegotiation" flag is
     166                 :            :          *# set to TRUE (if it is set to FALSE, see Section 4.4).
     167                 :            :          */
     168 [ -  + ][ #  # ]:          2 :         POSIX_ENSURE(conn->secure_renegotiation, S2N_ERR_NO_RENEGOTIATION);
     169                 :            : 
     170                 :            :         /**
     171                 :            :          *= https://www.rfc-editor.org/rfc/rfc5746#3.7
     172                 :            :          *# o  The server MUST verify that the "renegotiation_info" extension is
     173                 :            :          *#     present; if it is not, the server MUST abort the handshake.
     174                 :            :          */
     175         [ +  - ]:          2 :         POSIX_BAIL(S2N_ERR_MISSING_EXTENSION);
     176                 :       7472 :     } else {
     177                 :            :         /**
     178                 :            :          *= https://www.rfc-editor.org/rfc/rfc5746#3.6
     179                 :            :          *# o  If neither the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV nor the
     180                 :            :          *#    "renegotiation_info" extension was included, set the
     181                 :            :          *#    secure_renegotiation flag to FALSE.  In this case, some servers
     182                 :            :          *#    may want to terminate the handshake instead of continuing
     183                 :            :          *
     184                 :            :          * We do not terminate the handshake for compatibility reasons.
     185                 :            :          * See https://github.com/aws/s2n-tls/issues/3528
     186                 :            :          */
     187                 :       7472 :         conn->secure_renegotiation = false;
     188                 :       7472 :         return S2N_SUCCESS;
     189                 :       7472 :     }
     190                 :       7474 : }

Generated by: LCOV version 1.14