LCOV - code coverage report
Current view: top level - tls - s2n_alerts.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 205 212 96.7 %
Date: 2025-08-15 07:28:39 Functions: 11 11 100.0 %
Branches: 304 400 76.0 %

           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 : }

Generated by: LCOV version 1.14