| /* | 
 |  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. | 
 |  * | 
 |  * Licensed under the OpenSSL license (the "License").  You may not use | 
 |  * this file except in compliance with the License.  You can obtain a copy | 
 |  * in the file LICENSE in the source distribution or at | 
 |  * https://www.openssl.org/source/license.html | 
 |  */ | 
 |  | 
 | #include <openssl/ssl.h> | 
 |  | 
 | #include <assert.h> | 
 | #include <string.h> | 
 |  | 
 | #include <openssl/bytestring.h> | 
 | #include <openssl/err.h> | 
 | #include <openssl/mem.h> | 
 |  | 
 | #include "../crypto/internal.h" | 
 | #include "internal.h" | 
 |  | 
 |  | 
 | BSSL_NAMESPACE_BEGIN | 
 |  | 
 | // kMaxEmptyRecords is the number of consecutive, empty records that will be | 
 | // processed. Without this limit an attacker could send empty records at a | 
 | // faster rate than we can process and cause record processing to loop | 
 | // forever. | 
 | static const uint8_t kMaxEmptyRecords = 32; | 
 |  | 
 | // kMaxEarlyDataSkipped is the maximum number of rejected early data bytes that | 
 | // will be skipped. Without this limit an attacker could send records at a | 
 | // faster rate than we can process and cause trial decryption to loop forever. | 
 | // This value should be slightly above kMaxEarlyDataAccepted, which is measured | 
 | // in plaintext. | 
 | static const size_t kMaxEarlyDataSkipped = 16384; | 
 |  | 
 | // kMaxWarningAlerts is the number of consecutive warning alerts that will be | 
 | // processed. | 
 | static const uint8_t kMaxWarningAlerts = 4; | 
 |  | 
 | // ssl_needs_record_splitting returns one if |ssl|'s current outgoing cipher | 
 | // state needs record-splitting and zero otherwise. | 
 | bool ssl_needs_record_splitting(const SSL *ssl) { | 
 | #if !defined(BORINGSSL_UNSAFE_FUZZER_MODE) | 
 |   return !ssl->s3->aead_write_ctx->is_null_cipher() && | 
 |          ssl_protocol_version(ssl) < TLS1_1_VERSION && | 
 |          (ssl->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0 && | 
 |          SSL_CIPHER_is_block_cipher(ssl->s3->aead_write_ctx->cipher()); | 
 | #else | 
 |   return false; | 
 | #endif | 
 | } | 
 |  | 
 | size_t ssl_record_prefix_len(const SSL *ssl) { | 
 |   assert(!SSL_is_dtls(ssl)); | 
 |   return SSL3_RT_HEADER_LENGTH + ssl->s3->aead_read_ctx->ExplicitNonceLen(); | 
 | } | 
 |  | 
 | static ssl_open_record_t skip_early_data(SSL *ssl, uint8_t *out_alert, | 
 |                                          size_t consumed) { | 
 |   ssl->s3->early_data_skipped += consumed; | 
 |   if (ssl->s3->early_data_skipped < consumed) { | 
 |     ssl->s3->early_data_skipped = kMaxEarlyDataSkipped + 1; | 
 |   } | 
 |  | 
 |   if (ssl->s3->early_data_skipped > kMaxEarlyDataSkipped) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MUCH_SKIPPED_EARLY_DATA); | 
 |     *out_alert = SSL_AD_UNEXPECTED_MESSAGE; | 
 |     return ssl_open_record_error; | 
 |   } | 
 |  | 
 |   return ssl_open_record_discard; | 
 | } | 
 |  | 
 | static uint16_t tls_record_version(const SSL *ssl) { | 
 |   if (ssl->s3->version == 0) { | 
 |     // Before the version is determined, outgoing records use TLS 1.0 for | 
 |     // historical compatibility requirements. | 
 |     return TLS1_VERSION; | 
 |   } | 
 |  | 
 |   // TLS 1.3 freezes the record version at TLS 1.2. Previous ones use the | 
 |   // version itself. | 
 |   return ssl_protocol_version(ssl) >= TLS1_3_VERSION ? TLS1_2_VERSION | 
 |                                                      : ssl->s3->version; | 
 | } | 
 |  | 
 | ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, | 
 |                                   Span<uint8_t> *out, size_t *out_consumed, | 
 |                                   uint8_t *out_alert, Span<uint8_t> in) { | 
 |   *out_consumed = 0; | 
 |   if (ssl->s3->read_shutdown == ssl_shutdown_close_notify) { | 
 |     return ssl_open_record_close_notify; | 
 |   } | 
 |  | 
 |   // If there is an unprocessed handshake message or we are already buffering | 
 |   // too much, stop before decrypting another handshake record. | 
 |   if (!tls_can_accept_handshake_data(ssl, out_alert)) { | 
 |     return ssl_open_record_error; | 
 |   } | 
 |  | 
 |   CBS cbs = CBS(in); | 
 |  | 
 |   // Decode the record header. | 
 |   uint8_t type; | 
 |   uint16_t version, ciphertext_len; | 
 |   if (!CBS_get_u8(&cbs, &type) ||      // | 
 |       !CBS_get_u16(&cbs, &version) ||  // | 
 |       !CBS_get_u16(&cbs, &ciphertext_len)) { | 
 |     *out_consumed = SSL3_RT_HEADER_LENGTH; | 
 |     return ssl_open_record_partial; | 
 |   } | 
 |  | 
 |   bool version_ok; | 
 |   if (ssl->s3->aead_read_ctx->is_null_cipher()) { | 
 |     // Only check the first byte. Enforcing beyond that can prevent decoding | 
 |     // version negotiation failure alerts. | 
 |     version_ok = (version >> 8) == SSL3_VERSION_MAJOR; | 
 |   } else { | 
 |     version_ok = version == tls_record_version(ssl); | 
 |   } | 
 |  | 
 |   if (!version_ok) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER); | 
 |     *out_alert = SSL_AD_PROTOCOL_VERSION; | 
 |     return ssl_open_record_error; | 
 |   } | 
 |  | 
 |   // Check the ciphertext length. | 
 |   if (ciphertext_len > SSL3_RT_MAX_ENCRYPTED_LENGTH) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_ENCRYPTED_LENGTH_TOO_LONG); | 
 |     *out_alert = SSL_AD_RECORD_OVERFLOW; | 
 |     return ssl_open_record_error; | 
 |   } | 
 |  | 
 |   // Extract the body. | 
 |   CBS body; | 
 |   if (!CBS_get_bytes(&cbs, &body, ciphertext_len)) { | 
 |     *out_consumed = SSL3_RT_HEADER_LENGTH + (size_t)ciphertext_len; | 
 |     return ssl_open_record_partial; | 
 |   } | 
 |  | 
 |   Span<const uint8_t> header = in.subspan(0, SSL3_RT_HEADER_LENGTH); | 
 |   ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, header); | 
 |  | 
 |   *out_consumed = in.size() - CBS_len(&cbs); | 
 |  | 
 |   // In TLS 1.3, during the handshake, skip ChangeCipherSpec records. | 
 |   static const uint8_t kChangeCipherSpec[] = {SSL3_MT_CCS}; | 
 |   if (ssl_has_final_version(ssl) && | 
 |       ssl_protocol_version(ssl) >= TLS1_3_VERSION && SSL_in_init(ssl) && | 
 |       type == SSL3_RT_CHANGE_CIPHER_SPEC && | 
 |       Span<const uint8_t>(body) == kChangeCipherSpec) { | 
 |     ssl->s3->empty_record_count++; | 
 |     if (ssl->s3->empty_record_count > kMaxEmptyRecords) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_EMPTY_FRAGMENTS); | 
 |       *out_alert = SSL_AD_UNEXPECTED_MESSAGE; | 
 |       return ssl_open_record_error; | 
 |     } | 
 |     return ssl_open_record_discard; | 
 |   } | 
 |  | 
 |   // Skip early data received when expecting a second ClientHello if we rejected | 
 |   // 0RTT. | 
 |   if (ssl->s3->skip_early_data &&                  // | 
 |       ssl->s3->aead_read_ctx->is_null_cipher() &&  // | 
 |       type == SSL3_RT_APPLICATION_DATA) { | 
 |     return skip_early_data(ssl, out_alert, *out_consumed); | 
 |   } | 
 |  | 
 |   // Ensure the sequence number update does not overflow. | 
 |   if (ssl->s3->read_sequence + 1 == 0) { | 
 |     OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); | 
 |     *out_alert = SSL_AD_INTERNAL_ERROR; | 
 |     return ssl_open_record_error; | 
 |   } | 
 |  | 
 |   // Decrypt the body in-place. | 
 |   if (!ssl->s3->aead_read_ctx->Open( | 
 |           out, type, version, ssl->s3->read_sequence, header, | 
 |           Span(const_cast<uint8_t *>(CBS_data(&body)), CBS_len(&body)))) { | 
 |     if (ssl->s3->skip_early_data && !ssl->s3->aead_read_ctx->is_null_cipher()) { | 
 |       ERR_clear_error(); | 
 |       return skip_early_data(ssl, out_alert, *out_consumed); | 
 |     } | 
 |  | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); | 
 |     *out_alert = SSL_AD_BAD_RECORD_MAC; | 
 |     return ssl_open_record_error; | 
 |   } | 
 |  | 
 |   ssl->s3->skip_early_data = false; | 
 |   ssl->s3->read_sequence++; | 
 |  | 
 |   // TLS 1.3 hides the record type inside the encrypted data. | 
 |   bool has_padding = !ssl->s3->aead_read_ctx->is_null_cipher() && | 
 |                      ssl_protocol_version(ssl) >= TLS1_3_VERSION; | 
 |  | 
 |   // If there is padding, the plaintext limit includes the padding, but includes | 
 |   // extra room for the inner content type. | 
 |   size_t plaintext_limit = | 
 |       has_padding ? SSL3_RT_MAX_PLAIN_LENGTH + 1 : SSL3_RT_MAX_PLAIN_LENGTH; | 
 |   if (out->size() > plaintext_limit) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG); | 
 |     *out_alert = SSL_AD_RECORD_OVERFLOW; | 
 |     return ssl_open_record_error; | 
 |   } | 
 |  | 
 |   if (has_padding) { | 
 |     // The outer record type is always application_data. | 
 |     if (type != SSL3_RT_APPLICATION_DATA) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_OUTER_RECORD_TYPE); | 
 |       *out_alert = SSL_AD_DECODE_ERROR; | 
 |       return ssl_open_record_error; | 
 |     } | 
 |  | 
 |     do { | 
 |       if (out->empty()) { | 
 |         OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); | 
 |         *out_alert = SSL_AD_DECRYPT_ERROR; | 
 |         return ssl_open_record_error; | 
 |       } | 
 |       type = out->back(); | 
 |       *out = out->subspan(0, out->size() - 1); | 
 |     } while (type == 0); | 
 |   } | 
 |  | 
 |   // Limit the number of consecutive empty records. | 
 |   if (out->empty()) { | 
 |     ssl->s3->empty_record_count++; | 
 |     if (ssl->s3->empty_record_count > kMaxEmptyRecords) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_EMPTY_FRAGMENTS); | 
 |       *out_alert = SSL_AD_UNEXPECTED_MESSAGE; | 
 |       return ssl_open_record_error; | 
 |     } | 
 |     // Apart from the limit, empty records are returned up to the caller. This | 
 |     // allows the caller to reject records of the wrong type. | 
 |   } else { | 
 |     ssl->s3->empty_record_count = 0; | 
 |   } | 
 |  | 
 |   if (type == SSL3_RT_ALERT) { | 
 |     return ssl_process_alert(ssl, out_alert, *out); | 
 |   } | 
 |  | 
 |   // Handshake messages may not interleave with any other record type. | 
 |   if (type != SSL3_RT_HANDSHAKE &&  // | 
 |       tls_has_unprocessed_handshake_data(ssl)) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); | 
 |     *out_alert = SSL_AD_UNEXPECTED_MESSAGE; | 
 |     return ssl_open_record_error; | 
 |   } | 
 |  | 
 |   ssl->s3->warning_alert_count = 0; | 
 |  | 
 |   *out_type = type; | 
 |   return ssl_open_record_success; | 
 | } | 
 |  | 
 | static bool do_seal_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out, | 
 |                            uint8_t *out_suffix, uint8_t type, const uint8_t *in, | 
 |                            const size_t in_len) { | 
 |   SSLAEADContext *aead = ssl->s3->aead_write_ctx.get(); | 
 |   uint8_t *extra_in = NULL; | 
 |   size_t extra_in_len = 0; | 
 |   if (!aead->is_null_cipher() && ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | 
 |     // TLS 1.3 hides the actual record type inside the encrypted data. | 
 |     extra_in = &type; | 
 |     extra_in_len = 1; | 
 |   } | 
 |  | 
 |   size_t suffix_len, ciphertext_len; | 
 |   if (!aead->SuffixLen(&suffix_len, in_len, extra_in_len) || | 
 |       !aead->CiphertextLen(&ciphertext_len, in_len, extra_in_len)) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE); | 
 |     return false; | 
 |   } | 
 |  | 
 |   assert(in == out || !buffers_alias(in, in_len, out, in_len)); | 
 |   assert(!buffers_alias(in, in_len, out_prefix, ssl_record_prefix_len(ssl))); | 
 |   assert(!buffers_alias(in, in_len, out_suffix, suffix_len)); | 
 |  | 
 |   if (extra_in_len) { | 
 |     out_prefix[0] = SSL3_RT_APPLICATION_DATA; | 
 |   } else { | 
 |     out_prefix[0] = type; | 
 |   } | 
 |  | 
 |   uint16_t record_version = tls_record_version(ssl); | 
 |   out_prefix[1] = record_version >> 8; | 
 |   out_prefix[2] = record_version & 0xff; | 
 |   out_prefix[3] = ciphertext_len >> 8; | 
 |   out_prefix[4] = ciphertext_len & 0xff; | 
 |   Span<const uint8_t> header = Span(out_prefix, SSL3_RT_HEADER_LENGTH); | 
 |  | 
 |   // Ensure the sequence number update does not overflow. | 
 |   if (ssl->s3->write_sequence + 1 == 0) { | 
 |     OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (!aead->SealScatter(out_prefix + SSL3_RT_HEADER_LENGTH, out, out_suffix, | 
 |                          out_prefix[0], record_version, ssl->s3->write_sequence, | 
 |                          header, in, in_len, extra_in, extra_in_len)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   ssl->s3->write_sequence++; | 
 |   ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, header); | 
 |   return true; | 
 | } | 
 |  | 
 | static size_t tls_seal_scatter_prefix_len(const SSL *ssl, uint8_t type, | 
 |                                           size_t in_len) { | 
 |   size_t ret = SSL3_RT_HEADER_LENGTH; | 
 |   if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 && | 
 |       ssl_needs_record_splitting(ssl)) { | 
 |     // In the case of record splitting, the 1-byte record (of the 1/n-1 split) | 
 |     // will be placed in the prefix, as will four of the five bytes of the | 
 |     // record header for the main record. The final byte will replace the first | 
 |     // byte of the plaintext that was used in the small record. | 
 |     ret += ssl_cipher_get_record_split_len(ssl->s3->aead_write_ctx->cipher()); | 
 |     ret += SSL3_RT_HEADER_LENGTH - 1; | 
 |   } else { | 
 |     ret += ssl->s3->aead_write_ctx->ExplicitNonceLen(); | 
 |   } | 
 |   return ret; | 
 | } | 
 |  | 
 | static bool tls_seal_scatter_suffix_len(const SSL *ssl, size_t *out_suffix_len, | 
 |                                         uint8_t type, size_t in_len) { | 
 |   size_t extra_in_len = 0; | 
 |   if (!ssl->s3->aead_write_ctx->is_null_cipher() && | 
 |       ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | 
 |     // TLS 1.3 adds an extra byte for encrypted record type. | 
 |     extra_in_len = 1; | 
 |   } | 
 |   // clang-format off | 
 |   if (type == SSL3_RT_APPLICATION_DATA && | 
 |       in_len > 1 && | 
 |       ssl_needs_record_splitting(ssl)) { | 
 |     // With record splitting enabled, the first byte gets sealed into a separate | 
 |     // record which is written into the prefix. | 
 |     in_len -= 1; | 
 |   } | 
 |   // clang-format on | 
 |   return ssl->s3->aead_write_ctx->SuffixLen(out_suffix_len, in_len, | 
 |                                             extra_in_len); | 
 | } | 
 |  | 
 | // tls_seal_scatter_record seals a new record of type |type| and body |in| and | 
 | // splits it between |out_prefix|, |out|, and |out_suffix|. Exactly | 
 | // |tls_seal_scatter_prefix_len| bytes are written to |out_prefix|, |in_len| | 
 | // bytes to |out|, and |tls_seal_scatter_suffix_len| bytes to |out_suffix|. It | 
 | // returns one on success and zero on error. If enabled, | 
 | // |tls_seal_scatter_record| implements TLS 1.0 CBC 1/n-1 record splitting and | 
 | // may write two records concatenated. | 
 | static bool tls_seal_scatter_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out, | 
 |                                     uint8_t *out_suffix, uint8_t type, | 
 |                                     const uint8_t *in, size_t in_len) { | 
 |   if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 && | 
 |       ssl_needs_record_splitting(ssl)) { | 
 |     assert(ssl->s3->aead_write_ctx->ExplicitNonceLen() == 0); | 
 |     const size_t prefix_len = SSL3_RT_HEADER_LENGTH; | 
 |  | 
 |     // Write the 1-byte fragment into |out_prefix|. | 
 |     uint8_t *split_body = out_prefix + prefix_len; | 
 |     uint8_t *split_suffix = split_body + 1; | 
 |  | 
 |     if (!do_seal_record(ssl, out_prefix, split_body, split_suffix, type, in, | 
 |                         1)) { | 
 |       return false; | 
 |     } | 
 |  | 
 |     size_t split_record_suffix_len; | 
 |     if (!ssl->s3->aead_write_ctx->SuffixLen(&split_record_suffix_len, 1, 0)) { | 
 |       assert(false); | 
 |       return false; | 
 |     } | 
 |     const size_t split_record_len = prefix_len + 1 + split_record_suffix_len; | 
 |     assert(SSL3_RT_HEADER_LENGTH + ssl_cipher_get_record_split_len( | 
 |                                        ssl->s3->aead_write_ctx->cipher()) == | 
 |            split_record_len); | 
 |  | 
 |     // Write the n-1-byte fragment. The header gets split between |out_prefix| | 
 |     // (header[:-1]) and |out| (header[-1:]). | 
 |     uint8_t tmp_prefix[SSL3_RT_HEADER_LENGTH]; | 
 |     if (!do_seal_record(ssl, tmp_prefix, out + 1, out_suffix, type, in + 1, | 
 |                         in_len - 1)) { | 
 |       return false; | 
 |     } | 
 |     assert(tls_seal_scatter_prefix_len(ssl, type, in_len) == | 
 |            split_record_len + SSL3_RT_HEADER_LENGTH - 1); | 
 |     OPENSSL_memcpy(out_prefix + split_record_len, tmp_prefix, | 
 |                    SSL3_RT_HEADER_LENGTH - 1); | 
 |     OPENSSL_memcpy(out, tmp_prefix + SSL3_RT_HEADER_LENGTH - 1, 1); | 
 |     return true; | 
 |   } | 
 |  | 
 |   return do_seal_record(ssl, out_prefix, out, out_suffix, type, in, in_len); | 
 | } | 
 |  | 
 | bool tls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, | 
 |                      size_t max_out_len, uint8_t type, const uint8_t *in, | 
 |                      size_t in_len) { | 
 |   if (buffers_alias(in, in_len, out, max_out_len)) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT); | 
 |     return false; | 
 |   } | 
 |  | 
 |   const size_t prefix_len = tls_seal_scatter_prefix_len(ssl, type, in_len); | 
 |   size_t suffix_len; | 
 |   if (!tls_seal_scatter_suffix_len(ssl, &suffix_len, type, in_len)) { | 
 |     return false; | 
 |   } | 
 |   if (in_len + prefix_len < in_len || | 
 |       prefix_len + in_len + suffix_len < prefix_len + in_len) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE); | 
 |     return false; | 
 |   } | 
 |   if (max_out_len < in_len + prefix_len + suffix_len) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); | 
 |     return false; | 
 |   } | 
 |  | 
 |   uint8_t *prefix = out; | 
 |   uint8_t *body = out + prefix_len; | 
 |   uint8_t *suffix = body + in_len; | 
 |   if (!tls_seal_scatter_record(ssl, prefix, body, suffix, type, in, in_len)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   *out_len = prefix_len + in_len + suffix_len; | 
 |   return true; | 
 | } | 
 |  | 
 | enum ssl_open_record_t ssl_process_alert(SSL *ssl, uint8_t *out_alert, | 
 |                                          Span<const uint8_t> in) { | 
 |   // Alerts records may not contain fragmented or multiple alerts. | 
 |   if (in.size() != 2) { | 
 |     *out_alert = SSL_AD_DECODE_ERROR; | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ALERT); | 
 |     return ssl_open_record_error; | 
 |   } | 
 |  | 
 |   ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_ALERT, in); | 
 |  | 
 |   const uint8_t alert_level = in[0]; | 
 |   const uint8_t alert_descr = in[1]; | 
 |  | 
 |   uint16_t alert = (alert_level << 8) | alert_descr; | 
 |   ssl_do_info_callback(ssl, SSL_CB_READ_ALERT, alert); | 
 |  | 
 |   if (alert_level == SSL3_AL_WARNING) { | 
 |     if (alert_descr == SSL_AD_CLOSE_NOTIFY) { | 
 |       ssl->s3->read_shutdown = ssl_shutdown_close_notify; | 
 |       return ssl_open_record_close_notify; | 
 |     } | 
 |  | 
 |     // Warning alerts do not exist in TLS 1.3, but RFC 8446 section 6.1 | 
 |     // continues to define user_canceled as a signal to cancel the handshake, | 
 |     // without specifying how to handle it. JDK11 misuses it to signal | 
 |     // full-duplex connection close after the handshake. As a workaround, skip | 
 |     // user_canceled as in TLS 1.2. This matches NSS and OpenSSL. | 
 |     if (ssl_has_final_version(ssl) && | 
 |         ssl_protocol_version(ssl) >= TLS1_3_VERSION && | 
 |         alert_descr != SSL_AD_USER_CANCELLED) { | 
 |       *out_alert = SSL_AD_DECODE_ERROR; | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ALERT); | 
 |       return ssl_open_record_error; | 
 |     } | 
 |  | 
 |     ssl->s3->warning_alert_count++; | 
 |     if (ssl->s3->warning_alert_count > kMaxWarningAlerts) { | 
 |       *out_alert = SSL_AD_UNEXPECTED_MESSAGE; | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_WARNING_ALERTS); | 
 |       return ssl_open_record_error; | 
 |     } | 
 |     return ssl_open_record_discard; | 
 |   } | 
 |  | 
 |   if (alert_level == SSL3_AL_FATAL) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_AD_REASON_OFFSET + alert_descr); | 
 |     ERR_add_error_dataf("SSL alert number %d", alert_descr); | 
 |     *out_alert = 0;  // No alert to send back to the peer. | 
 |     return ssl_open_record_error; | 
 |   } | 
 |  | 
 |   *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |   OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_ALERT_TYPE); | 
 |   return ssl_open_record_error; | 
 | } | 
 |  | 
 | BSSL_NAMESPACE_END | 
 |  | 
 | using namespace bssl; | 
 |  | 
 | size_t SSL_max_seal_overhead(const SSL *ssl) { | 
 |   if (SSL_is_dtls(ssl)) { | 
 |     // TODO(crbug.com/381113363): Use the 0-RTT epoch if writing 0-RTT. | 
 |     return dtls_max_seal_overhead(ssl, ssl->d1->write_epoch.epoch()); | 
 |   } | 
 |  | 
 |   size_t ret = SSL3_RT_HEADER_LENGTH; | 
 |   ret += ssl->s3->aead_write_ctx->MaxOverhead(); | 
 |   // TLS 1.3 needs an extra byte for the encrypted record type. | 
 |   if (!ssl->s3->aead_write_ctx->is_null_cipher() && | 
 |       ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | 
 |     ret += 1; | 
 |   } | 
 |   if (ssl_needs_record_splitting(ssl)) { | 
 |     ret *= 2; | 
 |   } | 
 |   return ret; | 
 | } |