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

Generated by: LCOV version 1.14