// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "hermes/apdu.h"

#include <algorithm>
#include <utility>

#include <base/logging.h>
#include <base/strings/string_number_conversions.h>

namespace {

// Max data bytes for standard APDUs and extended APDUs.
// Note that the length limit for extended APDUs is not 65536 due
// to a limitation imposed by the Java Card platform.
constexpr size_t kMaxStandardDataSize = 255;
constexpr size_t kMaxExtendedDataSize = 32767;

// Number of bytes Lc and Le fields are in standard and extended APDUs.
// Note: Lc and Le must either both or neither be in extended form.
constexpr size_t kStandardLengthBytes = 1;
constexpr size_t kExtendedLengthBytes = 3;

constexpr size_t kHeaderSize = 4;  // CLA + INS + P1 + P2

}  // namespace

namespace hermes {

CommandApdu::CommandApdu(ApduClass cls,
                         ApduInstruction instruction,
                         bool is_extended_length,
                         uint16_t le)
    : is_extended_length_(is_extended_length),
      has_more_fragments_(true),
      current_fragment_(0),
      le_(le),
      current_index_(0) {
  max_data_size_ =
      is_extended_length_ ? kMaxExtendedDataSize : kMaxStandardDataSize;
  // Note that 256 is valid for standard APDUs because an Le field of 0 is
  // interpreted to mean that Ne=256.
  if (!is_extended_length_ && 256 < le_) {
    LOG(INFO) << "CommandApdu created with Le of " << le_
              << ", but is not an extended length APDU. Setting Le to 256.";
    le_ = 256;
  } else if (kMaxExtendedDataSize < le_) {
    LOG(INFO) << "CommandApdu created with Le of " << le_
              << " but restrictions imposed by the Java Card platform requires "
              << "Le to fit into a signed 16 bit integer. Setting Le to 32767.";
    le_ = kMaxExtendedDataSize;
  }

  // Create APDU header.
  data_.push_back(static_cast<uint8_t>(cls));          // CLS
  data_.push_back(static_cast<uint8_t>(instruction));  // INS
  data_.push_back(0);                                  // P1
  data_.push_back(0);                                  // P2
}

void CommandApdu::AddData(const std::initializer_list<uint8_t>& data) {
  DCHECK_EQ(current_index_, 0);
  EnsureLcExists();
  data_.insert(data_.end(), data.begin(), data.end());
}

void CommandApdu::AddData(const std::vector<uint8_t>& data) {
  DCHECK_EQ(current_index_, 0);
  EnsureLcExists();
  data_.insert(data_.end(), data.begin(), data.end());
}

size_t CommandApdu::GetNextFragment(uint8_t** fragment) {
  DCHECK(fragment);
  if (!HasMoreFragments()) {
    return 0;
  }

  size_t header_size = kHeaderSize;
  size_t length_size =
      is_extended_length_ ? kExtendedLengthBytes : kStandardLengthBytes;
  size_t lc_size = 0;
  // The APDU contains an Lc if it has any data.
  if (data_.size() > kHeaderSize) {
    lc_size += length_size;
  }
  header_size += lc_size;

  bool is_first_fragment = (current_index_ == 0);
  // Do not include APDU header in bytes_left calculation.
  current_index_ += is_first_fragment ? header_size : 0;
  size_t bytes_left = data_.size() - current_index_;
  size_t current_size = std::min(bytes_left, max_data_size_);
  bool is_last_fragment = (bytes_left == current_size);
  has_more_fragments_ = !is_last_fragment;

  // Set up APDU header in-place.
  // If Lc is 0, the generated APDU should be either case 1 or 2.
  current_index_ -= header_size;
  data_[current_index_] = data_[0];
  data_[current_index_ + 1] = data_[1];
  data_[current_index_ + 2] =
      is_last_fragment ? kApduP1LastBlock : kApduP1MoreBlocks;
  data_[current_index_ + 3] = current_fragment_++;
  if (is_extended_length_) {
    data_[current_index_ + 4] = 0;
    data_[current_index_ + 5] = static_cast<uint8_t>(current_size & 0xFF);
    data_[current_index_ + 6] = static_cast<uint8_t>(current_size >> 8);
  } else {
    data_[current_index_ + 4] = static_cast<uint8_t>(current_size);
  }
  size_t le_size = 0;
  // Last fragment is the only one that will potentially have an Le field, as we
  // do not expect any response data until we send the entire command.
  if (is_last_fragment && le_) {
    le_size = length_size;
    data_.reserve(data_.size() + length_size);
    if (is_extended_length_) {
      data_.push_back(0);
      data_.push_back(static_cast<uint8_t>(le_ & 0xFF));
      data_.push_back(static_cast<uint8_t>(le_ >> 8));
    } else {
      data_.push_back(static_cast<uint8_t>(le_));
    }
  }
  // Add APDU header and (potentially) Le to size.
  current_size += header_size + le_size;
  *fragment = &data_[current_index_];
  current_index_ += current_size;
  VLOG(2) << "APDU fragment #" << current_fragment_ - 1 << " (" << current_size
          << " bytes): " << base::HexEncode(*fragment, current_size);
  return current_size;
}

void CommandApdu::EnsureLcExists() {
  if (data_.size() == kHeaderSize) {
    if (is_extended_length_) {
      data_.push_back(0);
      data_.push_back(0);
      data_.push_back(0);
    } else {
      data_.push_back(0);
    }
  }
}

//////////////////////////
// ResponseApdu Methods //
//////////////////////////

void ResponseApdu::AddData(const std::vector<uint8_t>& data) {
  RemoveStatusBytes();
  data_.insert(data_.end(), data.begin(), data.end());
}

void ResponseApdu::AddData(const uint8_t* data, size_t data_len) {
  RemoveStatusBytes();
  data_.insert(data_.end(), data, data + data_len);
}

std::vector<uint8_t> ResponseApdu::Release() {
  RemoveStatusBytes();
  return std::move(data_);
}

CommandApdu ResponseApdu::CreateGetMoreCommand(bool use_extended_length) const {
  uint8_t sw2 = 0;
  if (2 <= data_.size()) {
    sw2 = data_[data_.size() - 1];
  }
  return CommandApdu(ApduClass::STORE_DATA, ApduInstruction::GET_MORE_RESPONSE,
                     use_extended_length, sw2);
}

bool ResponseApdu::IsSuccessful() const {
  if (2 <= data_.size()) {
    return data_[data_.size() - 2] == STATUS_OK;
  }
  LOG(WARNING) << "Called IsSuccessful() on an empty ResponseApdu";
  return true;
}

bool ResponseApdu::WaitingForNextFragment() const {
  return (data_.empty() || data_.size() == 2) && IsSuccessful();
}

bool ResponseApdu::MorePayloadIncoming() const {
  if (2 <= data_.size()) {
    return data_[data_.size() - 2] == STATUS_MORE_RESPONSE;
  }
  LOG(WARNING) << "Called MorePayloadIncoming() on an empty ResponseApdu";
  return false;
}

void ResponseApdu::RemoveStatusBytes() {
  if (2 <= data_.size()) {
    data_.pop_back();
    data_.pop_back();
  }
}

}  // namespace hermes
