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