// Copyright 2019 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 "arc/keymaster/conversion.h"

#include <utility>

namespace arc {
namespace keymaster {

namespace {

keymaster_key_format_t ConvertEnum(arc::mojom::KeyFormat key_format) {
  return static_cast<keymaster_key_format_t>(key_format);
}

keymaster_purpose_t ConvertEnum(arc::mojom::KeyPurpose key_purpose) {
  return static_cast<keymaster_purpose_t>(key_purpose);
}

keymaster_tag_t ConvertEnum(uint32_t tag) {
  return static_cast<keymaster_tag_t>(tag);
}

class KmParamSet {
 public:
  explicit KmParamSet(const std::vector<arc::mojom::KeyParameterPtr>& data) {
    param_set_.params = new keymaster_key_param_t[data.size()];
    param_set_.length = data.size();
    for (size_t i = 0; i < data.size(); ++i) {
      keymaster_tag_t tag = ConvertEnum(data[i]->tag);
      switch (keymaster_tag_get_type(tag)) {
        case KM_ENUM:
        case KM_ENUM_REP:
          if (data[i]->param->is_integer()) {
            param_set_.params[i] =
                keymaster_param_enum(tag, data[i]->param->get_integer());
          } else {
            param_set_.params[i].tag = KM_TAG_INVALID;
          }
          break;
        case KM_UINT:
        case KM_UINT_REP:
          if (data[i]->param->is_integer()) {
            param_set_.params[i] =
                keymaster_param_int(tag, data[i]->param->get_integer());
          } else {
            param_set_.params[i].tag = KM_TAG_INVALID;
          }
          break;
        case KM_ULONG:
        case KM_ULONG_REP:
          if (data[i]->param->is_long_integer()) {
            param_set_.params[i] =
                keymaster_param_long(tag, data[i]->param->get_long_integer());
          } else {
            param_set_.params[i].tag = KM_TAG_INVALID;
          }
          break;
        case KM_DATE:
          if (data[i]->param->is_date_time()) {
            param_set_.params[i] =
                keymaster_param_date(tag, data[i]->param->get_date_time());
          } else {
            param_set_.params[i].tag = KM_TAG_INVALID;
          }
          break;
        case KM_BOOL:
          if (data[i]->param->is_boolean_value() &&
              data[i]->param->get_boolean_value()) {
            param_set_.params[i] = keymaster_param_bool(tag);
          } else {
            param_set_.params[i].tag = KM_TAG_INVALID;
          }
          break;
        case KM_BIGNUM:
        case KM_BYTES:
          if (data[i]->param->is_blob()) {
            param_set_.params[i] =
                keymaster_param_blob(tag, data[i]->param->get_blob().data(),
                                     data[i]->param->get_blob().size());
          } else {
            param_set_.params[i].tag = KM_TAG_INVALID;
          }
          break;
        case KM_INVALID:
        default:
          param_set_.params[i].tag = KM_TAG_INVALID;
          /* just skip */
          break;
      }
    }
  }

  KmParamSet(KmParamSet&& other)
      : param_set_{other.param_set_.params, other.param_set_.length} {
    other.param_set_.length = 0;
    other.param_set_.params = nullptr;
  }
  ~KmParamSet() { delete[] param_set_.params; }

  inline const keymaster_key_param_set_t& param_set() const {
    return param_set_;
  }

 private:
  keymaster_key_param_set_t param_set_;

