// 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
//
//     http://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 "tink/subtle/aes_ctr_hmac_streaming.h"

#include <limits>
#include <string>
#include <vector>

#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "openssl/base.h"
#include "openssl/cipher.h"
#include "openssl/err.h"
#include "openssl/evp.h"
#include "tink/subtle/common_enums.h"
#include "tink/subtle/hkdf.h"
#include "tink/subtle/hmac_boringssl.h"
#include "tink/subtle/random.h"
#include "tink/subtle/stream_segment_decrypter.h"
#include "tink/subtle/stream_segment_encrypter.h"
#include "tink/subtle/subtle_util.h"
#include "tink/subtle/subtle_util_boringssl.h"
#include "tink/util/errors.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"

namespace crypto {
namespace tink {
namespace subtle {

static std::string NonceForSegment(absl::string_view nonce_prefix,
                              int64_t segment_number, bool is_last_segment) {
  return absl::StrCat(nonce_prefix, BigEndian32(segment_number),
                      is_last_segment ? std::string(1, '\x01') : std::string(1, '\x00'),
                      std::string(4, '\x00'));
}

static util::Status DeriveKeys(absl::string_view ikm, HashType hkdf_algo,
                               absl::string_view salt,
                               absl::string_view associated_data, int key_size,
                               std::string* key_value, std::string* hmac_key_value) {
  int derived_key_material_size =
      key_size + AesCtrHmacStreaming::kHmacKeySizeInBytes;
  auto hkdf_result = Hkdf::ComputeHkdf(hkdf_algo, ikm, salt, associated_data,
                                       derived_key_material_size);
  if (!hkdf_result.ok()) return hkdf_result.status();
  std::string key_material = std::move(hkdf_result.ValueOrDie());
  *key_value = key_material.substr(0, key_size);
  *hmac_key_value =
      key_material.substr(key_size, AesCtrHmacStreaming::kHmacKeySizeInBytes);
  return util::OkStatus();
}

static util::Status Validate(const AesCtrHmacStreaming::Params& params) {
  if (params.ikm.size() < std::max(16, params.key_size)) {
    return util::Status(util::error::INVALID_ARGUMENT,
                        "input key material too small");
  }
  if (!(params.hkdf_algo == SHA1 || params.hkdf_algo == SHA256 ||
        params.hkdf_algo == SHA512)) {
    return util::Status(util::error::INVALID_ARGUMENT, "unsupported hkdf_algo");
  }
  if (params.key_size != 16 && params.key_size != 32) {
    return util::Status(util::error::INVALID_ARGUMENT,
                        "key_size must be 16 or 32");
  }
  int header_size =
      1 + params.key_size + AesCtrHmacStreaming::kNoncePrefixSizeInBytes;
  if (params.ciphertext_segment_size <=
      params.ciphertext_offset + header_size + params.tag_size) {
    return util::Status(util::error::INVALID_ARGUMENT,
                        "ciphertext_segment_size too small");
  }
  if (params.ciphertext_offset < 0) {
    return util::Status(util::error::INVALID_ARGUMENT,
                        "ciphertext_offset must be non-negative");
  }
  if (params.tag_size < 10) {
    return util::Status(util::error::INVALID_ARGUMENT, "tag_size too small");
  }
  if (!(params.tag_algo == SHA1 || params.tag_algo == SHA256 ||
        params.tag_algo == SHA512)) {
    return util::Status(util::error::INVALID_ARGUMENT, "unsupported tag_algo");
  }
  if ((params.tag_algo == SHA1 && params.tag_size > 20) ||
      (params.tag_algo == SHA256 && params.tag_size > 32) ||
      (params.tag_algo == SHA512 && params.tag_size > 64)) {
    return util::Status(util::error::INVALID_ARGUMENT, "tag_size too big");
  }

  return util::OkStatus();
}

// AesCtrHmacStreaming
// static
util::StatusOr<std::unique_ptr<AesCtrHmacStreaming>> AesCtrHmacStreaming::New(
    const Params& params) {
  auto status = Validate(params);
  if (!status.ok()) return status;
  return {absl::WrapUnique(new AesCtrHmacStreaming(params))};
}

// static
util::StatusOr<std::unique_ptr<StreamSegmentEncrypter>>
AesCtrHmacStreaming::NewSegmentEncrypter(
    absl::string_view associated_data) const {
  return AesCtrHmacStreamSegmentEncrypter::New(params_, associated_data);
}

// static
util::StatusOr<std::unique_ptr<StreamSegmentDecrypter>>
AesCtrHmacStreaming::NewSegmentDecrypter(
    absl::string_view associated_data) const {
  return AesCtrHmacStreamSegmentDecrypter::New(params_, associated_data);
}

// AesCtrHmacStreamSegmentEncrypter
static std::string MakeHeader(absl::string_view salt,
                         absl::string_view nonce_prefix) {
  uint8_t header_size =
      static_cast<uint8_t>(1 + salt.size() + nonce_prefix.size());
  return absl::StrCat(std::string(1, header_size), salt, nonce_prefix);
}

// static
util::StatusOr<std::unique_ptr<StreamSegmentEncrypter>>
AesCtrHmacStreamSegmentEncrypter::New(const AesCtrHmacStreaming::Params& params,
                                      absl::string_view associated_data) {
  auto status = Validate(params);
  if (!status.ok()) return status;

  std::string salt = Random::GetRandomBytes(params.key_size);
  std::string nonce_prefix =
      Random::GetRandomBytes(AesCtrHmacStreaming::kNoncePrefixSizeInBytes);
  std::string header = MakeHeader(salt, nonce_prefix);

  std::string key_value, hmac_key_value;
  status = DeriveKeys(params.ikm, params.hkdf_algo, salt, associated_data,
                      params.key_size, &key_value, &hmac_key_value);
  if (!status.ok()) return status;

  auto cipher = SubtleUtilBoringSSL::GetAesCtrCipherForKeySize(params.key_size);
  if (cipher == nullptr) {
    return util::Status(util::error::INTERNAL, "invalid key size");
  }

  auto hmac_result =
      HmacBoringSsl::New(params.tag_algo, params.tag_size, hmac_key_value);
  if (!hmac_result.ok()) return hmac_result.status();
  auto mac = std::move(hmac_result.ValueOrDie());

  return {absl::WrapUnique(new AesCtrHmacStreamSegmentEncrypter(
      key_value, header, nonce_prefix, params.ciphertext_segment_size,
      params.ciphertext_offset, params.tag_size, cipher, std::move(mac)))};
}

util::Status AesCtrHmacStreamSegmentEncrypter::EncryptSegment(
    const std::vector<uint8_t>& plaintext, bool is_last_segment,
    std::vector<uint8_t>* ciphertext_buffer) {
  if (plaintext.size() > get_plaintext_segment_size()) {
    return util::Status(util::error::INVALID_ARGUMENT, "plaintext too long");
  }
  if (ciphertext_buffer == nullptr) {
    return util::Status(util::error::INVALID_ARGUMENT,
                        "ciphertext_buffer must be non-null");
  }
  if (get_segment_number() > std::numeric_limits<uint32_t>::max() ||
      (get_segment_number() == std::numeric_limits<uint32_t>::max() &&
       !is_last_segment)) {
    return util::Status(util::error::INVALID_ARGUMENT, "too many segments");
  }

  int ct_size = plaintext.size() + tag_size_;
  ciphertext_buffer->resize(ct_size);

  std::string nonce =
      NonceForSegment(nonce_prefix_, segment_number_, is_last_segment);

  // Encrypt.
  bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
  if (ctx.get() == nullptr) {
    return util::Status(util::error::INTERNAL,
                        "could not initialize EVP_CIPHER_CTX");
  }
  if (EVP_EncryptInit_ex(ctx.get(), cipher_, nullptr /* engine */,
                         reinterpret_cast<const uint8_t*>(key_value_.data()),
                         reinterpret_cast<const uint8_t*>(nonce.data())) != 1) {
    return util::Status(util::error::INTERNAL, "could not initialize ctx");
  }

  int out_len;
  if (EVP_EncryptUpdate(ctx.get(), ciphertext_buffer->data(), &out_len,
                        plaintext.data(), plaintext.size()) != 1) {
    return util::Status(util::error::INTERNAL, "encryption failed");
  }
  if (out_len != plaintext.size()) {
    return util::Status(util::error::INTERNAL, "incorrect ciphertext size");
  }

  // Add MAC tag.
  absl::string_view ciphertext_string(
      reinterpret_cast<const char*>(ciphertext_buffer->data()),
      plaintext.size());
  auto tag_result = mac_->ComputeMac(absl::StrCat(nonce, ciphertext_string));
  if (!tag_result.ok()) return tag_result.status();
  std::string tag = tag_result.ValueOrDie();
  memcpy(ciphertext_buffer->data() + plaintext.size(),
         reinterpret_cast<const uint8_t*>(tag.data()), tag_size_);

  IncSegmentNumber();
  return util::OkStatus();
}

// AesCtrHmacStreamSegmentDecrypter
// static
util::StatusOr<std::unique_ptr<StreamSegmentDecrypter>>
AesCtrHmacStreamSegmentDecrypter::New(const AesCtrHmacStreaming::Params& params,
                                      absl::string_view associated_data) {
  auto status = Validate(params);
  if (!status.ok()) return status;

  return {absl::WrapUnique(new AesCtrHmacStreamSegmentDecrypter(
      params.ikm, params.hkdf_algo, params.key_size, associated_data,
      params.ciphertext_segment_size, params.ciphertext_offset, params.tag_algo,
      params.tag_size))};
}

util::Status AesCtrHmacStreamSegmentDecrypter::Init(
    const std::vector<uint8_t>& header) {
  if (is_initialized_) {
    return util::Status(util::error::FAILED_PRECONDITION,
                        "decrypter alreday initialized");
  }
  if (header.size() != get_header_size()) {
    return util::Status(util::error::INVALID_ARGUMENT,
                        absl::StrCat("wrong header size, expected ",
                                     get_header_size(), " bytes"));
  }
  if (header[0] != header.size()) {
    return util::Status(util::error::INVALID_ARGUMENT, "corrupted header");
  }

  // Extract salt and nonce prefix.
  std::string salt(reinterpret_cast<const char*>(header.data() + 1), key_size_);
  nonce_prefix_ =
      std::string(reinterpret_cast<const char*>(header.data() + 1 + key_size_),
             AesCtrHmacStreaming::kNoncePrefixSizeInBytes);

  std::string hmac_key_value;
  auto status = DeriveKeys(ikm_, hkdf_algo_, salt, associated_data_, key_size_,
                           &key_value_, &hmac_key_value);
  if (!status.ok()) return status;

  cipher_ = SubtleUtilBoringSSL::GetAesCtrCipherForKeySize(key_size_);
  if (cipher_ == nullptr) {
    return util::Status(util::error::INTERNAL, "invalid key size");
  }

  auto hmac_result = HmacBoringSsl::New(tag_algo_, tag_size_, hmac_key_value);
  if (!hmac_result.ok()) return hmac_result.status();
  mac_ = std::move(hmac_result.ValueOrDie());

  is_initialized_ = true;
  return util::OkStatus();
}

util::Status AesCtrHmacStreamSegmentDecrypter::DecryptSegment(
    const std::vector<uint8_t>& ciphertext, int64_t segment_number,
    bool is_last_segment, std::vector<uint8_t>* plaintext_buffer) {
  if (!is_initialized_) {
    return util::Status(util::error::FAILED_PRECONDITION,
                        "decrypter not initialized");
  }
  if (ciphertext.size() > get_ciphertext_segment_size()) {
    return util::Status(util::error::INVALID_ARGUMENT, "ciphertext too long");
  }
  if (ciphertext.size() < tag_size_) {
    return util::Status(util::error::INVALID_ARGUMENT, "ciphertext too short");
  }
  if (plaintext_buffer == nullptr) {
    return util::Status(util::error::INVALID_ARGUMENT,
                        "plaintext_buffer must be non-null");
  }
  if (segment_number > std::numeric_limits<uint32_t>::max() ||
      (segment_number == std::numeric_limits<uint32_t>::max() &&
       !is_last_segment)) {
    return util::Status(util::error::INVALID_ARGUMENT, "too many segments");
  }

  int pt_size = ciphertext.size() - tag_size_;
  plaintext_buffer->resize(pt_size);

  std::string nonce =
      NonceForSegment(nonce_prefix_, segment_number, is_last_segment);

  // Verify MAC tag.
  absl::string_view tag(
      reinterpret_cast<const char*>(ciphertext.data() + pt_size), tag_size_);
  absl::string_view ciphertext_string(
      reinterpret_cast<const char*>(ciphertext.data()), pt_size);
  auto status = mac_->VerifyMac(tag, absl::StrCat(nonce, ciphertext_string));
  if (!status.ok()) return status;

  // Decrypt.
  bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
  if (ctx.get() == nullptr) {
    return util::Status(util::error::INTERNAL,
                        "could not initialize EVP_CIPHER_CTX");
  }
  if (EVP_DecryptInit_ex(ctx.get(), cipher_, nullptr /* engine */,
                         reinterpret_cast<const uint8_t*>(key_value_.data()),
                         reinterpret_cast<const uint8_t*>(nonce.data())) != 1) {
    return util::Status(util::error::INTERNAL, "could not initialize ctx");
  }

  int out_len;
  if (EVP_DecryptUpdate(ctx.get(), plaintext_buffer->data(), &out_len,
                        ciphertext.data(), pt_size) != 1) {
    return util::Status(util::error::INTERNAL, "decryption failed");
  }
  if (out_len != pt_size) {
    return util::Status(util::error::INTERNAL, "incorrect plaintext size");
  }

  return util::OkStatus();
}

}  // namespace subtle
}  // namespace tink
}  // namespace crypto
