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_server_renegotiation_info.h"
17 : :
18 : : #include "error/s2n_errno.h"
19 : : #include "stuffer/s2n_stuffer.h"
20 : : #include "tls/s2n_connection.h"
21 : : #include "tls/s2n_tls.h"
22 : : #include "tls/s2n_tls_parameters.h"
23 : : #include "utils/s2n_safety.h"
24 : :
25 : : /**
26 : : * s2n-tls servers do NOT support renegotiation.
27 : : *
28 : : * We implement this extension to handle clients that require secure renegotiation support:
29 : : *= https://www.rfc-editor.org/rfc/rfc5746#4.3
30 : : *# In order to enable clients to probe, even servers that do not support
31 : : *# renegotiation MUST implement the minimal version of the extension
32 : : *# described in this document for initial handshakes, thus signaling
33 : : *# that they have been upgraded.
34 : : */
35 : :
36 : : static bool s2n_renegotiation_info_should_send(struct s2n_connection *conn);
37 : : static int s2n_renegotiation_info_send(struct s2n_connection *conn, struct s2n_stuffer *out);
38 : : static int s2n_renegotiation_info_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
39 : : static int s2n_renegotiation_info_if_missing(struct s2n_connection *conn);
40 : :
41 : : const s2n_extension_type s2n_server_renegotiation_info_extension = {
42 : : .iana_value = TLS_EXTENSION_RENEGOTIATION_INFO,
43 : : .send = s2n_renegotiation_info_send,
44 : : .recv = s2n_renegotiation_info_recv,
45 : : .should_send = s2n_renegotiation_info_should_send,
46 : : .if_missing = s2n_renegotiation_info_if_missing,
47 : :
48 : : /**
49 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.6
50 : : *# Note that sending a "renegotiation_info" extension in response to a
51 : : *# ClientHello containing only the SCSV is an explicit exception to the
52 : : *# prohibition in RFC 5246, Section 7.4.1.4, on the server sending
53 : : *# unsolicited extensions and is only allowed because the client is
54 : : *# signaling its willingness to receive the extension via the
55 : : *# TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV.
56 : : *
57 : : * This extension is technically a response extension, but doesn't
58 : : * follow any of the usual response extension rules.
59 : : * s2n-tls will therefore not treat it as a response extension.
60 : : */
61 : : .is_response = false,
62 : : };
63 : :
64 : : /**
65 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.6
66 : : *# o If the secure_renegotiation flag is set to TRUE, the server MUST
67 : : *# include an empty "renegotiation_info" extension in the ServerHello
68 : : *# message.
69 : : */
70 : : static bool s2n_renegotiation_info_should_send(struct s2n_connection *conn)
71 : 2377 : {
72 [ + - ][ + + ]: 2377 : return conn && conn->secure_renegotiation && s2n_connection_get_protocol_version(conn) < S2N_TLS13;
[ + + ]
73 : 2377 : }
74 : :
75 : : /**
76 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.6
77 : : *# o If the secure_renegotiation flag is set to TRUE, the server MUST
78 : : *# include an empty "renegotiation_info" extension in the ServerHello
79 : : *# message.
80 : : */
81 : : static int s2n_renegotiation_info_send_initial(struct s2n_connection *conn, struct s2n_stuffer *out)
82 : 2088 : {
83 [ - + ]: 2088 : POSIX_GUARD(s2n_stuffer_write_uint8(out, 0));
84 : 2088 : return S2N_SUCCESS;
85 : 2088 : }
86 : :
87 : : static int s2n_renegotiation_info_send_renegotiation(struct s2n_connection *conn, struct s2n_stuffer *out)
88 : 255 : {
89 [ # # ][ - + ]: 255 : POSIX_ENSURE_REF(conn);
90 : :
91 : : /* s2n-tls servers do not support renegotiation.
92 : : * We add the renegotiation version of this logic only for testing.
93 : : */
94 [ - + ][ # # ]: 255 : POSIX_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
95 : :
96 : : /**
97 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.7
98 : : *# This text applies if the connection's "secure_renegotiation" flag is
99 : : *# set to TRUE (if it is set to FALSE, see Section 4.4).
100 : : */
101 [ # # ][ - + ]: 255 : POSIX_ENSURE(conn->secure_renegotiation, S2N_ERR_NO_RENEGOTIATION);
102 : :
103 : : /**
104 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.7
105 : : *# o The server MUST include a "renegotiation_info" extension
106 : : *# containing the saved client_verify_data and server_verify_data in
107 : : *# the ServerHello.
108 : : */
109 : 255 : const uint8_t verify_data_len = conn->handshake.finished_len;
110 [ - + ][ # # ]: 255 : POSIX_ENSURE_GT(verify_data_len, 0);
111 [ - + ]: 255 : POSIX_GUARD(s2n_stuffer_write_uint8(out, verify_data_len * 2));
112 [ - + ]: 255 : POSIX_GUARD(s2n_stuffer_write_bytes(out, conn->handshake.client_finished, verify_data_len));
113 [ - + ]: 255 : POSIX_GUARD(s2n_stuffer_write_bytes(out, conn->handshake.server_finished, verify_data_len));
114 : :
115 : 255 : return S2N_SUCCESS;
116 : 255 : }
117 : :
118 : : static int s2n_renegotiation_info_send(struct s2n_connection *conn, struct s2n_stuffer *out)
119 : 2343 : {
120 [ + + ]: 2343 : if (s2n_handshake_is_renegotiation(conn)) {
121 [ - + ]: 255 : POSIX_GUARD(s2n_renegotiation_info_send_renegotiation(conn, out));
122 : 2088 : } else {
123 [ - + ]: 2088 : POSIX_GUARD(s2n_renegotiation_info_send_initial(conn, out));
124 : 2088 : }
125 : 2343 : return S2N_SUCCESS;
126 : 2343 : }
127 : :
128 : : /**
129 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.4
130 : : *# o When a ServerHello is received, the client MUST check if it
131 : : *# includes the "renegotiation_info" extension:
132 : : */
133 : : static int s2n_renegotiation_info_recv_initial(struct s2n_connection *conn, struct s2n_stuffer *extension)
134 : 2028 : {
135 [ - + ][ # # ]: 2028 : POSIX_ENSURE_REF(conn);
136 : :
137 : : /**
138 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.4
139 : : *# * The client MUST then verify that the length of the
140 : : *# "renegotiated_connection" field is zero, and if it is not, MUST
141 : : *# abort the handshake (by sending a fatal handshake_failure alert).
142 : : */
143 : 2028 : uint8_t renegotiated_connection_len = 0;
144 [ - + ]: 2028 : POSIX_GUARD(s2n_stuffer_read_uint8(extension, &renegotiated_connection_len));
145 [ + + ][ + - ]: 2028 : POSIX_ENSURE(s2n_stuffer_data_available(extension) == 0, S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
146 [ + - ][ + + ]: 2026 : POSIX_ENSURE(renegotiated_connection_len == 0, S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
147 : :
148 : : /**
149 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.4
150 : : *# * If the extension is present, set the secure_renegotiation flag to TRUE.
151 : : */
152 : 2025 : conn->secure_renegotiation = 1;
153 : 2025 : return S2N_SUCCESS;
154 : 2026 : }
155 : :
156 : : static int s2n_renegotiation_info_recv_renegotiation(struct s2n_connection *conn, struct s2n_stuffer *extension)
157 : 262 : {
158 [ # # ][ - + ]: 262 : POSIX_ENSURE_REF(conn);
159 : 262 : uint8_t verify_data_len = conn->handshake.finished_len;
160 [ # # ][ - + ]: 262 : POSIX_ENSURE_GT(verify_data_len, 0);
161 : :
162 : : /**
163 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.5
164 : : *# This text applies if the connection's "secure_renegotiation" flag is
165 : : *# set to TRUE (if it is set to FALSE, see Section 4.2).
166 : : */
167 [ + + ][ + - ]: 262 : POSIX_ENSURE(conn->secure_renegotiation, S2N_ERR_NO_RENEGOTIATION);
168 : :
169 : : /**
170 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.5
171 : : *# o The client MUST then verify that the first half of the
172 : : *# "renegotiated_connection" field is equal to the saved
173 : : *# client_verify_data value, and the second half is equal to the
174 : : *# saved server_verify_data value. If they are not, the client MUST
175 : : *# abort the handshake.
176 : : */
177 : :
178 : 261 : uint8_t renegotiated_connection_len = 0;
179 [ - + ]: 261 : POSIX_GUARD(s2n_stuffer_read_uint8(extension, &renegotiated_connection_len));
180 [ + + ][ + - ]: 261 : POSIX_ENSURE(verify_data_len * 2 == renegotiated_connection_len, S2N_ERR_BAD_MESSAGE);
181 : :
182 : 258 : uint8_t *first_half = s2n_stuffer_raw_read(extension, verify_data_len);
183 [ - + ][ # # ]: 258 : POSIX_ENSURE_REF(first_half);
184 [ + + ][ + - ]: 258 : POSIX_ENSURE(s2n_constant_time_equals(first_half, conn->handshake.client_finished, verify_data_len),
185 : 257 : S2N_ERR_BAD_MESSAGE);
186 : :
187 : 257 : uint8_t *second_half = s2n_stuffer_raw_read(extension, verify_data_len);
188 [ # # ][ - + ]: 257 : POSIX_ENSURE_REF(second_half);
189 [ + - ][ + + ]: 257 : POSIX_ENSURE(s2n_constant_time_equals(second_half, conn->handshake.server_finished, verify_data_len),
190 : 256 : S2N_ERR_BAD_MESSAGE);
191 : :
192 : 256 : return S2N_SUCCESS;
193 : 257 : }
194 : :
195 : : /**
196 : : * Note that this extension must also work for SSLv3:
197 : : *= https://www.rfc-editor.org/rfc/rfc5746#4.5
198 : : *# Clients that support SSLv3 and offer secure renegotiation (either via SCSV or
199 : : *# "renegotiation_info") MUST accept the "renegotiation_info" extension
200 : : *# from the server, even if the server version is {0x03, 0x00}, and
201 : : *# behave as described in this specification.
202 : : */
203 : : static int s2n_renegotiation_info_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
204 : 2290 : {
205 [ + + ]: 2290 : if (s2n_handshake_is_renegotiation(conn)) {
206 [ + + ]: 262 : POSIX_GUARD(s2n_renegotiation_info_recv_renegotiation(conn, extension));
207 : 2028 : } else {
208 [ + + ]: 2028 : POSIX_GUARD(s2n_renegotiation_info_recv_initial(conn, extension));
209 : 2028 : }
210 : 2281 : return S2N_SUCCESS;
211 : 2290 : }
212 : :
213 : : static int s2n_renegotiation_info_if_missing(struct s2n_connection *conn)
214 : 51 : {
215 [ - + ][ # # ]: 51 : POSIX_ENSURE_REF(conn);
216 [ + + ]: 51 : if (s2n_handshake_is_renegotiation(conn)) {
217 : : /**
218 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.5
219 : : *# o When a ServerHello is received, the client MUST verify that the
220 : : *# "renegotiation_info" extension is present; if it is not, the
221 : : *# client MUST abort the handshake.
222 : : */
223 [ + - ]: 1 : POSIX_BAIL(S2N_ERR_NO_RENEGOTIATION);
224 : 50 : } else {
225 : : /**
226 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.4
227 : : *# * If the extension is not present, the server does not support
228 : : *# secure renegotiation; set secure_renegotiation flag to FALSE.
229 : : *# In this case, some clients may want to terminate the handshake
230 : : *# instead of continuing; see Section 4.1 for discussion.
231 : : */
232 : 50 : conn->secure_renegotiation = false;
233 : :
234 : : /**
235 : : *= https://www.rfc-editor.org/rfc/rfc5746#4.1
236 : : *= type=exception
237 : : *= reason=Avoid interoperability problems
238 : : *# If clients wish to ensure that such attacks are impossible, they need
239 : : *# to terminate the connection immediately upon failure to receive the
240 : : *# extension without completing the handshake. Such clients MUST
241 : : *# generate a fatal "handshake_failure" alert prior to terminating the
242 : : *# connection. However, it is expected that many TLS servers that do
243 : : *# not support renegotiation (and thus are not vulnerable) will not
244 : : *# support this extension either, so in general, clients that implement
245 : : *# this behavior will encounter interoperability problems.
246 : : *
247 : : * TODO: https://github.com/aws/s2n-tls/issues/3528
248 : : */
249 : 50 : return S2N_SUCCESS;
250 : 50 : }
251 : 51 : }
252 : :
253 : : /* Old-style extension functions -- remove after extensions refactor is complete */
254 : :
255 : : int s2n_recv_server_renegotiation_info_ext(struct s2n_connection *conn, struct s2n_stuffer *extension)
256 : 0 : {
257 : 0 : return s2n_extension_recv(&s2n_server_renegotiation_info_extension, conn, extension);
258 : 0 : }
|