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