/* Copyright (c) 2016, Google Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#include <openssl/ssl.h>

#include <assert.h>
#include <string.h>

#include <utility>

#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/hkdf.h>
#include <openssl/mem.h>
#include <openssl/stack.h>
#include <openssl/x509.h>

#include "../crypto/internal.h"
#include "internal.h"


BSSL_NAMESPACE_BEGIN

// kMaxKeyUpdates is the number of consecutive KeyUpdates that will be
// processed. Without this limit an attacker could force unbounded processing
// without being able to return application data.
static const uint8_t kMaxKeyUpdates = 32;

const uint8_t kHelloRetryRequest[SSL3_RANDOM_SIZE] = {
    0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c,
    0x02, 0x1e, 0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb,
    0x8c, 0x5e, 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c,
};

// See RFC 8446, section 4.1.3.
const uint8_t kTLS12DowngradeRandom[8] = {0x44, 0x4f, 0x57, 0x4e,
                                          0x47, 0x52, 0x44, 0x00};
const uint8_t kTLS13DowngradeRandom[8] = {0x44, 0x4f, 0x57, 0x4e,
                                          0x47, 0x52, 0x44, 0x01};

// This is a non-standard randomly-generated value.
const uint8_t kJDK11DowngradeRandom[8] = {0xed, 0xbf, 0xb4, 0xa8,
                                          0xc2, 0x47, 0x10, 0xff};

bool tls13_get_cert_verify_signature_input(
    SSL_HANDSHAKE *hs, Array<uint8_t> *out,
    enum ssl_cert_verify_context_t cert_verify_context) {
  ScopedCBB cbb;
  if (!CBB_init(cbb.get(), 64 + 33 + 1 + 2 * EVP_MAX_MD_SIZE)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return false;
  }

  for (size_t i = 0; i < 64; i++) {
    if (!CBB_add_u8(cbb.get(), 0x20)) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
      return false;
    }
  }

  Span<const char> context;
  if (cert_verify_context == ssl_cert_verify_server) {
    static const char kContext[] = "TLS 1.3, server CertificateVerify";
    context = kContext;
  } else if (cert_verify_context == ssl_cert_verify_client) {
    static const char kContext[] = "TLS 1.3, client CertificateVerify";
    context = kContext;
  } else if (cert_verify_context == ssl_cert_verify_channel_id) {
    static const char kContext[] = "TLS 1.3, Channel ID";
    context = kContext;
  } else {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return false;
  }

  // Note |context| includes the NUL byte separator.
  if (!CBB_add_bytes(cbb.get(),
                     reinterpret_cast<const uint8_t *>(context.data()),
                     context.size())) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return false;
  }

  uint8_t context_hash[EVP_MAX_MD_SIZE];
  size_t context_hash_len;
  if (!hs->transcript.GetHash(context_hash, &context_hash_len) ||
      !CBB_add_bytes(cbb.get(), context_hash, context_hash_len) ||
      !CBBFinishArray(cbb.get(), out)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return false;
  }

  return true;
}

bool tls13_process_certificate(SSL_HANDSHAKE *hs, const SSLMessage &msg,
                               bool allow_anonymous) {
  SSL *const ssl = hs->ssl;
  CBS body = msg.body;
  bssl::UniquePtr<CRYPTO_BUFFER> decompressed;

  if (msg.type == SSL3_MT_COMPRESSED_CERTIFICATE) {
    CBS compressed;
    uint16_t alg_id;
    uint32_t uncompressed_len;

    if (!CBS_get_u16(&body, &alg_id) ||
        !CBS_get_u24(&body, &uncompressed_len) ||
        !CBS_get_u24_length_prefixed(&body, &compressed) ||
        CBS_len(&body) != 0) {
      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
      return false;
    }

    if (uncompressed_len > ssl->max_cert_list) {
      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
      OPENSSL_PUT_ERROR(SSL, SSL_R_UNCOMPRESSED_CERT_TOO_LARGE);
      ERR_add_error_dataf("requested=%u",
                          static_cast<unsigned>(uncompressed_len));
      return false;
    }

    ssl_cert_decompression_func_t decompress = nullptr;
    for (const auto* alg : ssl->ctx->cert_compression_algs.get()) {
      if (alg->alg_id == alg_id) {
        decompress = alg->decompress;
        break;
      }
    }

    if (decompress == nullptr) {
      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
      OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERT_COMPRESSION_ALG);
      ERR_add_error_dataf("alg=%d", static_cast<int>(alg_id));
      return false;
    }

    CRYPTO_BUFFER *decompressed_ptr = nullptr;
    if (!decompress(ssl, &decompressed_ptr, uncompressed_len,
                    CBS_data(&compressed), CBS_len(&compressed))) {
      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
      OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_DECOMPRESSION_FAILED);
      ERR_add_error_dataf("alg=%d", static_cast<int>(alg_id));
      return false;
    }
    decompressed.reset(decompressed_ptr);

    if (CRYPTO_BUFFER_len(decompressed_ptr) != uncompressed_len) {
      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
      OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_DECOMPRESSION_FAILED);
      ERR_add_error_dataf(
          "alg=%d got=%u expected=%u", static_cast<int>(alg_id),
          static_cast<unsigned>(CRYPTO_BUFFER_len(decompressed_ptr)),
          static_cast<unsigned>(uncompressed_len));
      return false;
    }

    CBS_init(&body, CRYPTO_BUFFER_data(decompressed_ptr),
             CRYPTO_BUFFER_len(decompressed_ptr));
  } else {
    assert(msg.type == SSL3_MT_CERTIFICATE);
  }

  CBS context, certificate_list;
  if (!CBS_get_u8_length_prefixed(&body, &context) ||
      CBS_len(&context) != 0 ||
      !CBS_get_u24_length_prefixed(&body, &certificate_list) ||
      CBS_len(&body) != 0) {
    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
    return false;
  }

  UniquePtr<STACK_OF(CRYPTO_BUFFER)> certs(sk_CRYPTO_BUFFER_new_null());
  if (!certs) {
    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return false;
  }

  const bool retain_sha256 =
      ssl->server && hs->config->retain_only_sha256_of_client_certs;
  UniquePtr<EVP_PKEY> pkey;
  while (CBS_len(&certificate_list) > 0) {
    CBS certificate, extensions;
    if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate) ||
        !CBS_get_u16_length_prefixed(&certificate_list, &extensions) ||
        CBS_len(&certificate) == 0) {
      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
      OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
      return false;
    }

    if (sk_CRYPTO_BUFFER_num(certs.get()) == 0) {
      pkey = ssl_cert_parse_pubkey(&certificate);
      if (!pkey) {
        ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
        OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
        return false;
      }
      // TLS 1.3 always uses certificate keys for signing thus the correct
      // keyUsage is enforced.
      if (!ssl_cert_check_digital_signature_key_usage(&certificate)) {
        ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
        return false;
      }

      if (retain_sha256) {
        // Retain the hash of the leaf certificate if requested.
        SHA256(CBS_data(&certificate), CBS_len(&certificate),
               hs->new_session->peer_sha256);
      }
    }

    UniquePtr<CRYPTO_BUFFER> buf(
        CRYPTO_BUFFER_new_from_CBS(&certificate, ssl->ctx->pool));
    if (!buf ||
        !PushToStack(certs.get(), std::move(buf))) {
      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
      return false;
    }

    // Parse out the extensions.
    bool have_status_request = false, have_sct = false;
    CBS status_request, sct;
    const SSL_EXTENSION_TYPE ext_types[] = {
        {TLSEXT_TYPE_status_request, &have_status_request, &status_request},
        {TLSEXT_TYPE_certificate_timestamp, &have_sct, &sct},
    };

    uint8_t alert = SSL_AD_DECODE_ERROR;
    if (!ssl_parse_extensions(&extensions, &alert, ext_types,
                              OPENSSL_ARRAY_SIZE(ext_types),
                              0 /* reject unknown */)) {
      ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
      return false;
    }

    // All Certificate extensions are parsed, but only the leaf extensions are
    // stored.
    if (have_status_request) {
      if (ssl->server || !hs->config->ocsp_stapling_enabled) {
        OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
        ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
        return false;
      }

      uint8_t status_type;
      CBS ocsp_response;
      if (!CBS_get_u8(&status_request, &status_type) ||
          status_type != TLSEXT_STATUSTYPE_ocsp ||
          !CBS_get_u24_length_prefixed(&status_request, &ocsp_response) ||
          CBS_len(&ocsp_response) == 0 ||
          CBS_len(&status_request) != 0) {
        ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
        return false;
      }

      if (sk_CRYPTO_BUFFER_num(certs.get()) == 1) {
        hs->new_session->ocsp_response.reset(
            CRYPTO_BUFFER_new_from_CBS(&ocsp_response, ssl->ctx->pool));
        if (hs->new_session->ocsp_response == nullptr) {
          ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
          return false;
        }
      }
    }

    if (have_sct) {
      if (ssl->server || !hs->config->signed_cert_timestamps_enabled) {
        OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
        ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
        return false;
      }

      if (!ssl_is_sct_list_valid(&sct)) {
        OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
        ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
        return false;
      }

      if (sk_CRYPTO_BUFFER_num(certs.get()) == 1) {
        hs->new_session->signed_cert_timestamp_list.reset(
            CRYPTO_BUFFER_new_from_CBS(&sct, ssl->ctx->pool));
        if (hs->new_session->signed_cert_timestamp_list == nullptr) {
          ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
          return false;
        }
      }
    }
  }

  // Store a null certificate list rather than an empty one if the peer didn't
  // send certificates.
  if (sk_CRYPTO_BUFFER_num(certs.get()) == 0) {
    certs.reset();
  }

  hs->peer_pubkey = std::move(pkey);
  hs->new_session->certs = std::move(certs);

  if (!ssl->ctx->x509_method->session_cache_objects(hs->new_session.get())) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    return false;
  }

  if (sk_CRYPTO_BUFFER_num(hs->new_session->certs.get()) == 0) {
    if (!allow_anonymous) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED);
      return false;
    }

    // OpenSSL returns X509_V_OK when no certificates are requested. This is
    // classed by them as a bug, but it's assumed by at least NGINX.
    hs->new_session->verify_result = X509_V_OK;

    // No certificate, so nothing more to do.
    return true;
  }

  hs->new_session->peer_sha256_valid = retain_sha256;
  return true;
}