  DISALLOW_COPY_AND_ASSIGN(KmParamSet);
};

}  // namespace

std::unique_ptr<::keymaster::GetKeyCharacteristicsRequest>
MakeGetKeyCharacteristicsRequest(
    const ::arc::mojom::GetKeyCharacteristicsRequestPtr& value) {
  auto out = std::make_unique<::keymaster::GetKeyCharacteristicsRequest>();
  out->SetKeyMaterial(value->key_blob.data(), value->key_blob.size());
  ConvertToMessage(value->client_id, value->app_data, &out->additional_params);
  return out;
}

std::unique_ptr<::keymaster::GenerateKeyRequest> MakeGenerateKeyRequest(
    const std::vector<arc::mojom::KeyParameterPtr>& data) {
  auto out = std::make_unique<::keymaster::GenerateKeyRequest>();
  ConvertToMessage(data, &out->key_description);
  return out;
}

std::unique_ptr<::keymaster::ImportKeyRequest> MakeImportKeyRequest(
    const arc::mojom::ImportKeyRequestPtr& request) {
  auto out = std::make_unique<::keymaster::ImportKeyRequest>();
  ConvertToMessage(request->key_description, &out->key_description);

  out->key_format = ConvertEnum(request->key_format);
  out->SetKeyMaterial(request->key_data.data(), request->key_data.size());
  return out;
}

std::unique_ptr<::keymaster::ExportKeyRequest> MakeExportKeyRequest(
    const arc::mojom::ExportKeyRequestPtr& request) {
  auto out = std::make_unique<::keymaster::ExportKeyRequest>();
  out->key_format = ConvertEnum(request->key_format);
  ConvertToMessage(request->client_id, request->app_data,
                   &out->additional_params);
  out->SetKeyMaterial(request->key_blob.data(), request->key_blob.size());
  return out;
}

std::unique_ptr<::keymaster::AttestKeyRequest> MakeAttestKeyRequest(
    const arc::mojom::AttestKeyRequestPtr& request) {
  auto out = std::make_unique<::keymaster::AttestKeyRequest>();
  ConvertToMessage(request->attest_params, &out->attest_params);
  out->SetKeyMaterial(request->key_to_attest.data(),
                      request->key_to_attest.size());
  return out;
}

std::unique_ptr<::keymaster::UpgradeKeyRequest> MakeUpgradeKeyRequest(
    const arc::mojom::UpgradeKeyRequestPtr& request) {
  auto out = std::make_unique<::keymaster::UpgradeKeyRequest>();
  ConvertToMessage(request->upgrade_params, &out->upgrade_params);
  out->SetKeyMaterial(request->key_blob_to_upgrade.data(),
                      request->key_blob_to_upgrade.size());
  return out;
}

std::unique_ptr<::keymaster::BeginOperationRequest> MakeBeginOperationRequest(
    const arc::mojom::BeginRequestPtr& request) {
  auto out = std::make_unique<::keymaster::BeginOperationRequest>();
  out->purpose = ConvertEnum(request->purpose);
  out->SetKeyMaterial(request->key.data(), request->key.size());
  ConvertToMessage(request->in_params, &out->additional_params);
  return out;
}

std::unique_ptr<::keymaster::UpdateOperationRequest> MakeUpdateOperationRequest(
    const arc::mojom::UpdateRequestPtr& request) {
  auto out = std::make_unique<::keymaster::UpdateOperationRequest>();
  out->op_handle = request->op_handle;
  ConvertToMessage(request->input, &out->input);
  ConvertToMessage(request->in_params, &out->additional_params);
  return out;
}

std::unique_ptr<::keymaster::FinishOperationRequest> MakeFinishOperationRequest(
    const arc::mojom::FinishRequestPtr& request) {
  auto out = std::make_unique<::keymaster::FinishOperationRequest>();
  out->op_handle = request->op_handle;
  ConvertToMessage(request->input, &out->input);
  ConvertToMessage(request->signature, &out->signature);
  ConvertToMessage(request->in_params, &out->additional_params);
  return out;
}

arc::mojom::GetKeyCharacteristicsResultPtr MakeGetKeyCharacteristicsResult(
    const ::keymaster::GetKeyCharacteristicsResponse& km_response) {
  if (km_response.error == KM_ERROR_OK) {
    return arc::mojom::GetKeyCharacteristicsResult::New(
        arc::mojom::KeyCharacteristics::New(
            ConvertToMojo(km_response.unenforced),
            ConvertToMojo(km_response.enforced)),
        km_response.error);
  }

  return arc::mojom::GetKeyCharacteristicsResult::New(
      arc::mojom::KeyCharacteristics::New(), km_response.error);
}

arc::mojom::GenerateKeyResultPtr MakeGenerateKeyResult(
    const ::keymaster::GenerateKeyResponse& km_response) {
  if (km_response.error == KM_ERROR_OK) {
    return arc::mojom::GenerateKeyResult::New(
        ConvertToMojo(km_response.key_blob.key_material,
                      km_response.key_blob.key_material_size),
        arc::mojom::KeyCharacteristics::New(
            ConvertToMojo(km_response.unenforced),
            ConvertToMojo(km_response.enforced)),
        km_response.error);
  }

  return arc::mojom::GenerateKeyResult::New(
      std::vector<uint8_t>(), arc::mojom::KeyCharacteristics::New(),
      km_response.error);
}

arc::mojom::ImportKeyResultPtr MakeImportKeyResult(
    const ::keymaster::ImportKeyResponse& km_response) {
  if (km_response.error == KM_ERROR_OK) {
    return arc::mojom::ImportKeyResult::New(
        ConvertToMojo(km_response.key_blob.key_material,
                      km_response.key_blob.key_material_size),
        arc::mojom::KeyCharacteristics::New(
            ConvertToMojo(km_response.unenforced),
            ConvertToMojo(km_response.enforced)),
        km_response.error);
  }

  return arc::mojom::ImportKeyResult::New(std::vector<uint8_t>(),
                                          arc::mojom::KeyCharacteristics::New(),
                                          km_response.error);
}

arc::mojom::ExportKeyResultPtr MakeExportKeyResult(
    const ::keymaster::ExportKeyResponse& km_response) {
  if (km_response.error == KM_ERROR_OK) {
    return arc::mojom::ExportKeyResult::New(
        ConvertToMojo(km_response.key_data, km_response.key_data_length),
        km_response.error);
  }

  return arc::mojom::ExportKeyResult::New(std::vector<uint8_t>(),
                                          km_response.error);
}

arc::mojom::AttestKeyResultPtr MakeAttestKeyResult(
    const ::keymaster::AttestKeyResponse& km_response) {
  if (km_response.error == KM_ERROR_OK) {
    return arc::mojom::AttestKeyResult::New(
        ConvertToMojo(km_response.certificate_chain), km_response.error);
  }

  return arc::mojom::AttestKeyResult::New(std::vector<std::vector<uint8_t>>(),
                                          km_response.error);
}

arc::mojom::UpgradeKeyResultPtr MakeUpgradeKeyResult(
    const ::keymaster::UpgradeKeyResponse& km_response) {
  if (km_response.error == KM_ERROR_OK) {
    return arc::mojom::UpgradeKeyResult::New(
        ConvertToMojo(km_response.upgraded_key.key_material,
                      km_response.upgraded_key.key_material_size),
        km_response.error);
  }

  return arc::mojom::UpgradeKeyResult::New(std::vector<uint8_t>(),
                                           km_response.error);
}

arc::mojom::BeginResultPtr MakeBeginResult(
    const ::keymaster::BeginOperationResponse& km_response) {
  if (km_response.error == KM_ERROR_OK) {
    return arc::mojom::BeginResult::New(
        ConvertToMojo(km_response.output_params), km_response.op_handle,
        km_response.error);
  }

  return arc::mojom::BeginResult::New(
      std::vector<arc::mojom::KeyParameterPtr>(), km_response.op_handle,
      km_response.error);
}

arc::mojom::UpdateResultPtr MakeUpdateResult(
    const ::keymaster::UpdateOperationResponse& km_response) {
  if (km_response.error == KM_ERROR_OK) {
    return arc::mojom::UpdateResult::New(
        km_response.input_consumed, ConvertToMojo(km_response.output_params),
        ConvertToMojo(km_response.output.begin(),
                      km_response.output.available_read()),
        km_response.error);
  }

  return arc::mojom::UpdateResult::New(
      0, std::vector<arc::mojom::KeyParameterPtr>(), std::vector<uint8_t>(),
      km_response.error);
}

arc::mojom::FinishResultPtr MakeFinishResult(
    const ::keymaster::FinishOperationResponse& km_response) {
  if (km_response.error == KM_ERROR_OK) {
    return arc::mojom::FinishResult::New(
        ConvertToMojo(km_response.output_params),
        ConvertToMojo(km_response.output.begin(),
                      km_response.output.available_read()),
        km_response.error);
  }

  return arc::mojom::FinishResult::New(
      std::vector<arc::mojom::KeyParameterPtr>(), std::vector<uint8_t>(),
      km_response.error);
}

std::vector<uint8_t> ConvertToMojo(const uint8_t* data, const size_t size) {
  return std::vector<uint8_t>(data, data + size);
}

std::vector<std::vector<uint8_t>> ConvertToMojo(
    const keymaster_cert_chain_t& cert) {
  std::vector<std::vector<uint8_t>> out(cert.entry_count);
  for (size_t i = 0; i < cert.entry_count; ++i) {
    const auto& entry = cert.entries[i];
    out[i] = ConvertToMojo(entry.data, entry.data_length);
  }
  return out;
}

std::vector<arc::mojom::KeyParameterPtr> ConvertToMojo(
    const keymaster_key_param_set_t& param_set) {
  if (param_set.length == 0 || !param_set.params)
    return std::vector<arc::mojom::KeyParameterPtr>();

  std::vector<arc::mojom::KeyParameterPtr> out(param_set.length);
  keymaster_key_param_t* params = param_set.params;
  for (size_t i = 0; i < param_set.length; ++i) {
    keymaster_tag_t tag = params[i].tag;
    arc::mojom::IntegerKeyParamPtr param = arc::mojom::IntegerKeyParam::New();
    switch (keymaster_tag_get_type(tag)) {
      case KM_ENUM:
      case KM_ENUM_REP:
        param->set_integer(params[i].enumerated);
        break;
      case KM_UINT:
      case KM_UINT_REP:
        param->set_integer(params[i].integer);
        break;
      case KM_ULONG:
      case KM_ULONG_REP:
        param->set_long_integer(params[i].long_integer);
        break;
      case KM_DATE:
        param->set_date_time(params[i].date_time);
        break;
      case KM_BOOL:
        param->set_boolean_value(params[i].boolean);
        break;
      case KM_BIGNUM:
      case KM_BYTES:
        param->set_blob(
            ConvertToMojo(params[i].blob.data, params[i].blob.data_length));
        break;
      case KM_INVALID:
        tag = KM_TAG_INVALID;
        /* just skip */
        break;
    }

    out[i] = arc::mojom::KeyParameter::New(tag, std::move(param));
  }

  return out;
}

void ConvertToMessage(const std::vector<uint8_t>& data,
                      ::keymaster::Buffer* out) {
  out->Reinitialize(data.data(), data.size());
}

void ConvertToMessage(const std::vector<uint8_t>& clientId,
                      const std::vector<uint8_t>& appData,
                      ::keymaster::AuthorizationSet* params) {
  params->Clear();
  if (!clientId.empty()) {
    params->push_back(::keymaster::TAG_APPLICATION_ID, clientId.data(),
                      clientId.size());
  }
  if (!appData.empty()) {
    params->push_back(::keymaster::TAG_APPLICATION_DATA, appData.data(),
                      appData.size());
  }
}

void ConvertToMessage(const std::vector<arc::mojom::KeyParameterPtr>& data,
                      ::keymaster::AuthorizationSet* out) {
  KmParamSet param_set(data);
  out->Reinitialize(param_set.param_set());
}

}  // namespace keymaster
}  // namespace arc
