LCOV - code coverage report
Current view: top level - tls - s2n_alerts.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 203 211 96.2 %
Date: 2026-10-06 07:26:09 Functions: 11 11 100.0 %
Branches: 310 406 76.4 %

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

Generated by: LCOV version 1.14