bool tls13_process_certificate_verify(SSL_HANDSHAKE *hs, const SSLMessage &msg) {
  SSL *const ssl = hs->ssl;
  if (hs->peer_pubkey == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return false;
  }

  CBS body = msg.body, signature;
  uint16_t signature_algorithm;
  if (!CBS_get_u16(&body, &signature_algorithm) ||
      !CBS_get_u16_length_prefixed(&body, &signature) ||
      CBS_len(&body) != 0) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    return false;
  }

  uint8_t alert = SSL_AD_DECODE_ERROR;
  if (!tls12_check_peer_sigalg(ssl, &alert, signature_algorithm)) {
    ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
    return false;
  }
  hs->new_session->peer_signature_algorithm = signature_algorithm;

  Array<uint8_t> input;
  if (!tls13_get_cert_verify_signature_input(
          hs, &input,
          ssl->server ? ssl_cert_verify_client : ssl_cert_verify_server)) {
    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
    return false;
  }

  bool sig_ok = ssl_public_key_verify(ssl, signature, signature_algorithm,
                                      hs->peer_pubkey.get(), input);
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
  sig_ok = true;
  ERR_clear_error();
#endif
  if (!sig_ok) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
    return false;
  }

  return true;
}

bool tls13_process_finished(SSL_HANDSHAKE *hs, const SSLMessage &msg,
                            bool use_saved_value) {
  SSL *const ssl = hs->ssl;
  uint8_t verify_data_buf[EVP_MAX_MD_SIZE];
  const uint8_t *verify_data;
  size_t verify_data_len;
  if (use_saved_value) {
    assert(ssl->server);
    verify_data = hs->expected_client_finished;
    verify_data_len = hs->hash_len;
  } else {
    if (!tls13_finished_mac(hs, verify_data_buf, &verify_data_len,
                            !ssl->server)) {
      return false;
    }
    verify_data = verify_data_buf;
  }

  bool finished_ok = CBS_mem_equal(&msg.body, verify_data, verify_data_len);
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
  finished_ok = true;
#endif
  if (!finished_ok) {
    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
    OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
    return false;
  }

  return true;
}

