LCOV - code coverage report
Current view: top level - tls - s2n_alerts.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 206 213 96.7 %
Date: 2025-12-31 08:28:16 Functions: 11 11 100.0 %
Branches: 309 406 76.1 %

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

Generated by: LCOV version 1.14