/*
 *
 * Copyright 2018 gRPC authors.
 *
 * 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 <grpc/support/port_platform.h>

#include "src/core/tsi/alts/frame_protector/frame_handler.h"

#include <limits.h>
#include <stdint.h>
#include <string.h>

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>

#include "src/core/lib/gpr/useful.h"

/* Use little endian to interpret a string of bytes as uint32_t. */
static uint32_t load_32_le(const unsigned char* buffer) {
  return (((uint32_t)buffer[3]) << 24) | (((uint32_t)buffer[2]) << 16) |
         (((uint32_t)buffer[1]) << 8) | ((uint32_t)buffer[0]);
}

/* Store uint32_t as a string of little endian bytes. */
static void store_32_le(uint32_t value, unsigned char* buffer) {
  buffer[3] = (unsigned char)(value >> 24) & 0xFF;
  buffer[2] = (unsigned char)(value >> 16) & 0xFF;
  buffer[1] = (unsigned char)(value >> 8) & 0xFF;
  buffer[0] = (unsigned char)(value)&0xFF;
}

/* Frame writer implementation. */
alts_frame_writer* alts_create_frame_writer() {
  alts_frame_writer* writer =
      static_cast<alts_frame_writer*>(gpr_zalloc(sizeof(*writer)));
  return writer;
}

bool alts_reset_frame_writer(alts_frame_writer* writer,
                             const unsigned char* buffer, size_t length) {
  if (buffer == nullptr) return false;
  size_t max_input_size = SIZE_MAX - kFrameLengthFieldSize;
  if (length > max_input_size) {
    gpr_log(GPR_ERROR, "length must be at most %zu", max_input_size);
    return false;
  }
  writer->input_buffer = buffer;
  writer->input_size = length;
  writer->input_bytes_written = 0;
  writer->header_bytes_written = 0;
  store_32_le(
      static_cast<uint32_t>(writer->input_size + kFrameMessageTypeFieldSize),
      writer->header_buffer);
  store_32_le(kFrameMessageType, writer->header_buffer + kFrameLengthFieldSize);
  return true;
}

bool alts_write_frame_bytes(alts_frame_writer* writer, unsigned char* output,
                            size_t* bytes_size) {
  if (bytes_size == nullptr || output == nullptr) return false;
  if (alts_is_frame_writer_done(writer)) {
    *bytes_size = 0;
    return true;
  }
  size_t bytes_written = 0;
  /* Write some header bytes, if needed. */
  if (writer->header_bytes_written != sizeof(writer->header_buffer)) {
    size_t bytes_to_write =
        GPR_MIN(*bytes_size,
                sizeof(writer->header_buffer) - writer->header_bytes_written);
    memcpy(output, writer->header_buffer + writer->header_bytes_written,
           bytes_to_write);
    bytes_written += bytes_to_write;
    *bytes_size -= bytes_to_write;
    writer->header_bytes_written += bytes_to_write;
    output += bytes_to_write;
    if (writer->header_bytes_written != sizeof(writer->header_buffer)) {
      *bytes_size = bytes_written;
      return true;
    }
  }
  /* Write some non-header bytes. */
  size_t bytes_to_write =
      GPR_MIN(writer->input_size - writer->input_bytes_written, *bytes_size);
  memcpy(output, writer->input_buffer, bytes_to_write);
  writer->input_buffer += bytes_to_write;
  bytes_written += bytes_to_write;
  writer->input_bytes_written += bytes_to_write;
  *bytes_size = bytes_written;
  return true;
}

bool alts_is_frame_writer_done(alts_frame_writer* writer) {
  return writer->input_buffer == nullptr ||
         writer->input_size == writer->input_bytes_written;
}

size_t alts_get_num_writer_bytes_remaining(alts_frame_writer* writer) {
  return (sizeof(writer->header_buffer) - writer->header_bytes_written) +
         (writer->input_size - writer->input_bytes_written);
}

void alts_destroy_frame_writer(alts_frame_writer* writer) { gpr_free(writer); }

