// Copyright 2019 Google Inc.
//
// 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_encrypting_stream.h"

#include <algorithm>
#include <cstring>

#include "absl/memory/memory.h"
#include "tink/output_stream.h"
#include "tink/subtle/stream_segment_encrypter.h"
#include "tink/util/statusor.h"

using crypto::tink::OutputStream;
using crypto::tink::util::Status;
using crypto::tink::util::StatusOr;

namespace crypto {
namespace tink {
namespace subtle {

namespace {

// Writes 'contents' to the specified 'output_stream', which must be non-null.
// In case of errors returns the first non-OK status of
// output_stream->Next()-operation.

util::Status WriteToStream(const std::vector<uint8_t>& contents,
                           OutputStream* output_stream) {
  void* buffer;
  int pos = 0;
  int remaining = contents.size();
  int available_space = 0;
  int available_bytes = 0;
  while (remaining > 0) {
    auto next_result = output_stream->Next(&buffer);
    if (!next_result.ok()) return next_result.status();
    available_space = next_result.ValueOrDie();
    available_bytes = std::min(available_space, remaining);
    memcpy(buffer, contents.data() + pos, available_bytes);
    remaining -= available_bytes;
    pos += available_bytes;
  }
  if (available_space > available_bytes) {
    output_stream->BackUp(available_space - available_bytes);
  }
  return Status::OK;
}

}  // anonymous namespace

// static
StatusOr<std::unique_ptr<OutputStream>> StreamingAeadEncryptingStream::New(
    std::unique_ptr<StreamSegmentEncrypter> segment_encrypter,
    std::unique_ptr<OutputStream> ciphertext_destination) {
  if (segment_encrypter == nullptr) {
    return Status(util::error::INVALID_ARGUMENT,
                  "segment_encrypter must be non-null");
  }
  if (ciphertext_destination == nullptr) {
    return Status(util::error::INVALID_ARGUMENT,
                  "cipertext_destination must be non-null");
  }
  std::unique_ptr<StreamingAeadEncryptingStream> enc_stream(
      new StreamingAeadEncryptingStream());
  enc_stream->segment_encrypter_ = std::move(segment_encrypter);
  enc_stream->ct_destination_ = std::move(ciphertext_destination);
  int first_segment_size =
      enc_stream->segment_encrypter_->get_plaintext_segment_size() -
      enc_stream->segment_encrypter_->get_ciphertext_offset() -
      enc_stream->segment_encrypter_->get_header().size();

  if (first_segment_size <= 0) {
    return Status(util::error::INTERNAL,
                  "Size of the first segment must be greater than 0.");
  }
  enc_stream->pt_buffer_.resize(first_segment_size);
  enc_stream->pt_to_encrypt_.resize(0);
  enc_stream->position_ = 0;
  enc_stream->is_first_segment_ = true;
  enc_stream->count_backedup_ = first_segment_size;
  enc_stream->pt_buffer_offset_ = 0;
  enc_stream->status_ = Status::OK;
  return {std::move(enc_stream)};
}

StatusOr<int> StreamingAeadEncryptingStream::Next(void** data) {
  if (!status_.ok()) return status_;

  // The first call to Next().
  if (is_first_segment_) {
    is_first_segment_ = false;
    count_backedup_ = 0;
    status_ =
        WriteToStream(segment_encrypter_->get_header(), ct_destination_.get());
    if (!status_.ok()) return status_;
    *data = pt_buffer_.data();
    position_ = pt_buffer_.size();
    return pt_buffer_.size();
  }

  // If some space was backed up, return it first.
  if (count_backedup_ > 0) {
    position_ += count_backedup_;
    pt_buffer_offset_ = pt_buffer_.size() - count_backedup_;
    int backedup = count_backedup_;
    count_backedup_ = 0;
    *data = pt_buffer_.data() + pt_buffer_offset_;
    return backedup;
  }

  // We're past the first segment, and no space was backed up, so we:
  // 1. encrypt pt_to_encrypt_ (if non-empty) as a not-last segment
  //    and attempt to write the ciphertext to ct_destination_.
  // 2. move contents of pt_buffer_ to pt_to_encrypt_ (for later encryption,
  //    as we don't know yet whether it will be the last segment or not.
  // 3. prepare and return "fresh" pt_buffer_.
  //
  // Step 1.
  if (!pt_to_encrypt_.empty()) {
    status_ = segment_encrypter_->EncryptSegment(
        pt_to_encrypt_, /* is_last_segment = */ false, &ct_buffer_);
    if (!status_.ok()) return status_;
    status_ = WriteToStream(ct_buffer_, ct_destination_.get());
    if (!status_.ok()) return status_;
  }
  // Step 2.
  pt_buffer_.swap(pt_to_encrypt_);
  // Step 3.
  pt_buffer_.resize(segment_encrypter_->get_plaintext_segment_size());
  *data = pt_buffer_.data();
  pt_buffer_offset_ = 0;
  position_ += pt_buffer_.size();
  return pt_buffer_.size();
}

void StreamingAeadEncryptingStream::BackUp(int count) {
  if (is_first_segment_ || !status_.ok() || count < 1) return;
  int curr_buffer_size = pt_buffer_.size() - pt_buffer_offset_;
  int actual_count = std::min(count, curr_buffer_size - count_backedup_);
  count_backedup_ += actual_count;
  position_ -= actual_count;
}

Status StreamingAeadEncryptingStream::Close() {
  if (!status_.ok()) return status_;
  if (is_first_segment_) {  // Next() was never called.
    status_ =
        WriteToStream(segment_encrypter_->get_header(), ct_destination_.get());
    if (!status_.ok()) return status_;
  }

  // The last segment encrypts plaintext from pt_to_encrypt_,
  // unless the current pt_buffer_ has some plaintext bytes.
  std::vector<uint8_t>* pt_last_segment = &pt_to_encrypt_;
  if ((!pt_buffer_.empty()) && count_backedup_ < pt_buffer_.size()) {
    // The last segment encrypts plaintext from pt_buffer_.
    pt_buffer_.resize(pt_buffer_.size() - count_backedup_);
    pt_last_segment = &pt_buffer_;
  }
  if (pt_last_segment != &pt_to_encrypt_ && (!pt_to_encrypt_.empty())) {
    // Before writing the last segment we must encrypt pt_to_encrypt_.
    status_ = segment_encrypter_->EncryptSegment(
        pt_to_encrypt_, /* is_last_segment = */ false, &ct_buffer_);
    if (!status_.ok()) {
      ct_destination_->Close().IgnoreError();
      return status_;
    }
    status_ = WriteToStream(ct_buffer_, ct_destination_.get());
    if (!status_.ok()) {
      ct_destination_->Close().IgnoreError();
      return status_;
    }
  }

  // Encrypt pt_last_segment, write the ciphertext, and close the stream.
  status_ = segment_encrypter_->EncryptSegment(
      *pt_last_segment, /* is_last_segment = */ true, &ct_buffer_);
  if (!status_.ok()) {
    ct_destination_->Close().IgnoreError();
    return status_;
  }
  status_ = WriteToStream(ct_buffer_, ct_destination_.get());
  if (!status_.ok()) {
    ct_destination_->Close().IgnoreError();
    return status_;
  }
  status_ = Status(util::error::FAILED_PRECONDITION, "Stream closed");
  return ct_destination_->Close();
}

int64_t StreamingAeadEncryptingStream::Position() const { return position_; }

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