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/s2n_alerts.h"
17 : :
18 : : #include <stdint.h>
19 : : #include <sys/param.h>
20 : :
21 : : #include "error/s2n_errno.h"
22 : : #include "tls/s2n_connection.h"
23 : : #include "tls/s2n_record.h"
24 : : #include "tls/s2n_resume.h"
25 : : #include "tls/s2n_tls_parameters.h"
26 : : #include "utils/s2n_atomic.h"
27 : : #include "utils/s2n_blob.h"
28 : : #include "utils/s2n_safety.h"
29 : :
30 : : #define S2N_ALERT_CASE(error, alert_code) \
31 : 27 : case (error): \
32 : 27 : *alert = (alert_code); \
33 : 27 : return S2N_RESULT_OK
34 : :
35 : : #define S2N_NO_ALERT(error) \
36 : 2 : case (error): \
37 : 64 : RESULT_BAIL(S2N_ERR_NO_ALERT)
38 : :
39 : : static S2N_RESULT s2n_translate_protocol_error_to_alert(int error_code, uint8_t *alert)
40 : 92 : {
41 [ - + ][ # # ]: 92 : RESULT_ENSURE_REF(alert);
42 : :
43 [ - + ]: 92 : switch (error_code) {
44 [ + + ]: 3 : S2N_ALERT_CASE(S2N_ERR_MISSING_EXTENSION, S2N_TLS_ALERT_MISSING_EXTENSION);
45 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_NO_VALID_SIGNATURE_SCHEME, S2N_TLS_ALERT_HANDSHAKE_FAILURE);
46 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_MISSING_CLIENT_CERT, S2N_TLS_ALERT_CERTIFICATE_REQUIRED);
47 : :
48 : : /* TODO: The ERR_BAD_MESSAGE -> ALERT_UNEXPECTED_MESSAGE mapping
49 : : * isn't always correct. Sometimes s2n-tls uses ERR_BAD_MESSAGE
50 : : * to indicate S2N_TLS_ALERT_ILLEGAL_PARAMETER instead.
51 : : * We'll want to add a new error to distinguish between the two usages:
52 : : * our errors should be equally or more specific than alerts, not less.
53 : : */
54 [ + + ]: 3 : S2N_ALERT_CASE(S2N_ERR_BAD_MESSAGE, S2N_TLS_ALERT_UNEXPECTED_MESSAGE);
55 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_UNEXPECTED_CERT_REQUEST, S2N_TLS_ALERT_UNEXPECTED_MESSAGE);
56 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_MISSING_CERT_REQUEST, S2N_TLS_ALERT_UNEXPECTED_MESSAGE);
57 : :
58 : : /* For errors involving secure renegotiation:
59 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.4
60 : : *# Note: later in Section 3, "abort the handshake" is used as
61 : : *# shorthand for "send a fatal handshake_failure alert and
62 : : *# terminate the connection".
63 : : */
64 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_NO_RENEGOTIATION, S2N_TLS_ALERT_HANDSHAKE_FAILURE);
65 : :
66 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_KTLS_KEYUPDATE, S2N_TLS_ALERT_UNEXPECTED_MESSAGE);
67 : :
68 : : /* For errors involving certificates */
69 : :
70 : : /* This error is used in several ways so make it a general certificate issue
71 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6.2
72 : : *# certificate_unknown: Some other (unspecified) issue arose in
73 : : *# processing the certificate, rendering it unacceptable.
74 : : */
75 [ + + ]: 4 : S2N_ALERT_CASE(S2N_ERR_CERT_UNTRUSTED, S2N_TLS_ALERT_CERTIFICATE_UNKNOWN);
76 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_CERT_UNHANDLED_CRITICAL_EXTENSION, S2N_TLS_ALERT_CERTIFICATE_UNKNOWN);
77 [ + + ]: 2 : S2N_ALERT_CASE(S2N_ERR_CERT_INVALID_HOSTNAME, S2N_TLS_ALERT_CERTIFICATE_UNKNOWN);
78 : :
79 : : /*
80 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6.2
81 : : *# certificate_revoked: A certificate was revoked by its signer.
82 : : */
83 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_CERT_REVOKED, S2N_TLS_ALERT_CERTIFICATE_REVOKED);
84 : :
85 : : /*
86 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6.2
87 : : *# certificate_expired: A certificate has expired or is not currently
88 : : *# valid.
89 : : */
90 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_CERT_NOT_YET_VALID, S2N_TLS_ALERT_CERTIFICATE_EXPIRED);
91 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_CERT_EXPIRED, S2N_TLS_ALERT_CERTIFICATE_EXPIRED);
92 : :
93 : : /*
94 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6.2
95 : : *# unsupported_certificate: A certificate was of an unsupported type.
96 : : */
97 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_CERT_TYPE_UNSUPPORTED, S2N_TLS_ALERT_UNSUPPORTED_CERTIFICATE);
98 : :
99 : : /*
100 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6.2
101 : : *# access_denied: A valid certificate or PSK was received, but when
102 : : *# access control was applied, the sender decided not to proceed with
103 : : *# negotiation.
104 : : */
105 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_CERT_REJECTED, S2N_TLS_ALERT_ACCESS_DENIED);
106 : :
107 : : /*
108 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6.2
109 : : *# bad_certificate: A certificate was corrupt, contained signatures
110 : : *# that did not verify correctly, etc.
111 : : */
112 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_CERT_MAX_CHAIN_DEPTH_EXCEEDED, S2N_TLS_ALERT_BAD_CERTIFICATE);
113 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_CERT_INVALID, S2N_TLS_ALERT_BAD_CERTIFICATE);
114 [ + + ]: 1 : S2N_ALERT_CASE(S2N_ERR_DECODE_CERTIFICATE, S2N_TLS_ALERT_BAD_CERTIFICATE);
115 : :
116 : : /* TODO: Add mappings for other protocol errors.
117 : : */
118 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_ENCRYPT);
119 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_DECRYPT);
120 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_KEY_INIT);
121 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_KEY_DESTROY);
122 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_DH_SERIALIZING);
123 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_DH_SHARED_SECRET);
124 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_DH_WRITING_PUBLIC_KEY);
125 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_DH_FAILED_SIGNING);
126 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_DH_COPYING_PARAMETERS);
127 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_DH_GENERATING_PARAMETERS);
128 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CIPHER_NOT_SUPPORTED);
129 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_NO_APPLICATION_PROTOCOL);
130 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_FALLBACK_DETECTED);
131 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_HASH_DIGEST_FAILED);
132 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_HASH_INIT_FAILED);
133 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_HASH_UPDATE_FAILED);
134 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_HASH_COPY_FAILED);
135 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_HASH_WIPE_FAILED);
136 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_HASH_NOT_READY);
137 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_ALLOW_MD5_FOR_FIPS_FAILED);
138 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_DECODE_PRIVATE_KEY);
139 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_INVALID_HELLO_RETRY);
140 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_INVALID_SIGNATURE_ALGORITHM);
141 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_INVALID_SIGNATURE_SCHEME);
142 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CBC_VERIFY);
143 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_DH_COPYING_PUBLIC_KEY);
144 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_SIGN);
145 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_VERIFY_SIGNATURE);
146 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_ECDHE_GEN_KEY);
147 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_ECDHE_SHARED_SECRET);
148 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
149 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_ECDHE_INVALID_PUBLIC_KEY);
150 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_ECDHE_INVALID_PUBLIC_KEY_FIPS);
151 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_ECDSA_UNSUPPORTED_CURVE);
152 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_ECDHE_SERIALIZING);
153 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
154 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_SHUTDOWN_RECORD_TYPE);
155 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_SHUTDOWN_CLOSED);
156 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
157 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_RECORD_LIMIT);
158 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CERT_INTENT_INVALID);
159 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_LOOKUP_FAILED);
160 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_SIGNATURE);
161 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_ISSUER);
162 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_UNHANDLED_CRITICAL_EXTENSION);
163 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_INVALID_THIS_UPDATE);
164 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_INVALID_NEXT_UPDATE);
165 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_NOT_YET_VALID);
166 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_EXPIRED);
167 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_INVALID_MAX_FRAG_LEN);
168 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_MAX_FRAG_LEN_MISMATCH);
169 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
170 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_BAD_KEY_SHARE);
171 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CANCELLED);
172 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED);
173 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_MAX_INNER_PLAINTEXT_SIZE);
174 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_RECORD_STUFFER_SIZE);
175 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE);
176 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
177 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_RECORD_STUFFER_NEEDS_DRAINING);
178 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_UNSUPPORTED_EXTENSION);
179 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_DUPLICATE_EXTENSION);
180 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_MAX_EARLY_DATA_SIZE);
181 [ + + ][ + - ]: 92 : S2N_NO_ALERT(S2N_ERR_EARLY_DATA_TRIAL_DECRYPT);
182 : 92 : }
183 : :
184 [ # # ]: 0 : RESULT_BAIL(S2N_ERR_UNIMPLEMENTED);
185 : 0 : }
186 : :
187 : : static bool s2n_alerts_supported(struct s2n_connection *conn)
188 : 7640 : {
189 : : /* If running in QUIC mode, QUIC handles alerting.
190 : : * S2N should not send or receive alerts. */
191 : 7640 : return !s2n_connection_is_quic_enabled(conn);
192 : 7640 : }
193 : :
194 : : /* In TLS1.3 all Alerts
195 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6
196 : : *# MUST be treated as error alerts when received
197 : : *# regardless of the AlertLevel in the message.
198 : : */
199 : : static bool s2n_process_as_warning(struct s2n_connection *conn, uint8_t level, uint8_t type)
200 : 3024 : {
201 : : /* Only TLS1.2 considers the alert level. The alert level field is
202 : : * considered deprecated in TLS1.3. If the protocol version has not
203 : : * been negotiated yet, we allow for warnings to avoid premature
204 : : * handshake failures before we know the protocol version. */
205 [ + + ][ + + ]: 3024 : if (s2n_connection_get_protocol_version(conn) < S2N_TLS13 || !conn->actual_protocol_version_established) {
206 [ + + ]: 21 : return level == S2N_TLS_ALERT_LEVEL_WARNING
207 [ + + ]: 21 : && conn->config->alert_behavior == S2N_ALERT_IGNORE_WARNINGS;
208 : 21 : }
209 : :
210 : : /* user_canceled is the only alert currently treated as a warning in TLS1.3.
211 : : * We need to treat it as a warning regardless of alert_behavior to avoid marking
212 : : * correctly-closed connections as failed. */
213 : 3003 : return type == S2N_TLS_ALERT_USER_CANCELED;
214 : 3024 : }
215 : :
216 : : int s2n_error_get_alert(int error, uint8_t *alert)
217 : 279 : {
218 : 279 : int error_type = s2n_error_get_type(error);
219 : :
220 [ - + ][ # # ]: 279 : POSIX_ENSURE_REF(alert);
221 : :
222 [ - + ]: 279 : switch (error_type) {
223 [ + + ]: 1 : case S2N_ERR_T_OK:
224 [ + + ]: 2 : case S2N_ERR_T_CLOSED:
225 [ + + ]: 6 : case S2N_ERR_T_BLOCKED:
226 [ + + ]: 97 : case S2N_ERR_T_USAGE:
227 [ + + ]: 98 : case S2N_ERR_T_ALERT:
228 [ + - ]: 98 : POSIX_BAIL(S2N_ERR_NO_ALERT);
229 : 0 : break;
230 [ + + ]: 92 : case S2N_ERR_T_PROTO:
231 [ + + ]: 92 : POSIX_GUARD_RESULT(s2n_translate_protocol_error_to_alert(error, alert));
232 : 27 : break;
233 [ + + ]: 27 : case S2N_ERR_T_IO:
234 [ + + ]: 89 : case S2N_ERR_T_INTERNAL:
235 : 89 : *alert = S2N_TLS_ALERT_INTERNAL_ERROR;
236 : 89 : break;
237 : 279 : }
238 : :
239 : 116 : return S2N_SUCCESS;
240 : 279 : }
241 : :
242 : : int s2n_process_alert_fragment(struct s2n_connection *conn)
243 : 5316 : {
244 [ + - ][ + + ]: 5316 : POSIX_ENSURE_REF(conn);
245 [ + + ][ + - ]: 5315 : S2N_ERROR_IF(s2n_stuffer_data_available(&conn->in) == 0, S2N_ERR_BAD_MESSAGE);
246 [ - + ][ # # ]: 5313 : S2N_ERROR_IF(s2n_stuffer_data_available(&conn->alert_in) == 2, S2N_ERR_ALERT_PRESENT);
247 [ + - ][ + + ]: 5313 : POSIX_ENSURE(s2n_alerts_supported(conn), S2N_ERR_BAD_MESSAGE);
248 : :
249 [ + + ]: 5314 : while (s2n_stuffer_data_available(&conn->in)) {
250 : 5312 : uint8_t bytes_required = 2;
251 : :
252 : : /* Alerts are two bytes long, but can still be fragmented or coalesced */
253 [ + + ]: 5312 : if (s2n_stuffer_data_available(&conn->alert_in) == 1) {
254 : 2 : bytes_required = 1;
255 : 2 : }
256 : :
257 : 5312 : int bytes_to_read = MIN(bytes_required, s2n_stuffer_data_available(&conn->in));
258 : :
259 [ - + ]: 5312 : POSIX_GUARD(s2n_stuffer_copy(&conn->in, &conn->alert_in, bytes_to_read));
260 : :
261 [ + + ]: 5312 : if (s2n_stuffer_data_available(&conn->alert_in) == 2) {
262 : : /* Close notifications are handled as shutdowns */
263 [ + + ]: 5310 : if (conn->alert_in_data[1] == S2N_TLS_ALERT_CLOSE_NOTIFY) {
264 : 2286 : s2n_atomic_flag_set(&conn->read_closed);
265 : 2286 : s2n_atomic_flag_set(&conn->close_notify_received);
266 : 2286 : return 0;
267 : 2286 : }
268 : :
269 : : /* Ignore warning-level alerts if we're in warning-tolerant mode */
270 [ + + ]: 3024 : if (s2n_process_as_warning(conn, conn->alert_in_data[0], conn->alert_in_data[1])) {
271 [ - + ]: 6 : POSIX_GUARD(s2n_stuffer_wipe(&conn->alert_in));
272 : 6 : return 0;
273 : 6 : }
274 : :
275 : : /* RFC 5077 5.1 - Expire any cached session on an error alert */
276 [ - + ][ # # ]: 3018 : if (s2n_allowed_to_cache_connection(conn) && conn->session_id_len) {
277 : 0 : conn->config->cache_delete(conn, conn->config->cache_delete_data, conn->session_id, conn->session_id_len);
278 : 0 : }
279 : :
280 : : /* All other alerts are treated as fatal errors.
281 : : *
282 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6
283 : : *# Unknown Alert types MUST be treated as error alerts.
284 : : */
285 [ - + ]: 3018 : POSIX_GUARD_RESULT(s2n_connection_set_closed(conn));
286 : 3018 : s2n_atomic_flag_set(&conn->error_alert_received);
287 [ + - ]: 3018 : POSIX_BAIL(S2N_ERR_ALERT);
288 : 3018 : }
289 : 5312 : }
290 : :
291 : 2 : return 0;
292 : 5312 : }
293 : :
294 : : static S2N_RESULT s2n_queue_reader_alert(struct s2n_connection *conn, s2n_tls_alert_code code)
295 : 24 : {
296 [ + + ][ + - ]: 24 : RESULT_ENSURE_REF(conn);
297 [ + + ]: 22 : if (!conn->reader_alert_out) {
298 : 21 : conn->reader_alert_out = code;
299 : 21 : }
300 : 22 : return S2N_RESULT_OK;
301 : 24 : }
302 : :
303 : : int s2n_queue_reader_unsupported_protocol_version_alert(struct s2n_connection *conn)
304 : 14 : {
305 [ + + ]: 14 : POSIX_GUARD_RESULT(s2n_queue_reader_alert(conn, S2N_TLS_ALERT_PROTOCOL_VERSION));
306 : 13 : return S2N_SUCCESS;
307 : 14 : }
308 : :
309 : : int s2n_queue_reader_handshake_failure_alert(struct s2n_connection *conn)
310 : 10 : {
311 [ + + ]: 10 : POSIX_GUARD_RESULT(s2n_queue_reader_alert(conn, S2N_TLS_ALERT_HANDSHAKE_FAILURE));
312 : 9 : return S2N_SUCCESS;
313 : 10 : }
314 : :
315 : : S2N_RESULT s2n_queue_reader_no_renegotiation_alert(struct s2n_connection *conn)
316 : 5 : {
317 : : /**
318 : : *= https://www.rfc-editor.org/rfc/rfc5746#4.5
319 : : *# SSLv3 does not define the "no_renegotiation" alert (and does
320 : : *# not offer a way to indicate a refusal to renegotiate at a "warning"
321 : : *# level). SSLv3 clients that refuse renegotiation SHOULD use a fatal
322 : : *# handshake_failure alert.
323 : : **/
324 [ + + ]: 5 : if (s2n_connection_get_protocol_version(conn) == S2N_SSLv3) {
325 [ - + ]: 1 : RESULT_GUARD_POSIX(s2n_queue_reader_handshake_failure_alert(conn));
326 [ + - ]: 1 : RESULT_BAIL(S2N_ERR_BAD_MESSAGE);
327 : 1 : }
328 : :
329 [ + - ]: 4 : if (!conn->reader_warning_out) {
330 : 4 : conn->reader_warning_out = S2N_TLS_ALERT_NO_RENEGOTIATION;
331 : 4 : }
332 : 4 : return S2N_RESULT_OK;
333 : 5 : }
334 : :
335 : : S2N_RESULT s2n_alerts_write_error_or_close_notify(struct s2n_connection *conn)
336 : 2323 : {
337 [ + + ]: 2323 : if (!s2n_alerts_supported(conn)) {
338 : 1 : return S2N_RESULT_OK;
339 : 1 : }
340 : :
341 : : /*
342 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6.2
343 : : *= type=exception
344 : : *= reason=Specific alerts could expose a side-channel attack vector.
345 : : *# The phrases "terminate the connection with an X
346 : : *# alert" and "abort the handshake with an X alert" mean that the
347 : : *# implementation MUST send alert X if it sends any alert.
348 : : *
349 : : * By default, s2n-tls sends a generic close_notify alert, even in
350 : : * response to fatal errors. This is done to avoid potential
351 : : * side-channel attacks since specific alerts could reveal information
352 : : * about why the error occured.
353 : : */
354 : 2322 : uint8_t code = S2N_TLS_ALERT_CLOSE_NOTIFY;
355 : 2322 : uint8_t level = S2N_TLS_ALERT_LEVEL_WARNING;
356 : :
357 : : /* s2n-tls sends a very small subset of more specific error alerts.
358 : : * Since either the reader or the writer can produce one of these alerts,
359 : : * but only a single alert can be reported, we prioritize writer alerts.
360 : : */
361 [ + + ]: 2322 : if (conn->writer_alert_out) {
362 : 1 : code = conn->writer_alert_out;
363 : 1 : level = S2N_TLS_ALERT_LEVEL_FATAL;
364 [ + + ]: 2321 : } else if (conn->reader_alert_out) {
365 : 7 : code = conn->reader_alert_out;
366 : 7 : level = S2N_TLS_ALERT_LEVEL_FATAL;
367 : 7 : }
368 : :
369 : 2322 : struct s2n_blob alert = { 0 };
370 : 2322 : uint8_t alert_bytes[] = { level, code };
371 [ - + ]: 2322 : RESULT_GUARD_POSIX(s2n_blob_init(&alert, alert_bytes, sizeof(alert_bytes)));
372 : :
373 [ - + ]: 2322 : RESULT_GUARD(s2n_record_write(conn, TLS_ALERT, &alert));
374 : 2322 : conn->alert_sent = true;
375 : 2322 : return S2N_RESULT_OK;
376 : 2322 : }
377 : :
378 : : S2N_RESULT s2n_alerts_write_warning(struct s2n_connection *conn)
379 : 4 : {
380 [ - + ]: 4 : if (!s2n_alerts_supported(conn)) {
381 : 0 : return S2N_RESULT_OK;
382 : 0 : }
383 : :
384 : 4 : uint8_t code = conn->reader_warning_out;
385 : 4 : uint8_t level = S2N_TLS_ALERT_LEVEL_WARNING;
386 : :
387 : 4 : struct s2n_blob alert = { 0 };
388 : 4 : uint8_t alert_bytes[] = { level, code };
389 [ - + ]: 4 : RESULT_GUARD_POSIX(s2n_blob_init(&alert, alert_bytes, sizeof(alert_bytes)));
390 : :
391 [ - + ]: 4 : RESULT_GUARD(s2n_record_write(conn, TLS_ALERT, &alert));
392 : 4 : return S2N_RESULT_OK;
393 : 4 : }
|