/* Frame reader implementation. */
alts_frame_reader* alts_create_frame_reader() {
  alts_frame_reader* reader =
      static_cast<alts_frame_reader*>(gpr_zalloc(sizeof(*reader)));
  return reader;
}

bool alts_is_frame_reader_done(alts_frame_reader* reader) {
  return reader->output_buffer == nullptr ||
         (reader->header_bytes_read == sizeof(reader->header_buffer) &&
          reader->bytes_remaining == 0);
}

bool alts_has_read_frame_length(alts_frame_reader* reader) {
  return sizeof(reader->header_buffer) == reader->header_bytes_read;
}

size_t alts_get_reader_bytes_remaining(alts_frame_reader* reader) {
  return alts_has_read_frame_length(reader) ? reader->bytes_remaining : 0;
}

void alts_reset_reader_output_buffer(alts_frame_reader* reader,
                                     unsigned char* buffer) {
  reader->output_buffer = buffer;
}

bool alts_reset_frame_reader(alts_frame_reader* reader, unsigned char* buffer) {
  if (buffer == nullptr) return false;
  reader->output_buffer = buffer;
  reader->bytes_remaining = 0;
  reader->header_bytes_read = 0;
  reader->output_bytes_read = 0;
  return true;
}

bool alts_read_frame_bytes(alts_frame_reader* reader,
                           const unsigned char* bytes, size_t* bytes_size) {
  if (bytes_size == nullptr) return false;
  if (bytes == nullptr) {
    *bytes_size = 0;
    return false;
  }
  if (alts_is_frame_reader_done(reader)) {
    *bytes_size = 0;
    return true;
  }
  size_t bytes_processed = 0;
  /* Process the header, if needed. */
  if (reader->header_bytes_read != sizeof(reader->header_buffer)) {
    size_t bytes_to_write = GPR_MIN(
        *bytes_size, sizeof(reader->header_buffer) - reader->header_bytes_read);
    memcpy(reader->header_buffer + reader->header_bytes_read, bytes,
           bytes_to_write);
    reader->header_bytes_read += bytes_to_write;
    bytes_processed += bytes_to_write;
    bytes += bytes_to_write;
    *bytes_size -= bytes_to_write;
    if (reader->header_bytes_read != sizeof(reader->header_buffer)) {
      *bytes_size = bytes_processed;
      return true;
    }
    size_t frame_length = load_32_le(reader->header_buffer);
    if (frame_length < kFrameMessageTypeFieldSize ||
        frame_length > kFrameMaxSize) {
      gpr_log(GPR_ERROR,
              "Bad frame length (should be at least %zu, and at most %zu)",
              kFrameMessageTypeFieldSize, kFrameMaxSize);
      *bytes_size = 0;
      return false;
    }
    size_t message_type =
        load_32_le(reader->header_buffer + kFrameLengthFieldSize);
    if (message_type != kFrameMessageType) {
      gpr_log(GPR_ERROR, "Unsupported message type %zu (should be %zu)",
              message_type, kFrameMessageType);
      *bytes_size = 0;
      return false;
    }
    reader->bytes_remaining = frame_length - kFrameMessageTypeFieldSize;
  }
  /* Process the non-header bytes. */
  size_t bytes_to_write = GPR_MIN(*bytes_size, reader->bytes_remaining);
  memcpy(reader->output_buffer, bytes, bytes_to_write);
  reader->output_buffer += bytes_to_write;
  bytes_processed += bytes_to_write;
  reader->bytes_remaining -= bytes_to_write;
  reader->output_bytes_read += bytes_to_write;
  *bytes_size = bytes_processed;
  return true;
}

size_t alts_get_output_bytes_read(alts_frame_reader* reader) {
  return reader->output_bytes_read;
}

unsigned char* alts_get_output_buffer(alts_frame_reader* reader) {
  return reader->output_buffer;
}

void alts_destroy_frame_reader(alts_frame_reader* reader) { gpr_free(reader); }
