// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
// Copyright 2005 Nokia. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <openssl/ssl.h>

#include <string_view>

#include <openssl/buf.h>
#include <openssl/digest.h>
#include <openssl/err.h>

#include "internal.h"


BSSL_NAMESPACE_BEGIN

SSLTranscript::SSLTranscript(bool is_dtls) : is_dtls_(is_dtls) {}

SSLTranscript::~SSLTranscript() {}

bool SSLTranscript::Init() {
  buffer_.reset(BUF_MEM_new());
  if (!buffer_) {
    return false;
  }

  hash_.Reset();
  return true;
}

bool SSLTranscript::InitHash(uint16_t version, const SSL_CIPHER *cipher) {
  version_ = version;
  const EVP_MD *md = ssl_get_handshake_digest(version, cipher);
  if (Digest() == md) {
    // No need to re-hash the buffer.
    return true;
  }
  if (!HashBuffer(hash_.get(), md)) {
    return false;
  }
  if (is_dtls_ && version_ >= TLS1_3_VERSION) {
    // In DTLS 1.3, prior to the call to InitHash, the message (if present) in
    // the buffer has the DTLS 1.2 header. After the call to InitHash, the TLS
    // 1.3 header is written by SSLTranscript::Update. If the buffer isn't freed
    // here, it would have a mix of different header formats and using it would
    // yield wrong results. However, there's no need for the buffer once the
    // version and the digest for the cipher suite are known, so the buffer is
    // freed here to avoid potential misuse of the SSLTranscript object.
    FreeBuffer();
  }
  return true;
}

bool SSLTranscript::HashBuffer(EVP_MD_CTX *ctx, const EVP_MD *digest) const {
  if (!EVP_DigestInit_ex(ctx, digest, nullptr)) {
    return false;
  }
  if (!is_dtls_ || version_ < TLS1_3_VERSION) {
    return EVP_DigestUpdate(ctx, buffer_->data, buffer_->length);
  }

  // If the version is DTLS 1.3 and we still have a buffer, then there should be
  // at most a single DTLSHandshake message in the buffer, for the ClientHello.
  // On the server side, the version (DTLS 1.3) and cipher suite are chosen in
  // response to the first ClientHello, and InitHash is called before that
  // ClientHello is added to the SSLTranscript, so the buffer is empty if this
  // SSLTranscript is on the server.
  if (buffer_->length == 0) {
    return true;
  }

  // On the client side, we can receive either a ServerHello or
  // HelloRetryRequest in response to the ClientHello. Regardless of which
  // message we receive, the client code calls InitHash before updating the
  // transcript with that message, so the ClientHello is the only message in the
  // buffer. In DTLS 1.3, we need to skip the message_seq, fragment_offset, and
  // fragment_length fields from the DTLSHandshake message in the buffer. The
  // structure of a DTLSHandshake message is as follows (RFC 9147, section 5.2):
  //
  //   struct {
  //       HandshakeType msg_type;    /* handshake type */
  //       uint24 length;             /* bytes in message */
  //       uint16 message_seq;        /* DTLS-required field */
  //       uint24 fragment_offset;    /* DTLS-required field */
  //       uint24 fragment_length;    /* DTLS-required field */
  //       select (msg_type) {
  //         /* omitted for brevity */
  //       } body;
  //   } DTLSHandshake;
  CBS buf, header;
  CBS_init(&buf, reinterpret_cast<uint8_t *>(buffer_->data), buffer_->length);
  if (!CBS_get_bytes(&buf, &header, 4) ||                             //
      !CBS_skip(&buf, 8) ||                                           //
      !EVP_DigestUpdate(ctx, CBS_data(&header), CBS_len(&header)) ||  //
      !EVP_DigestUpdate(ctx, CBS_data(&buf), CBS_len(&buf))) {
    return false;
  }
  return true;
}

void SSLTranscript::FreeBuffer() { buffer_.reset(); }

