// 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/streaming_aead_test_util.h"

#include <sstream>
#include <string>

#include "tink/random_access_stream.h"
#include "tink/subtle/test_util.h"
#include "tink/util/buffer.h"
#include "tink/util/file_random_access_stream.h"
#include "tink/util/istream_input_stream.h"
#include "tink/util/ostream_output_stream.h"
#include "tink/util/status.h"
#include "tink/util/test_util.h"

namespace crypto {
namespace tink {

using ::crypto::tink::test::GetTestFileDescriptor;
using ::crypto::tink::util::IstreamInputStream;
using ::crypto::tink::util::OstreamOutputStream;
using ::crypto::tink::util::Status;

namespace {

// Creates a RandomAccessStream with the specified contents.
std::unique_ptr<RandomAccessStream> GetRandomAccessStreamContaining(
    absl::string_view contents) {
  static int index = 1;
  std::string filename = absl::StrCat("stream_data_file_", index, ".txt");
  index++;
  int input_fd = GetTestFileDescriptor(filename, contents);
  return {absl::make_unique<util::FileRandomAccessStream>(input_fd)};
}

// Reads up to 'count' bytes from 'ras' starting at position 'pos'
// and verifies that the read bytes are equal to the corresponding
// subsequence in 'full_contents'.
Status ReadAndVerifyFragment(RandomAccessStream* ras, int pos, int count,
                             absl::string_view full_contents) {
  auto buf_result = util::Buffer::New(count);
  if (!buf_result.ok()) {
    return Status(crypto::tink::util::error::INTERNAL,
                  absl::StrCat("Could not allocate buffer of size ", count));
  }
  auto buf = std::move(buf_result.ValueOrDie());
  int full_size = full_contents.size();
  auto status = ras->PRead(pos, count, buf.get());
  if (!status.ok() && status.error_code() != util::error::OUT_OF_RANGE) {
    return Status(
        crypto::tink::util::error::INTERNAL,
        absl::StrCat("PRead failed with status: ", status.ToString()));
  }
  int exp_size = std::min(count, full_size - pos);
  if (exp_size != buf->size()) {
    return Status(crypto::tink::util::error::INTERNAL,
                  absl::StrCat("PRead returned ", buf->size(), " bytes, while ",
                               exp_size, " bytes were expected."));
  }
  if (std::memcmp(full_contents.data() + pos, buf->get_mem_block(), exp_size)) {
    return Status(
        crypto::tink::util::error::INTERNAL,
        absl::StrCat("PRead returned bytes [",
                     std::string(buf->get_mem_block(), exp_size), "] while [",
                     full_contents.substr(pos, exp_size), "] were expected."));
  }
  return Status::OK;
}

}  // namespace

crypto::tink::util::Status EncryptThenDecrypt(StreamingAead* encrypter,
                                              StreamingAead* decrypter,
                                              absl::string_view plaintext,
                                              absl::string_view associated_data,
                                              int ciphertext_offset) {
  // Prepare ciphertext destination stream.
  auto ct_stream = absl::make_unique<std::stringstream>();

  // A reference to the ciphertext buffer, for later validation.
  auto ct_buf = ct_stream->rdbuf();
  auto ct_destination =
      absl::make_unique<OstreamOutputStream>(std::move(ct_stream));
  auto status = subtle::test::WriteToStream(
      ct_destination.get(), std::string(ciphertext_offset, 'o'), false);
  if (!status.ok()) return status;

  // Use encrypter to encrypt some data.
  auto enc_stream_result = encrypter->NewEncryptingStream(
      std::move(ct_destination), associated_data);
  if (!enc_stream_result.ok()) return enc_stream_result.status();
  auto enc_stream = std::move(enc_stream_result.ValueOrDie());
  status = subtle::test::WriteToStream(enc_stream.get(), plaintext);
  if (!status.ok()) return status;
  if (plaintext.size() != enc_stream->Position()) {
    return ::crypto::tink::util::Status(
        crypto::tink::util::error::INTERNAL,
        "Plaintext size different from stream position.");
  }

  // Prepare an InputStream with the ciphertext.
  auto ct_bytes = absl::make_unique<std::stringstream>(
      ct_buf->str().substr(ciphertext_offset));
  std::unique_ptr<InputStream> ct_source(
      absl::make_unique<IstreamInputStream>(std::move(ct_bytes)));

  // Decrypt the ciphertext using the decrypter.
  auto dec_stream_result = decrypter->NewDecryptingStream(
      std::move(ct_source), associated_data);
  if (!dec_stream_result.ok()) return dec_stream_result.status();
  auto dec_stream = std::move(dec_stream_result.ValueOrDie());
  std::string decrypted;
  status = subtle::test::ReadFromStream(dec_stream.get(), &decrypted);
  if (!status.ok()) {
    return status;
  }
  if (plaintext != decrypted) {
    return ::crypto::tink::util::Status(crypto::tink::util::error::INTERNAL,
                                        "Decryption differs from plaintext.");
  }

  // Prepare a RandomAccessStream with the ciphertext.
  auto ct_ras = GetRandomAccessStreamContaining(std::string(ct_buf->str()));

  // Decrypt fragments of the ciphertext using the decrypter.
  auto dec_ras_result = decrypter->NewDecryptingRandomAccessStream(
      std::move(ct_ras), associated_data);
  if (!dec_ras_result.ok()) return dec_ras_result.status();
  auto dec_ras = std::move(dec_ras_result.ValueOrDie());
  int pt_size = plaintext.size();
  for (int pos : {0, pt_size / 2, std::max(pt_size - 10, 0)}) {
    for (int count : {1, 10, std::max(pt_size / 2, 1), std::max(pt_size, 1)}) {
      auto status = ReadAndVerifyFragment(dec_ras.get(), pos, count, plaintext);
      if (!status.ok()) {
        return Status(
            crypto::tink::util::error::INTERNAL,
            absl::StrCat("Random access decryption failed at position=", pos,
                         " with count=", count,
                         " and status: ", status.ToString()));
      }
    }
  }
  return crypto::tink::util::OkStatus();
}

}  // namespace tink
}  // namespace crypto
