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 : 26 : case (error): \
32 : 26 : *alert = (alert_code); \
33 : 26 : return S2N_RESULT_OK
34 : :
35 : : #define S2N_NO_ALERT(error) \
36 : 2 : case (error): \
37 : 63 : RESULT_BAIL(S2N_ERR_NO_ALERT)
38 : :
39 : : static S2N_RESULT s2n_translate_protocol_error_to_alert(int error_code, uint8_t *alert)
40 : 90 : {
41 [ # # ][ - + ]: 90 : RESULT_ENSURE_REF(alert);
42 : :
43 [ - + ]: 90 : 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 [ + + ]: 5 : 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 : :
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_CRL_LOOKUP_FAILED);
158 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_SIGNATURE);
159 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_ISSUER);
160 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_UNHANDLED_CRITICAL_EXTENSION);
161 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_INVALID_THIS_UPDATE);
162 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_INVALID_NEXT_UPDATE);
163 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_NOT_YET_VALID);
164 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CRL_EXPIRED);
165 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_INVALID_MAX_FRAG_LEN);
166 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_MAX_FRAG_LEN_MISMATCH);
167 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
168 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_BAD_KEY_SHARE);
169 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_CANCELLED);
170 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED);
171 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_MAX_INNER_PLAINTEXT_SIZE);
172 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_RECORD_STUFFER_SIZE);
173 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE);
174 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
175 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_RECORD_STUFFER_NEEDS_DRAINING);
176 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_UNSUPPORTED_EXTENSION);
177 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_DUPLICATE_EXTENSION);
178 [ + + ][ + - ]: 1 : S2N_NO_ALERT(S2N_ERR_MAX_EARLY_DATA_SIZE);
179 [ + + ][ + - ]: 90 : S2N_NO_ALERT(S2N_ERR_EARLY_DATA_TRIAL_DECRYPT);
180 : 90 : }
181 : :
182 [ # # ]: 0 : RESULT_BAIL(S2N_ERR_UNIMPLEMENTED);
183 : 0 : }
184 : :
185 : : static bool s2n_alerts_supported(struct s2n_connection *conn)
186 : 7638 : {
187 : : /* If running in QUIC mode, QUIC handles alerting.
188 : : * S2N should not send or receive alerts. */
189 : 7638 : return !s2n_connection_is_quic_enabled(conn);
190 : 7638 : }
191 : :
192 : : /* In TLS1.3 all Alerts
193 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6
194 : : *# MUST be treated as error alerts when received
195 : : *# regardless of the AlertLevel in the message.
196 : : */
197 : : static bool s2n_process_as_warning(struct s2n_connection *conn, uint8_t level, uint8_t type)
198 : 3022 : {
199 : : /* Only TLS1.2 considers the alert level. The alert level field is
200 : : * considered deprecated in TLS1.3. */
201 [ + + ]: 3022 : if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
202 [ + + ]: 13 : return level == S2N_TLS_ALERT_LEVEL_WARNING
203 [ + + ]: 13 : && conn->config->alert_behavior == S2N_ALERT_IGNORE_WARNINGS;
204 : 13 : }
205 : :
206 : : /* user_canceled is the only alert currently treated as a warning in TLS1.3.
207 : : * We need to treat it as a warning regardless of alert_behavior to avoid marking
208 : : * correctly-closed connections as failed. */
209 : 3009 : return type == S2N_TLS_ALERT_USER_CANCELED;
210 : 3022 : }
211 : :
212 : : int s2n_error_get_alert(int error, uint8_t *alert)
213 : 278 : {
214 : 278 : int error_type = s2n_error_get_type(error);
215 : :
216 [ - + ][ # # ]: 278 : POSIX_ENSURE_REF(alert);
217 : :
218 [ - + ]: 278 : switch (error_type) {
219 [ + + ]: 1 : case S2N_ERR_T_OK:
220 [ + + ]: 2 : case S2N_ERR_T_CLOSED:
221 [ + + ]: 6 : case S2N_ERR_T_BLOCKED:
222 [ + + ]: 96 : case S2N_ERR_T_USAGE:
223 [ + + ]: 97 : case S2N_ERR_T_ALERT:
224 [ + - ]: 97 : POSIX_BAIL(S2N_ERR_NO_ALERT);
225 : 0 : break;
226 [ + + ]: 90 : case S2N_ERR_T_PROTO:
227 [ + + ]: 90 : POSIX_GUARD_RESULT(s2n_translate_protocol_error_to_alert(error, alert));
228 : 26 : break;
229 [ + + ]: 26 : case S2N_ERR_T_IO:
230 [ + + ]: 91 : case S2N_ERR_T_INTERNAL:
231 : 91 : *alert = S2N_TLS_ALERT_INTERNAL_ERROR;
232 : 91 : break;
233 : 278 : }
234 : :
235 : 117 : return S2N_SUCCESS;
236 : 278 : }
237 : :
238 : : int s2n_process_alert_fragment(struct s2n_connection *conn)
239 : 5314 : {
240 [ + - ][ + + ]: 5314 : POSIX_ENSURE_REF(conn);
241 [ + + ][ + - ]: 5313 : S2N_ERROR_IF(s2n_stuffer_data_available(&conn->in) == 0, S2N_ERR_BAD_MESSAGE);
242 [ - + ][ # # ]: 5311 : S2N_ERROR_IF(s2n_stuffer_data_available(&conn->alert_in) == 2, S2N_ERR_ALERT_PRESENT);
243 [ + - ][ + + ]: 5311 : POSIX_ENSURE(s2n_alerts_supported(conn), S2N_ERR_BAD_MESSAGE);
244 : :
245 [ + + ]: 5312 : while (s2n_stuffer_data_available(&conn->in)) {
246 : 5310 : uint8_t bytes_required = 2;
247 : :
248 : : /* Alerts are two bytes long, but can still be fragmented or coalesced */
249 [ + + ]: 5310 : if (s2n_stuffer_data_available(&conn->alert_in) == 1) {
250 : 2 : bytes_required = 1;
251 : 2 : }
252 : :
253 : 5310 : int bytes_to_read = MIN(bytes_required, s2n_stuffer_data_available(&conn->in));
254 : :
255 [ - + ]: 5310 : POSIX_GUARD(s2n_stuffer_copy(&conn->in, &conn->alert_in, bytes_to_read));
256 : :
257 [ + + ]: 5310 : if (s2n_stuffer_data_available(&conn->alert_in) == 2) {
258 : : /* Close notifications are handled as shutdowns */
259 [ + + ]: 5308 : if (conn->alert_in_data[1] == S2N_TLS_ALERT_CLOSE_NOTIFY) {
260 : 2286 : s2n_atomic_flag_set(&conn->read_closed);
261 : 2286 : s2n_atomic_flag_set(&conn->close_notify_received);
262 : 2286 : return 0;
263 : 2286 : }
264 : :
265 : : /* Ignore warning-level alerts if we're in warning-tolerant mode */
266 [ + + ]: 3022 : if (s2n_process_as_warning(conn, conn->alert_in_data[0], conn->alert_in_data[1])) {
267 [ - + ]: 4 : POSIX_GUARD(s2n_stuffer_wipe(&conn->alert_in));
268 : 4 : return 0;
269 : 4 : }
270 : :
271 : : /* RFC 5077 5.1 - Expire any cached session on an error alert */
272 [ - + ][ # # ]: 3018 : if (s2n_allowed_to_cache_connection(conn) && conn->session_id_len) {
273 : 0 : conn->config->cache_delete(conn, conn->config->cache_delete_data, conn->session_id, conn->session_id_len);
274 : 0 : }
275 : :
276 : : /* All other alerts are treated as fatal errors.
277 : : *
278 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6
279 : : *# Unknown Alert types MUST be treated as error alerts.
280 : : */
281 [ - + ]: 3018 : POSIX_GUARD_RESULT(s2n_connection_set_closed(conn));
282 : 3018 : s2n_atomic_flag_set(&conn->error_alert_received);
283 [ + - ]: 3018 : POSIX_BAIL(S2N_ERR_ALERT);
284 : 3018 : }
285 : 5310 : }
286 : :
287 : 2 : return 0;
288 : 5310 : }
289 : :
290 : : static S2N_RESULT s2n_queue_reader_alert(struct s2n_connection *conn, s2n_tls_alert_code code)
291 : 24 : {
292 [ + + ][ + - ]: 24 : RESULT_ENSURE_REF(conn);
293 [ + + ]: 22 : if (!conn->reader_alert_out) {
294 : 21 : conn->reader_alert_out = code;
295 : 21 : }
296 : 22 : return S2N_RESULT_OK;
297 : 24 : }
298 : :
299 : : int s2n_queue_reader_unsupported_protocol_version_alert(struct s2n_connection *conn)
300 : 14 : {
301 [ + + ]: 14 : POSIX_GUARD_RESULT(s2n_queue_reader_alert(conn, S2N_TLS_ALERT_PROTOCOL_VERSION));
302 : 13 : return S2N_SUCCESS;
303 : 14 : }
304 : :
305 : : int s2n_queue_reader_handshake_failure_alert(struct s2n_connection *conn)
306 : 10 : {
307 [ + + ]: 10 : POSIX_GUARD_RESULT(s2n_queue_reader_alert(conn, S2N_TLS_ALERT_HANDSHAKE_FAILURE));
308 : 9 : return S2N_SUCCESS;
309 : 10 : }
310 : :
311 : : S2N_RESULT s2n_queue_reader_no_renegotiation_alert(struct s2n_connection *conn)
312 : 5 : {
313 : : /**
314 : : *= https://www.rfc-editor.org/rfc/rfc5746#4.5
315 : : *# SSLv3 does not define the "no_renegotiation" alert (and does
316 : : *# not offer a way to indicate a refusal to renegotiate at a "warning"
317 : : *# level). SSLv3 clients that refuse renegotiation SHOULD use a fatal
318 : : *# handshake_failure alert.
319 : : **/
320 [ + + ]: 5 : if (s2n_connection_get_protocol_version(conn) == S2N_SSLv3) {
321 [ - + ]: 1 : RESULT_GUARD_POSIX(s2n_queue_reader_handshake_failure_alert(conn));
322 [ + - ]: 1 : RESULT_BAIL(S2N_ERR_BAD_MESSAGE);
323 : 1 : }
324 : :
325 [ + - ]: 4 : if (!conn->reader_warning_out) {
326 : 4 : conn->reader_warning_out = S2N_TLS_ALERT_NO_RENEGOTIATION;
327 : 4 : }
328 : 4 : return S2N_RESULT_OK;
329 : 5 : }
330 : :
331 : : S2N_RESULT s2n_alerts_write_error_or_close_notify(struct s2n_connection *conn)
332 : 2323 : {
333 [ + + ]: 2323 : if (!s2n_alerts_supported(conn)) {
334 : 1 : return S2N_RESULT_OK;
335 : 1 : }
336 : :
337 : : /*
338 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6.2
339 : : *= type=exception
340 : : *= reason=Specific alerts could expose a side-channel attack vector.
341 : : *# The phrases "terminate the connection with an X
342 : : *# alert" and "abort the handshake with an X alert" mean that the
343 : : *# implementation MUST send alert X if it sends any alert.
344 : : *
345 : : * By default, s2n-tls sends a generic close_notify alert, even in
346 : : * response to fatal errors. This is done to avoid potential
347 : : * side-channel attacks since specific alerts could reveal information
348 : : * about why the error occured.
349 : : */
350 : 2322 : uint8_t code = S2N_TLS_ALERT_CLOSE_NOTIFY;
351 : 2322 : uint8_t level = S2N_TLS_ALERT_LEVEL_WARNING;
352 : :
353 : : /* s2n-tls sends a very small subset of more specific error alerts.
354 : : * Since either the reader or the writer can produce one of these alerts,
355 : : * but only a single alert can be reported, we prioritize writer alerts.
356 : : */
357 [ + + ]: 2322 : if (conn->writer_alert_out) {
358 : 1 : code = conn->writer_alert_out;
359 : 1 : level = S2N_TLS_ALERT_LEVEL_FATAL;
360 [ + + ]: 2321 : } else if (conn->reader_alert_out) {
361 : 7 : code = conn->reader_alert_out;
362 : 7 : level = S2N_TLS_ALERT_LEVEL_FATAL;
363 : 7 : }
364 : :
365 : 2322 : struct s2n_blob alert = { 0 };
366 : 2322 : uint8_t alert_bytes[] = { level, code };
367 [ - + ]: 2322 : RESULT_GUARD_POSIX(s2n_blob_init(&alert, alert_bytes, sizeof(alert_bytes)));
368 : :
369 [ - + ]: 2322 : RESULT_GUARD(s2n_record_write(conn, TLS_ALERT, &alert));
370 : 2322 : conn->alert_sent = true;
371 : 2322 : return S2N_RESULT_OK;
372 : 2322 : }
373 : :
374 : : S2N_RESULT s2n_alerts_write_warning(struct s2n_connection *conn)
375 : 4 : {
376 [ - + ]: 4 : if (!s2n_alerts_supported(conn)) {
377 : 0 : return S2N_RESULT_OK;
378 : 0 : }
379 : :
380 : 4 : uint8_t code = conn->reader_warning_out;
381 : 4 : uint8_t level = S2N_TLS_ALERT_LEVEL_WARNING;
382 : :
383 : 4 : struct s2n_blob alert = { 0 };
384 : 4 : uint8_t alert_bytes[] = { level, code };
385 [ - + ]: 4 : RESULT_GUARD_POSIX(s2n_blob_init(&alert, alert_bytes, sizeof(alert_bytes)));
386 : :
387 [ - + ]: 4 : RESULT_GUARD(s2n_record_write(conn, TLS_ALERT, &alert));
388 : 4 : return S2N_RESULT_OK;
389 : 4 : }
|