size_t SSLTranscript::DigestLen() const { return EVP_MD_size(Digest()); }

const EVP_MD *SSLTranscript::Digest() const {
  return EVP_MD_CTX_get0_md(hash_.get());
}

bool SSLTranscript::UpdateForHelloRetryRequest() {
  if (buffer_) {
    buffer_->length = 0;
  }

  uint8_t old_hash[EVP_MAX_MD_SIZE];
  size_t hash_len;
  if (!GetHash(old_hash, &hash_len)) {
    return false;
  }
  const uint8_t header[4] = {SSL3_MT_MESSAGE_HASH, 0, 0,
                             static_cast<uint8_t>(hash_len)};
  if (!EVP_DigestInit_ex(hash_.get(), Digest(), nullptr) ||
      !AddToBufferOrHash(header) ||
      !AddToBufferOrHash(Span(old_hash, hash_len))) {
    return false;
  }
  return true;
}

bool SSLTranscript::CopyToHashContext(EVP_MD_CTX *ctx,
                                      const EVP_MD *digest) const {
  const EVP_MD *transcript_digest = Digest();
  if (transcript_digest != nullptr &&
      EVP_MD_type(transcript_digest) == EVP_MD_type(digest)) {
    return EVP_MD_CTX_copy_ex(ctx, hash_.get());
  }

  if (buffer_) {
    return HashBuffer(ctx, digest);
  }

  OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
  return false;
}

bool SSLTranscript::Update(Span<const uint8_t> in) {
  if (!is_dtls_ || version_ < TLS1_3_VERSION) {
    return AddToBufferOrHash(in);
  }
  if (in.size() < DTLS1_HM_HEADER_LENGTH) {
    return false;
  }
  // The message passed into Update is the whole Handshake or DTLSHandshake
  // message, including the msg_type and length. In DTLS, the DTLSHandshake
  // message also has message_seq, fragment_offset, and fragment_length
  // fields. In DTLS 1.3, those fields are omitted so that the same
  // transcript format as TLS 1.3 is used. This means we write the 1-byte
  // msg_type, 3-byte length, then skip 2+3+3 bytes for the DTLS-specific
  // fields that get omitted.
  if (!AddToBufferOrHash(in.subspan(0, 4)) ||
      !AddToBufferOrHash(in.subspan(12))) {
    return false;
  }
  return true;
}

bool SSLTranscript::AddToBufferOrHash(Span<const uint8_t> in) {
  // Depending on the state of the handshake, either the handshake buffer may be
  // active, the rolling hash, or both.
  if (buffer_ &&  //
      !BUF_MEM_append(buffer_.get(), in.data(), in.size())) {
    return false;
  }

  if (EVP_MD_CTX_md(hash_.get()) != NULL) {
    EVP_DigestUpdate(hash_.get(), in.data(), in.size());
  }

  return true;
}

bool SSLTranscript::GetHash(uint8_t *out, size_t *out_len) const {
  ScopedEVP_MD_CTX ctx;
  unsigned len;
  if (!EVP_MD_CTX_copy_ex(ctx.get(), hash_.get()) ||
      !EVP_DigestFinal_ex(ctx.get(), out, &len)) {
    return false;
  }
  *out_len = len;
  return true;
}

bool SSLTranscript::GetFinishedMAC(uint8_t *out, size_t *out_len,
                                   const SSL_SESSION *session,
                                   bool from_server) const {
  uint8_t digest[EVP_MAX_MD_SIZE];
  size_t digest_len;
  if (!GetHash(digest, &digest_len)) {
    return false;
  }

  std::string_view label = from_server ? "server finished" : "client finished";
  static const size_t kFinishedLen = 12;
  if (!tls1_prf(Digest(), Span(out, kFinishedLen), session->secret, label,
                Span(digest, digest_len), {})) {
    return false;
  }

  *out_len = kFinishedLen;
  return true;
}

BSSL_NAMESPACE_END
