LCOV - code coverage report
Current view: top level - tls/extensions - s2n_extension_list.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 102 102 100.0 %
Date: 2025-08-14 07:26:07 Functions: 7 7 100.0 %
Branches: 82 118 69.5 %

           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 "s2n_extension_list.h"
      17                 :            : 
      18                 :            : #include "api/s2n.h"
      19                 :            : #include "error/s2n_errno.h"
      20                 :            : #include "s2n_extension_type.h"
      21                 :            : #include "s2n_extension_type_lists.h"
      22                 :            : #include "utils/s2n_safety.h"
      23                 :            : 
      24                 :     213793 : #define s2n_parsed_extension_is_empty(parsed_extension) ((parsed_extension)->extension.data == NULL)
      25                 :            : 
      26                 :            : int s2n_extension_list_send(s2n_extension_list_id list_type, struct s2n_connection *conn, struct s2n_stuffer *out)
      27                 :      27066 : {
      28                 :      27066 :     s2n_extension_type_list *extension_type_list = NULL;
      29         [ +  + ]:      27066 :     POSIX_GUARD(s2n_extension_type_list_get(list_type, &extension_type_list));
      30                 :            : 
      31                 :      27065 :     struct s2n_stuffer_reservation total_extensions_size = { 0 };
      32         [ +  + ]:      27065 :     POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &total_extensions_size));
      33                 :            : 
      34         [ +  + ]:     242405 :     for (int i = 0; i < extension_type_list->count; i++) {
      35         [ +  + ]:     215346 :         POSIX_GUARD(s2n_extension_send(extension_type_list->extension_types[i], conn, out));
      36                 :     215346 :     }
      37                 :            : 
      38         [ -  + ]:      27059 :     POSIX_GUARD(s2n_stuffer_write_vector_size(&total_extensions_size));
      39                 :      27059 :     return S2N_SUCCESS;
      40                 :      27059 : }
      41                 :            : 
      42                 :            : int s2n_extension_list_recv(s2n_extension_list_id list_type, struct s2n_connection *conn, struct s2n_stuffer *in)
      43                 :       4717 : {
      44                 :       4717 :     s2n_parsed_extensions_list parsed_extension_list = { 0 };
      45         [ -  + ]:       4717 :     POSIX_GUARD(s2n_extension_list_parse(in, &parsed_extension_list));
      46         [ +  + ]:       4717 :     POSIX_GUARD(s2n_extension_list_process(list_type, conn, &parsed_extension_list));
      47                 :       4715 :     return S2N_SUCCESS;
      48                 :       4717 : }
      49                 :            : 
      50                 :            : static int s2n_extension_process_impl(const s2n_extension_type *extension_type,
      51                 :            :         struct s2n_connection *conn, s2n_parsed_extension *parsed_extension)
      52                 :     221118 : {
      53 [ -  + ][ #  # ]:     221118 :     POSIX_ENSURE_REF(extension_type);
      54 [ -  + ][ #  # ]:     221118 :     POSIX_ENSURE_REF(parsed_extension);
      55                 :            : 
      56         [ +  + ]:     221118 :     if (parsed_extension->processed) {
      57                 :       7325 :         return S2N_SUCCESS;
      58                 :       7325 :     }
      59                 :            : 
      60         [ +  + ]:     213793 :     if (s2n_parsed_extension_is_empty(parsed_extension)) {
      61         [ +  + ]:     155984 :         POSIX_GUARD(s2n_extension_is_missing(extension_type, conn));
      62                 :     155977 :         return S2N_SUCCESS;
      63                 :     155984 :     }
      64                 :            : 
      65 [ +  + ][ +  - ]:      57809 :     POSIX_ENSURE(parsed_extension->extension_type == extension_type->iana_value,
      66                 :      57808 :             S2N_ERR_INVALID_PARSED_EXTENSIONS);
      67                 :            : 
      68                 :      57808 :     struct s2n_stuffer extension_stuffer = { 0 };
      69         [ -  + ]:      57808 :     POSIX_GUARD(s2n_stuffer_init(&extension_stuffer, &parsed_extension->extension));
      70         [ -  + ]:      57808 :     POSIX_GUARD(s2n_stuffer_skip_write(&extension_stuffer, parsed_extension->extension.size));
      71                 :            : 
      72         [ +  + ]:      57808 :     POSIX_GUARD(s2n_extension_recv(extension_type, conn, &extension_stuffer));
      73                 :            : 
      74                 :      57796 :     return S2N_SUCCESS;
      75                 :      57808 : }
      76                 :            : 
      77                 :            : int s2n_extension_process(const s2n_extension_type *extension_type, struct s2n_connection *conn,
      78                 :            :         s2n_parsed_extensions_list *parsed_extension_list)
      79                 :     221120 : {
      80 [ +  + ][ +  - ]:     221120 :     POSIX_ENSURE_REF(parsed_extension_list);
      81 [ +  + ][ +  - ]:     221119 :     POSIX_ENSURE_REF(extension_type);
      82                 :            : 
      83                 :     221118 :     s2n_extension_type_id extension_id = 0;
      84         [ -  + ]:     221118 :     POSIX_GUARD(s2n_extension_supported_iana_value_to_id(extension_type->iana_value, &extension_id));
      85                 :            : 
      86                 :     221118 :     s2n_parsed_extension *parsed_extension = &parsed_extension_list->parsed_extensions[extension_id];
      87         [ +  + ]:     221118 :     POSIX_GUARD(s2n_extension_process_impl(extension_type, conn, parsed_extension));
      88                 :     221098 :     parsed_extension->processed = true;
      89                 :     221098 :     return S2N_SUCCESS;
      90                 :     221118 : }
      91                 :            : 
      92                 :            : int s2n_extension_list_process(s2n_extension_list_id list_type, struct s2n_connection *conn,
      93                 :            :         s2n_parsed_extensions_list *parsed_extension_list)
      94                 :      21506 : {
      95 [ +  + ][ +  - ]:      21506 :     POSIX_ENSURE_REF(parsed_extension_list);
      96                 :            : 
      97                 :      21505 :     s2n_extension_type_list *extension_type_list = NULL;
      98         [ +  + ]:      21505 :     POSIX_GUARD(s2n_extension_type_list_get(list_type, &extension_type_list));
      99                 :            : 
     100         [ +  + ]:     235288 :     for (int i = 0; i < extension_type_list->count; i++) {
     101         [ +  + ]:     213797 :         POSIX_GUARD(s2n_extension_process(extension_type_list->extension_types[i],
     102                 :     213797 :                 conn, parsed_extension_list));
     103                 :     213797 :     }
     104                 :            : 
     105                 :            :     /**
     106                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2
     107                 :            :      *= type=exception
     108                 :            :      *= reason=Incorrect implementations exist in the wild. Ignoring instead.
     109                 :            :      *# If an implementation receives an extension
     110                 :            :      *# which it recognizes and which is not specified for the message in
     111                 :            :      *# which it appears, it MUST abort the handshake with an
     112                 :            :      *# "illegal_parameter" alert.
     113                 :            :      *
     114                 :            :      * If we want to enforce this restriction in the future, we can verify
     115                 :            :      * that no parsed extensions exist without the "processed" flag set.
     116                 :            :      */
     117                 :            : 
     118                 :      21491 :     return S2N_SUCCESS;
     119                 :      21504 : }
     120                 :            : 
     121                 :            : static int s2n_extension_parse(struct s2n_stuffer *in, s2n_parsed_extension *parsed_extensions, uint16_t *wire_index)
     122                 :      58689 : {
     123 [ -  + ][ #  # ]:      58689 :     POSIX_ENSURE_REF(parsed_extensions);
     124 [ -  + ][ #  # ]:      58689 :     POSIX_ENSURE_REF(wire_index);
     125                 :            : 
     126                 :      58689 :     uint16_t extension_type = 0;
     127 [ +  + ][ +  - ]:      58689 :     POSIX_ENSURE(s2n_stuffer_read_uint16(in, &extension_type) == S2N_SUCCESS,
     128                 :      58688 :             S2N_ERR_BAD_MESSAGE);
     129                 :            : 
     130                 :      58688 :     uint16_t extension_size = 0;
     131 [ +  + ][ +  - ]:      58688 :     POSIX_ENSURE(s2n_stuffer_read_uint16(in, &extension_size) == S2N_SUCCESS,
     132                 :      58687 :             S2N_ERR_BAD_MESSAGE);
     133                 :            : 
     134                 :      58687 :     uint8_t *extension_data = s2n_stuffer_raw_read(in, extension_size);
     135 [ +  + ][ +  - ]:      58687 :     POSIX_ENSURE(extension_data != NULL, S2N_ERR_BAD_MESSAGE);
     136                 :            : 
     137                 :      58686 :     s2n_extension_type_id extension_id = 0;
     138         [ +  + ]:      58686 :     if (s2n_extension_supported_iana_value_to_id(extension_type, &extension_id) != S2N_SUCCESS) {
     139                 :            :         /* Ignore unknown extensions */
     140                 :        575 :         return S2N_SUCCESS;
     141                 :        575 :     }
     142                 :            : 
     143                 :      58111 :     s2n_parsed_extension *parsed_extension = &parsed_extensions[extension_id];
     144                 :            : 
     145                 :            :     /* Error if extension is a duplicate */
     146 [ +  - ][ +  + ]:      58111 :     POSIX_ENSURE(s2n_parsed_extension_is_empty(parsed_extension),
     147                 :      58108 :             S2N_ERR_DUPLICATE_EXTENSION);
     148                 :            : 
     149                 :            :     /* Fill in parsed extension */
     150                 :      58108 :     parsed_extension->extension_type = extension_type;
     151                 :      58108 :     parsed_extension->wire_index = *wire_index;
     152         [ -  + ]:      58108 :     POSIX_GUARD(s2n_blob_init(&parsed_extension->extension, extension_data, extension_size));
     153                 :      58108 :     (*wire_index)++;
     154                 :            : 
     155                 :      58108 :     return S2N_SUCCESS;
     156                 :      58108 : }
     157                 :            : 
     158                 :            : int s2n_extension_list_parse(struct s2n_stuffer *in, s2n_parsed_extensions_list *parsed_extension_list)
     159                 :      27044 : {
     160 [ +  + ][ +  - ]:      27044 :     POSIX_ENSURE_REF(in);
     161 [ +  - ][ +  + ]:      27043 :     POSIX_ENSURE_REF(parsed_extension_list);
     162                 :            : 
     163 [ -  + ][ #  # ]:      27042 :     POSIX_CHECKED_MEMSET((s2n_parsed_extension *) parsed_extension_list->parsed_extensions,
                 [ +  - ]
     164                 :      27042 :             0, sizeof(parsed_extension_list->parsed_extensions));
     165                 :            : 
     166                 :      27042 :     uint16_t total_extensions_size = 0;
     167         [ +  + ]:      27042 :     if (s2n_stuffer_read_uint16(in, &total_extensions_size) != S2N_SUCCESS) {
     168                 :        117 :         total_extensions_size = 0;
     169                 :        117 :     }
     170                 :            : 
     171                 :      27042 :     uint8_t *extensions_data = s2n_stuffer_raw_read(in, total_extensions_size);
     172 [ +  - ][ +  + ]:      27042 :     POSIX_ENSURE(extensions_data != NULL, S2N_ERR_BAD_MESSAGE);
     173                 :            : 
     174         [ -  + ]:      27041 :     POSIX_GUARD(s2n_blob_init(&parsed_extension_list->raw, extensions_data, total_extensions_size));
     175                 :            : 
     176                 :      27041 :     struct s2n_stuffer extensions_stuffer = { 0 };
     177         [ -  + ]:      27041 :     POSIX_GUARD(s2n_stuffer_init(&extensions_stuffer, &parsed_extension_list->raw));
     178         [ -  + ]:      27041 :     POSIX_GUARD(s2n_stuffer_skip_write(&extensions_stuffer, total_extensions_size));
     179                 :            : 
     180                 :      27041 :     uint16_t wire_index = 0;
     181         [ +  + ]:      85724 :     while (s2n_stuffer_data_available(&extensions_stuffer)) {
     182         [ +  + ]:      58689 :         POSIX_GUARD(s2n_extension_parse(&extensions_stuffer, parsed_extension_list->parsed_extensions, &wire_index));
     183                 :      58689 :     }
     184                 :            : 
     185                 :      27035 :     parsed_extension_list->count = wire_index;
     186                 :      27035 :     return S2N_SUCCESS;
     187                 :      27041 : }

Generated by: LCOV version 1.14