bool tls13_add_certificate(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  CERT *const cert = hs->config->cert.get();

  ScopedCBB cbb;
  CBB *body, body_storage, certificate_list;

  if (hs->cert_compression_negotiated) {
    if (!CBB_init(cbb.get(), 1024)) {
      return false;
    }
    body = cbb.get();
  } else {
    body = &body_storage;
    if (!ssl->method->init_message(ssl, cbb.get(), body, SSL3_MT_CERTIFICATE)) {
      return false;
    }
  }

  if (// The request context is always empty in the handshake.
      !CBB_add_u8(body, 0) ||
      !CBB_add_u24_length_prefixed(body, &certificate_list)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return false;
  }

  if (!ssl_has_certificate(hs->config)) {
    return ssl_add_message_cbb(ssl, cbb.get());
  }

  CRYPTO_BUFFER *leaf_buf = sk_CRYPTO_BUFFER_value(cert->chain.get(), 0);
  CBB leaf, extensions;
  if (!CBB_add_u24_length_prefixed(&certificate_list, &leaf) ||
      !CBB_add_bytes(&leaf, CRYPTO_BUFFER_data(leaf_buf),
                     CRYPTO_BUFFER_len(leaf_buf)) ||
      !CBB_add_u16_length_prefixed(&certificate_list, &extensions)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return false;
  }

  if (hs->scts_requested && cert->signed_cert_timestamp_list != nullptr) {
    CBB contents;
    if (!CBB_add_u16(&extensions, TLSEXT_TYPE_certificate_timestamp) ||
        !CBB_add_u16_length_prefixed(&extensions, &contents) ||
        !CBB_add_bytes(
            &contents,
            CRYPTO_BUFFER_data(cert->signed_cert_timestamp_list.get()),
            CRYPTO_BUFFER_len(cert->signed_cert_timestamp_list.get())) ||
        !CBB_flush(&extensions)) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      return false;
    }
  }

  if (hs->ocsp_stapling_requested && cert->ocsp_response != NULL) {
    CBB contents, ocsp_response;
    if (!CBB_add_u16(&extensions, TLSEXT_TYPE_status_request) ||
        !CBB_add_u16_length_prefixed(&extensions, &contents) ||
        !CBB_add_u8(&contents, TLSEXT_STATUSTYPE_ocsp) ||
        !CBB_add_u24_length_prefixed(&contents, &ocsp_response) ||
        !CBB_add_bytes(&ocsp_response,
                       CRYPTO_BUFFER_data(cert->ocsp_response.get()),
                       CRYPTO_BUFFER_len(cert->ocsp_response.get())) ||
        !CBB_flush(&extensions)) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      return false;
    }
  }

  for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(cert->chain.get()); i++) {
    CRYPTO_BUFFER *cert_buf = sk_CRYPTO_BUFFER_value(cert->chain.get(), i);
    CBB child;
    if (!CBB_add_u24_length_prefixed(&certificate_list, &child) ||
        !CBB_add_bytes(&child, CRYPTO_BUFFER_data(cert_buf),
                       CRYPTO_BUFFER_len(cert_buf)) ||
        !CBB_add_u16(&certificate_list, 0 /* no extensions */)) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      return false;
    }
  }

  if (!hs->cert_compression_negotiated) {
    return ssl_add_message_cbb(ssl, cbb.get());
  }

  Array<uint8_t> msg;
  if (!CBBFinishArray(cbb.get(), &msg)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return false;
  }

  const CertCompressionAlg *alg = nullptr;
  for (const auto *candidate : ssl->ctx->cert_compression_algs.get()) {
    if (candidate->alg_id == hs->cert_compression_alg_id) {
      alg = candidate;
      break;
    }
  }

  if (alg == nullptr || alg->compress == nullptr) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return false;
  }

  CBB compressed;
  body = &body_storage;
  if (!ssl->method->init_message(ssl, cbb.get(), body,
                                 SSL3_MT_COMPRESSED_CERTIFICATE) ||
      !CBB_add_u16(body, hs->cert_compression_alg_id) ||
      !CBB_add_u24(body, msg.size()) ||
      !CBB_add_u24_length_prefixed(body, &compressed) ||
      !alg->compress(ssl, &compressed, msg.data(), msg.size()) ||
      !ssl_add_message_cbb(ssl, cbb.get())) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return false;
  }

  return true;
}

enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  uint16_t signature_algorithm;
  if (!tls1_choose_signature_algorithm(hs, &signature_algorithm)) {
    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
    return ssl_private_key_failure;
  }

  ScopedCBB cbb;
  CBB body;
  if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                 SSL3_MT_CERTIFICATE_VERIFY) ||
      !CBB_add_u16(&body, signature_algorithm)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return ssl_private_key_failure;
  }

  // Sign the digest.
  CBB child;
  const size_t max_sig_len = EVP_PKEY_size(hs->local_pubkey.get());
  uint8_t *sig;
  size_t sig_len;
  if (!CBB_add_u16_length_prefixed(&body, &child) ||
      !CBB_reserve(&child, &sig, max_sig_len)) {
    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
    return ssl_private_key_failure;
  }

  Array<uint8_t> msg;
  if (!tls13_get_cert_verify_signature_input(
          hs, &msg,
          ssl->server ? ssl_cert_verify_server : ssl_cert_verify_client)) {
    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
    return ssl_private_key_failure;
  }

  enum ssl_private_key_result_t sign_result = ssl_private_key_sign(
      hs, sig, &sig_len, max_sig_len, signature_algorithm, msg);
  if (sign_result != ssl_private_key_success) {
    return sign_result;
  }

  if (!CBB_did_write(&child, sig_len) ||
      !ssl_add_message_cbb(ssl, cbb.get())) {
    return ssl_private_key_failure;
  }

  return ssl_private_key_success;
}

