LCOV - code coverage report
Current view: top level - tls/extensions - s2n_npn.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 42 42 100.0 %
Date: 2025-08-14 07:26:07 Functions: 5 5 100.0 %
Branches: 28 48 58.3 %

           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_npn.h"
      17                 :            : 
      18                 :            : #include "tls/extensions/s2n_client_alpn.h"
      19                 :            : #include "tls/extensions/s2n_server_alpn.h"
      20                 :            : #include "tls/s2n_protocol_preferences.h"
      21                 :            : #include "tls/s2n_tls.h"
      22                 :            : #include "tls/s2n_tls_parameters.h"
      23                 :            : #include "utils/s2n_safety.h"
      24                 :            : 
      25                 :            : bool s2n_npn_should_send(struct s2n_connection *conn)
      26                 :       7369 : {
      27                 :            :     /*
      28                 :            :      *= https://datatracker.ietf.org/doc/id/draft-agl-tls-nextprotoneg-03#section-3
      29                 :            :      *# For the same reasons, after a handshake has been performed for a
      30                 :            :      *# given connection, renegotiations on the same connection MUST NOT
      31                 :            :      *# include the "next_protocol_negotiation" extension.
      32                 :            :      */
      33 [ +  + ][ +  + ]:       7369 :     return s2n_client_alpn_should_send(conn) && conn->config->npn_supported && !s2n_handshake_is_renegotiation(conn);
                 [ +  + ]
      34                 :       7369 : }
      35                 :            : 
      36                 :            : int s2n_client_npn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
      37                 :         11 : {
      38                 :            :     /* Only use the NPN extension to negotiate a protocol if we don't have
      39                 :            :      * an option to use the ALPN extension.
      40                 :            :      */
      41 [ +  + ][ +  + ]:         11 :     if (s2n_npn_should_send(conn) && !s2n_server_alpn_should_send(conn)) {
      42                 :          3 :         conn->npn_negotiated = true;
      43                 :          3 :     }
      44                 :            : 
      45                 :         11 :     return S2N_SUCCESS;
      46                 :         11 : }
      47                 :            : 
      48                 :            : const s2n_extension_type s2n_client_npn_extension = {
      49                 :            :     .iana_value = TLS_EXTENSION_NPN,
      50                 :            :     .is_response = false,
      51                 :            :     .send = s2n_extension_send_noop,
      52                 :            :     .recv = s2n_client_npn_recv,
      53                 :            :     .should_send = s2n_npn_should_send,
      54                 :            :     .if_missing = s2n_extension_noop_if_missing,
      55                 :            : };
      56                 :            : 
      57                 :            : bool s2n_server_npn_should_send(struct s2n_connection *conn)
      58                 :          6 : {
      59                 :          6 :     return conn->npn_negotiated;
      60                 :          6 : }
      61                 :            : 
      62                 :            : int s2n_server_npn_send(struct s2n_connection *conn, struct s2n_stuffer *out)
      63                 :          4 : {
      64                 :          4 :     struct s2n_blob *app_protocols = NULL;
      65         [ -  + ]:          4 :     POSIX_GUARD(s2n_connection_get_protocol_preferences(conn, &app_protocols));
      66 [ #  # ][ -  + ]:          4 :     POSIX_ENSURE_REF(app_protocols);
      67                 :            : 
      68         [ -  + ]:          4 :     POSIX_GUARD(s2n_stuffer_write(out, app_protocols));
      69                 :            : 
      70                 :          4 :     return S2N_SUCCESS;
      71                 :          4 : }
      72                 :            : 
      73                 :            : int s2n_server_npn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
      74                 :          7 : {
      75                 :          7 :     struct s2n_blob *supported_protocols = NULL;
      76         [ -  + ]:          7 :     POSIX_GUARD(s2n_connection_get_protocol_preferences(conn, &supported_protocols));
      77 [ -  + ][ #  # ]:          7 :     POSIX_ENSURE_REF(supported_protocols);
      78                 :            : 
      79         [ +  + ]:          7 :     if (supported_protocols->size == 0) {
      80                 :            :         /* No protocols configured */
      81                 :          1 :         return S2N_SUCCESS;
      82                 :          1 :     }
      83                 :            : 
      84                 :            :     /*
      85                 :            :      *= https://datatracker.ietf.org/doc/id/draft-agl-tls-nextprotoneg-03#section-3
      86                 :            :      *# The "extension_data" field of a "next_protocol_negotiation" extension
      87                 :            :      *# in a "ServerHello" contains an optional list of protocols advertised
      88                 :            :      *# by the server.
      89                 :            :      */
      90         [ +  + ]:          6 :     if (s2n_stuffer_data_available(extension)) {
      91         [ -  + ]:          5 :         POSIX_GUARD_RESULT(s2n_select_server_preference_protocol(conn, extension, supported_protocols));
      92                 :          5 :     }
      93                 :            : 
      94                 :            :     /*
      95                 :            :      *= https://datatracker.ietf.org/doc/id/draft-agl-tls-nextprotoneg-03#section-4
      96                 :            :      *# In the event that the client doesn't support any of server's protocols, or
      97                 :            :      *# the server doesn't advertise any, it SHOULD select the first protocol
      98                 :            :      *# that it supports.
      99                 :            :      */
     100         [ +  + ]:          6 :     if (s2n_get_application_protocol(conn) == NULL) {
     101                 :          3 :         struct s2n_stuffer stuffer = { 0 };
     102         [ -  + ]:          3 :         POSIX_GUARD(s2n_stuffer_init(&stuffer, supported_protocols));
     103         [ -  + ]:          3 :         POSIX_GUARD(s2n_stuffer_skip_write(&stuffer, supported_protocols->size));
     104                 :          3 :         struct s2n_blob protocol = { 0 };
     105         [ -  + ]:          3 :         POSIX_GUARD_RESULT(s2n_protocol_preferences_read(&stuffer, &protocol));
     106                 :            : 
     107 [ -  + ][ #  # ]:          3 :         POSIX_ENSURE_LT(protocol.size, sizeof(conn->application_protocol));
     108 [ -  + ][ #  # ]:          3 :         POSIX_CHECKED_MEMCPY(conn->application_protocol, protocol.data, protocol.size);
                 [ +  - ]
     109                 :          3 :         conn->application_protocol[protocol.size] = '\0';
     110                 :          3 :     }
     111                 :            : 
     112                 :          6 :     conn->npn_negotiated = true;
     113                 :            : 
     114                 :          6 :     return S2N_SUCCESS;
     115                 :          6 : }
     116                 :            : 
     117                 :            : const s2n_extension_type s2n_server_npn_extension = {
     118                 :            :     .iana_value = TLS_EXTENSION_NPN,
     119                 :            :     .is_response = true,
     120                 :            :     .send = s2n_server_npn_send,
     121                 :            :     .recv = s2n_server_npn_recv,
     122                 :            :     .should_send = s2n_server_npn_should_send,
     123                 :            :     .if_missing = s2n_extension_noop_if_missing,
     124                 :            : };

Generated by: LCOV version 1.14