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 : }
|