bool tls13_add_finished(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  size_t verify_data_len;
  uint8_t verify_data[EVP_MAX_MD_SIZE];

  if (!tls13_finished_mac(hs, verify_data, &verify_data_len, ssl->server)) {
    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
    OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
    return false;
  }

  ScopedCBB cbb;
  CBB body;
  if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_FINISHED) ||
      !CBB_add_bytes(&body, verify_data, verify_data_len) ||
      !ssl_add_message_cbb(ssl, cbb.get())) {
    return false;
  }

  return true;
}

static bool tls13_receive_key_update(SSL *ssl, const SSLMessage &msg) {
  CBS body = msg.body;
  uint8_t key_update_request;
  if (!CBS_get_u8(&body, &key_update_request) ||
      CBS_len(&body) != 0 ||
      (key_update_request != SSL_KEY_UPDATE_NOT_REQUESTED &&
       key_update_request != SSL_KEY_UPDATE_REQUESTED)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    return false;
  }

  if (!tls13_rotate_traffic_key(ssl, evp_aead_open)) {
    return false;
  }

  // Acknowledge the KeyUpdate
  if (key_update_request == SSL_KEY_UPDATE_REQUESTED &&
      !ssl->s3->key_update_pending) {
    ScopedCBB cbb;
    CBB body_cbb;
    if (!ssl->method->init_message(ssl, cbb.get(), &body_cbb,
                                   SSL3_MT_KEY_UPDATE) ||
        !CBB_add_u8(&body_cbb, SSL_KEY_UPDATE_NOT_REQUESTED) ||
        !ssl_add_message_cbb(ssl, cbb.get()) ||
        !tls13_rotate_traffic_key(ssl, evp_aead_seal)) {
      return false;
    }

    // Suppress KeyUpdate acknowledgments until this change is written to the
    // wire. This prevents us from accumulating write obligations when read and
    // write progress at different rates. See RFC 8446, section 4.6.3.
    ssl->s3->key_update_pending = true;
  }

  return true;
}

bool tls13_post_handshake(SSL *ssl, const SSLMessage &msg) {
  if (msg.type == SSL3_MT_KEY_UPDATE) {
    ssl->s3->key_update_count++;
    if (ssl->ctx->quic_method != nullptr ||
        ssl->s3->key_update_count > kMaxKeyUpdates) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_KEY_UPDATES);
      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
      return false;
    }

    return tls13_receive_key_update(ssl, msg);
  }

  ssl->s3->key_update_count = 0;

  if (msg.type == SSL3_MT_NEW_SESSION_TICKET && !ssl->server) {
    return tls13_process_new_session_ticket(ssl, msg);
  }

  ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
  OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
  return false;
}

BSSL_NAMESPACE_END
