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 <time.h>
17 : :
18 : : #include "api/s2n.h"
19 : : #include "crypto/s2n_fips.h"
20 : : #include "error/s2n_errno.h"
21 : : #include "stuffer/s2n_stuffer.h"
22 : : #include "tls/s2n_alerts.h"
23 : : #include "tls/s2n_cipher_preferences.h"
24 : : #include "tls/s2n_cipher_suites.h"
25 : : #include "tls/s2n_connection.h"
26 : : #include "tls/s2n_security_policies.h"
27 : : #include "tls/s2n_server_extensions.h"
28 : : #include "tls/s2n_tls.h"
29 : : #include "tls/s2n_tls13.h"
30 : : #include "tls/s2n_tls13_handshake.h"
31 : : #include "tls/s2n_tls13_key_schedule.h"
32 : : #include "utils/s2n_bitmap.h"
33 : : #include "utils/s2n_random.h"
34 : : #include "utils/s2n_safety.h"
35 : :
36 : : /* From RFC5246 7.4.1.2. */
37 : : #define S2N_TLS_COMPRESSION_METHOD_NULL 0
38 : :
39 : : /* From RFC8446 4.1.3. */
40 : 9830 : #define S2N_DOWNGRADE_PROTECTION_SIZE 8
41 : : const uint8_t tls12_downgrade_protection_bytes[] = {
42 : : 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x01
43 : : };
44 : :
45 : : const uint8_t tls11_downgrade_protection_bytes[] = {
46 : : 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x00
47 : : };
48 : :
49 : : static int s2n_random_value_is_hello_retry(struct s2n_connection *conn)
50 : 7561 : {
51 [ - + ][ # # ]: 7561 : POSIX_ENSURE_REF(conn);
52 : :
53 [ + - ][ + + ]: 7561 : POSIX_ENSURE(s2n_constant_time_equals(hello_retry_req_random, conn->handshake_params.server_random, S2N_TLS_RANDOM_DATA_LEN),
54 : 634 : S2N_ERR_INVALID_HELLO_RETRY);
55 : :
56 : 634 : return S2N_SUCCESS;
57 : 7561 : }
58 : :
59 : : static int s2n_client_detect_downgrade_mechanism(struct s2n_connection *conn)
60 : 2344 : {
61 [ - + ][ # # ]: 2344 : POSIX_ENSURE_REF(conn);
62 : 2344 : uint8_t *downgrade_bytes = &conn->handshake_params.server_random[S2N_TLS_RANDOM_DATA_LEN - S2N_DOWNGRADE_PROTECTION_SIZE];
63 : :
64 : : /* Detect downgrade attacks according to RFC 8446 section 4.1.3 */
65 [ + + ][ + + ]: 2344 : if (conn->client_protocol_version == S2N_TLS13 && conn->server_protocol_version == S2N_TLS12) {
66 [ + + ]: 315 : if (s2n_constant_time_equals(downgrade_bytes, tls12_downgrade_protection_bytes, S2N_DOWNGRADE_PROTECTION_SIZE)) {
67 [ + - ]: 2 : POSIX_BAIL(S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED);
68 : 2 : }
69 [ + + ][ + - ]: 2029 : } else if (conn->client_protocol_version == S2N_TLS13 && conn->server_protocol_version <= S2N_TLS11) {
70 [ + + ]: 250 : if (s2n_constant_time_equals(downgrade_bytes, tls11_downgrade_protection_bytes, S2N_DOWNGRADE_PROTECTION_SIZE)) {
71 [ + - ]: 1 : POSIX_BAIL(S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED);
72 : 1 : }
73 : 250 : }
74 : :
75 : 2341 : return 0;
76 : 2344 : }
77 : :
78 : : static int s2n_server_add_downgrade_mechanism(struct s2n_connection *conn)
79 : 6921 : {
80 [ # # ][ - + ]: 6921 : POSIX_ENSURE_REF(conn);
81 : 6921 : uint8_t *downgrade_bytes = &conn->handshake_params.server_random[S2N_TLS_RANDOM_DATA_LEN - S2N_DOWNGRADE_PROTECTION_SIZE];
82 : :
83 : : /* Protect against downgrade attacks according to RFC 8446 section 4.1.3 */
84 [ + + ][ + + ]: 6921 : if (conn->server_protocol_version >= S2N_TLS13 && conn->actual_protocol_version == S2N_TLS12) {
85 : : /* TLS1.3 servers MUST use a special random value when negotiating TLS1.2 */
86 [ # # ][ - + ]: 79 : POSIX_CHECKED_MEMCPY(downgrade_bytes, tls12_downgrade_protection_bytes, S2N_DOWNGRADE_PROTECTION_SIZE);
[ + - ]
87 [ + + ][ + + ]: 6842 : } else if (conn->server_protocol_version >= S2N_TLS13 && conn->actual_protocol_version <= S2N_TLS11) {
88 : : /* TLS1.3 servers MUST, use a special random value when negotiating TLS1.1 or below */
89 [ - + ][ # # ]: 5 : POSIX_CHECKED_MEMCPY(downgrade_bytes, tls11_downgrade_protection_bytes, S2N_DOWNGRADE_PROTECTION_SIZE);
[ + - ]
90 : 5 : }
91 : :
92 : 6921 : return 0;
93 : 6921 : }
94 : :
95 : : static int s2n_server_hello_parse(struct s2n_connection *conn)
96 : 7561 : {
97 [ # # ][ - + ]: 7561 : POSIX_ENSURE_REF(conn);
98 [ # # ][ - + ]: 7561 : POSIX_ENSURE_REF(conn->secure);
99 : :
100 : 7561 : struct s2n_stuffer *in = &conn->handshake.io;
101 : 7561 : uint8_t compression_method = 0;
102 : 7561 : uint8_t session_id_len = 0;
103 : 7561 : uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN];
104 : 7561 : uint8_t session_id[S2N_TLS_SESSION_ID_MAX_LEN];
105 : :
106 [ - + ]: 7561 : POSIX_GUARD(s2n_stuffer_read_bytes(in, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
107 [ - + ]: 7561 : POSIX_GUARD(s2n_stuffer_read_bytes(in, conn->handshake_params.server_random, S2N_TLS_RANDOM_DATA_LEN));
108 : :
109 : 7561 : uint8_t legacy_version = (uint8_t) (protocol_version[0] * 10) + protocol_version[1];
110 : :
111 : : /**
112 : : *= https://www.rfc-editor.org/rfc/rfc8446#4.1.3
113 : : *# Upon receiving a message with type server_hello, implementations MUST
114 : : *# first examine the Random value and, if it matches this value, process
115 : : *# it as described in Section 4.1.4).
116 : : **/
117 [ + + ]: 7561 : if (s2n_random_value_is_hello_retry(conn) == S2N_SUCCESS) {
118 : : /**
119 : : *= https://www.rfc-editor.org/rfc/rfc8446#4.1.4
120 : : *# If a client receives a second
121 : : *# HelloRetryRequest in the same connection (i.e., where the ClientHello
122 : : *# was itself in response to a HelloRetryRequest), it MUST abort the
123 : : *# handshake with an "unexpected_message" alert.
124 : : **/
125 [ - + ][ # # ]: 634 : POSIX_ENSURE(!s2n_is_hello_retry_handshake(conn), S2N_ERR_INVALID_HELLO_RETRY);
126 : :
127 : : /**
128 : : *= https://www.rfc-editor.org/rfc/rfc8446#4.1.4
129 : : *# Upon receipt of a HelloRetryRequest, the client MUST check the
130 : : *# legacy_version
131 : : **/
132 [ # # ][ - + ]: 634 : POSIX_ENSURE(legacy_version == S2N_TLS12, S2N_ERR_INVALID_HELLO_RETRY);
133 : :
134 [ - + ]: 634 : POSIX_GUARD(s2n_set_hello_retry_required(conn));
135 : 634 : }
136 : :
137 [ - + ]: 7561 : POSIX_GUARD(s2n_stuffer_read_uint8(in, &session_id_len));
138 [ - + ][ # # ]: 7561 : S2N_ERROR_IF(session_id_len > S2N_TLS_SESSION_ID_MAX_LEN, S2N_ERR_BAD_MESSAGE);
139 [ - + ]: 7561 : POSIX_GUARD(s2n_stuffer_read_bytes(in, session_id, session_id_len));
140 : :
141 : 7561 : uint8_t *cipher_suite_wire = s2n_stuffer_raw_read(in, S2N_TLS_CIPHER_SUITE_LEN);
142 [ - + ][ # # ]: 7561 : POSIX_ENSURE_REF(cipher_suite_wire);
143 : :
144 [ - + ]: 7561 : POSIX_GUARD(s2n_stuffer_read_uint8(in, &compression_method));
145 : :
146 : : /**
147 : : *= https://www.rfc-editor.org/rfc/rfc8446#4.1.3
148 : : *# legacy_compression_method: A single byte which MUST have the
149 : : *# value 0.
150 : : *
151 : : *= https://www.rfc-editor.org/rfc/rfc8446#4.1.4
152 : : *# Upon receipt of a HelloRetryRequest, the client MUST check the
153 : : *# legacy_version, legacy_session_id_echo, cipher_suite, and
154 : : *# legacy_compression_method
155 : : **/
156 [ - + ][ # # ]: 7561 : S2N_ERROR_IF(compression_method != S2N_TLS_COMPRESSION_METHOD_NULL, S2N_ERR_BAD_MESSAGE);
157 : :
158 [ + + ][ + + ]: 7561 : bool session_ids_match = session_id_len != 0 && session_id_len == conn->session_id_len
159 [ + + ]: 7561 : && s2n_constant_time_equals(session_id, conn->session_id, session_id_len);
160 [ + + ]: 7561 : if (!session_ids_match) {
161 : 2387 : conn->ems_negotiated = false;
162 : 2387 : }
163 : :
164 [ + + ]: 7561 : POSIX_GUARD(s2n_server_extensions_recv(conn, in));
165 : :
166 : : /**
167 : : *= https://www.rfc-editor.org/rfc/rfc8446#4.1.4
168 : : *# The server's extensions MUST contain "supported_versions".
169 : : **/
170 [ + + ]: 7560 : if (s2n_is_hello_retry_message(conn)) {
171 : 634 : s2n_extension_type_id supported_versions_id = s2n_unsupported_extension;
172 [ - + ]: 634 : POSIX_GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_SUPPORTED_VERSIONS, &supported_versions_id));
173 [ # # ][ - + ]: 634 : POSIX_ENSURE(S2N_CBIT_TEST(conn->extension_responses_received, supported_versions_id),
174 : 634 : S2N_ERR_MISSING_EXTENSION);
175 : 634 : }
176 : :
177 [ + + ]: 7560 : if (conn->server_protocol_version >= S2N_TLS13) {
178 [ - + ][ # # ]: 5216 : POSIX_ENSURE(!conn->handshake.renegotiation, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
179 : :
180 : : /**
181 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.3
182 : : *# A client which
183 : : *# receives a legacy_session_id_echo field that does not match what
184 : : *# it sent in the ClientHello MUST abort the handshake with an
185 : : *# "illegal_parameter" alert.
186 : : *
187 : : *= https://www.rfc-editor.org/rfc/rfc8446#4.1.4
188 : : *# Upon receipt of a HelloRetryRequest, the client MUST check the
189 : : *# legacy_version, legacy_session_id_echo
190 : : **/
191 [ + - ][ + + ]: 5216 : POSIX_ENSURE(session_ids_match || (session_id_len == 0 && conn->session_id_len == 0), S2N_ERR_BAD_MESSAGE);
[ + + ][ + - ]
192 : :
193 : 5151 : conn->actual_protocol_version = conn->server_protocol_version;
194 [ - + ]: 5151 : POSIX_GUARD(s2n_set_cipher_as_client(conn, cipher_suite_wire));
195 : :
196 : : /* Erase TLS 1.2 client session ticket which might have been set for session resumption */
197 [ - + ]: 5151 : POSIX_GUARD(s2n_free(&conn->client_ticket));
198 : 5151 : } else {
199 : 2344 : conn->server_protocol_version = legacy_version;
200 : :
201 [ + + ][ + - ]: 2344 : POSIX_ENSURE(!s2n_client_detect_downgrade_mechanism(conn), S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED);
202 [ + + ][ + - ]: 2341 : POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
203 : :
204 : : /* Hello retries are only supported in >=TLS1.3. */
205 [ - + ][ # # ]: 2340 : POSIX_ENSURE(!s2n_is_hello_retry_handshake(conn), S2N_ERR_BAD_MESSAGE);
206 : :
207 : : /*
208 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-D.3
209 : : *# A client that attempts to send 0-RTT data MUST fail a connection if
210 : : *# it receives a ServerHello with TLS 1.2 or older.
211 : : */
212 [ + + ][ + - ]: 2340 : POSIX_ENSURE(conn->early_data_state != S2N_EARLY_DATA_REQUESTED, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
213 : :
214 : 2338 : const struct s2n_security_policy *security_policy = NULL;
215 [ - + ]: 2338 : POSIX_GUARD(s2n_connection_get_security_policy(conn, &security_policy));
216 : :
217 [ - + ]: 2338 : if (conn->server_protocol_version < security_policy->minimum_protocol_version
218 [ - + ]: 2338 : || conn->server_protocol_version > conn->client_protocol_version) {
219 [ # # ]: 0 : POSIX_GUARD(s2n_queue_reader_unsupported_protocol_version_alert(conn));
220 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
221 : 0 : }
222 : :
223 [ + + ]: 2338 : conn->actual_protocol_version = S2N_MIN(conn->server_protocol_version, conn->client_protocol_version);
224 : :
225 : : /*
226 : : *= https://www.rfc-editor.org/rfc/rfc5077#section-3.4
227 : : *# If the server accepts the ticket
228 : : *# and the Session ID is not empty, then it MUST respond with the same
229 : : *# Session ID present in the ClientHello. This allows the client to
230 : : *# easily differentiate when the server is resuming a session from when
231 : : *# it is falling back to a full handshake.
232 : : */
233 [ + + ]: 2338 : if (session_ids_match) {
234 : : /* check if the resumed session state is valid */
235 [ + - ][ + + ]: 25 : POSIX_ENSURE(conn->resume_protocol_version == conn->actual_protocol_version, S2N_ERR_BAD_MESSAGE);
236 [ + + ][ + - ]: 23 : POSIX_ENSURE(s2n_constant_time_equals(conn->secure->cipher_suite->iana_value, cipher_suite_wire, S2N_TLS_CIPHER_SUITE_LEN),
237 : 22 : S2N_ERR_BAD_MESSAGE);
238 : :
239 : : /* Session is resumed */
240 : 22 : conn->client_session_resumed = 1;
241 : 2313 : } else {
242 : 2313 : conn->session_id_len = session_id_len;
243 [ - + ][ # # ]: 2313 : POSIX_CHECKED_MEMCPY(conn->session_id, session_id, session_id_len);
[ + + ]
244 [ + + ]: 2313 : POSIX_GUARD(s2n_set_cipher_as_client(conn, cipher_suite_wire));
245 : : /* Erase master secret which might have been set for session resumption */
246 [ - + ][ # # ]: 2312 : POSIX_CHECKED_MEMSET((uint8_t *) conn->secrets.version.tls12.master_secret, 0, S2N_TLS_SECRET_LEN);
[ + - ]
247 : :
248 : : /* Erase client session ticket which might have been set for session resumption */
249 [ - + ]: 2312 : POSIX_GUARD(s2n_free(&conn->client_ticket));
250 : 2312 : }
251 : 2338 : }
252 : :
253 : : /* If it is not possible to accept early data on this connection
254 : : * (for example, because no PSK was negotiated) we need to reject early data now.
255 : : * Otherwise, early data logic may make certain invalid assumptions about the
256 : : * state of the connection (for example, that the prf is the early data prf).
257 : : */
258 [ - + ]: 7485 : POSIX_GUARD_RESULT(s2n_early_data_accept_or_reject(conn));
259 [ + + ]: 7485 : if (conn->early_data_state == S2N_EARLY_DATA_REJECTED) {
260 [ - + ]: 914 : POSIX_GUARD_RESULT(s2n_tls13_key_schedule_reset(conn));
261 : 914 : }
262 : :
263 : 7485 : return 0;
264 : 7485 : }
265 : :
266 : : int s2n_server_hello_recv(struct s2n_connection *conn)
267 : 7610 : {
268 [ - + ][ # # ]: 7610 : POSIX_ENSURE_REF(conn);
269 : :
270 : : /* Read the message off the wire */
271 [ + + ]: 7610 : POSIX_GUARD(s2n_server_hello_parse(conn));
272 : :
273 : 7525 : conn->actual_protocol_version_established = 1;
274 : :
275 [ - + ]: 7525 : POSIX_GUARD(s2n_conn_set_handshake_type(conn));
276 : :
277 : : /* If this is a HelloRetryRequest, we don't process the ServerHello.
278 : : * Instead we proceed with retry logic. */
279 [ + + ]: 7525 : if (s2n_is_hello_retry_message(conn)) {
280 [ + + ]: 664 : POSIX_GUARD(s2n_server_hello_retry_recv(conn));
281 : 663 : return 0;
282 : 664 : }
283 : :
284 [ + + ][ + + ]: 6861 : if (conn->actual_protocol_version < S2N_TLS13 && s2n_connection_is_session_resumed(conn)) {
285 [ - + ]: 22 : POSIX_GUARD(s2n_prf_key_expansion(conn));
286 : 22 : }
287 : :
288 : : /* Update the required hashes for this connection */
289 [ - + ]: 6861 : POSIX_GUARD(s2n_conn_update_required_handshake_hashes(conn));
290 : :
291 : 6861 : return 0;
292 : 6861 : }
293 : :
294 : : int s2n_server_hello_write_message(struct s2n_connection *conn)
295 : 7607 : {
296 [ - + ][ # # ]: 7607 : POSIX_ENSURE_REF(conn);
297 [ # # ][ - + ]: 7607 : POSIX_ENSURE_REF(conn->secure);
298 : :
299 : : /* The actual_protocol_version is set while processing the CLIENT_HELLO message, so
300 : : * it could be S2N_TLS13. SERVER_HELLO should always respond with the legacy version.
301 : : * https://tools.ietf.org/html/rfc8446#section-4.1.3 */
302 [ + + ]: 7607 : const uint16_t legacy_protocol_version = S2N_MIN(conn->actual_protocol_version, S2N_TLS12);
303 : 7607 : uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN];
304 : 7607 : protocol_version[0] = (uint8_t) (legacy_protocol_version / 10);
305 : 7607 : protocol_version[1] = (uint8_t) (legacy_protocol_version % 10);
306 : :
307 [ - + ]: 7607 : POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
308 [ - + ]: 7607 : POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, conn->handshake_params.server_random, S2N_TLS_RANDOM_DATA_LEN));
309 [ - + ]: 7607 : POSIX_GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, conn->session_id_len));
310 [ - + ]: 7607 : POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, conn->session_id, conn->session_id_len));
311 [ - + ]: 7607 : POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, conn->secure->cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
312 [ - + ]: 7607 : POSIX_GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, S2N_TLS_COMPRESSION_METHOD_NULL));
313 : :
314 : 7607 : return 0;
315 : 7607 : }
316 : :
317 : : int s2n_server_hello_send(struct s2n_connection *conn)
318 : 6934 : {
319 [ - + ][ # # ]: 6934 : POSIX_ENSURE_REF(conn);
320 : :
321 : 6934 : struct s2n_stuffer server_random = { 0 };
322 : 6934 : struct s2n_blob b = { 0 };
323 [ - + ]: 6934 : POSIX_GUARD(s2n_blob_init(&b, conn->handshake_params.server_random, S2N_TLS_RANDOM_DATA_LEN));
324 : :
325 : : /* Create the server random data */
326 [ - + ]: 6934 : POSIX_GUARD(s2n_stuffer_init(&server_random, &b));
327 : :
328 : 6934 : struct s2n_blob rand_data = { 0 };
329 [ - + ]: 6934 : POSIX_GUARD(s2n_blob_init(&rand_data, s2n_stuffer_raw_write(&server_random, S2N_TLS_RANDOM_DATA_LEN), S2N_TLS_RANDOM_DATA_LEN));
330 [ - + ][ # # ]: 6934 : POSIX_ENSURE_REF(rand_data.data);
331 [ - + ]: 6934 : POSIX_GUARD_RESULT(s2n_get_public_random_data(&rand_data));
332 : :
333 : : /* Add a downgrade detection mechanism if required */
334 [ - + ]: 6934 : POSIX_GUARD(s2n_server_add_downgrade_mechanism(conn));
335 : :
336 [ - + ]: 6934 : POSIX_GUARD(s2n_server_hello_write_message(conn));
337 : :
338 [ - + ]: 6934 : POSIX_GUARD(s2n_server_extensions_send(conn, &conn->handshake.io));
339 : :
340 : 6934 : conn->actual_protocol_version_established = 1;
341 : :
342 : 6934 : return 0;
343 : 6934 : }
|