// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "arc/keymint/conversion.h"

#include <algorithm>
#include <utility>

namespace arc::keymint {

namespace {

class KmParamSet {
 public:
  explicit KmParamSet(
      const std::vector<arc::mojom::keymint::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:
          param_set_.params[i] = ConvertEnum(data[i]);
          break;
        case KM_UINT:
        case KM_UINT_REP:
          if (data[i]->value->is_integer()) {
            param_set_.params[i] =
                keymaster_param_int(tag, data[i]->value->get_integer());
          } else {
            param_set_.params[i].tag = KM_TAG_INVALID;
          }
          break;
        case KM_ULONG:
        case KM_ULONG_REP:
          if (data[i]->value->is_long_integer()) {
            param_set_.params[i] =
                keymaster_param_long(tag, data[i]->value->get_long_integer());
          } else {
            param_set_.params[i].tag = KM_TAG_INVALID;
          }
          break;
        case KM_DATE:
          if (data[i]->value->is_date_time()) {
            param_set_.params[i] =
                keymaster_param_date(tag, data[i]->value->get_date_time());
          } else {
            param_set_.params[i].tag = KM_TAG_INVALID;
          }
          break;
        case KM_BOOL:
          if (data[i]->value->is_bool_value() &&
              data[i]->value->get_bool_value()) {
            // This function takes a single argument. Default value is TRUE.
            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]->value->is_blob()) {
            param_set_.params[i] =
                keymaster_param_blob(tag, data[i]->value->get_blob().data(),
                                     data[i]->value->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(const KmParamSet&) = delete;
  KmParamSet& operator=(const KmParamSet&) = delete;

  ~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_;
};

}  // namespace

std::vector<uint8_t> authToken2AidlVec(
    const arc::mojom::keymint::HardwareAuthToken& token) {
  static_assert(
      1 /* version size */ + sizeof(token.challenge) + sizeof(token.user_id) +
              sizeof(token.authenticator_id) +
              sizeof(token.authenticator_type) + sizeof(*token.timestamp) +
              32 /* HMAC size */
          == sizeof(hw_auth_token_t),
      "HardwareAuthToken content size does not match hw_auth_token_t size");

  std::vector<uint8_t> result;

  if (token.mac.size() != 32) {
    return result;
  }

  result.resize(sizeof(hw_auth_token_t));
  auto pos = result.begin();
  *pos++ = 0;  // Version byte
  pos = copy_bytes_to_iterator(token.challenge, pos);
  pos = copy_bytes_to_iterator(token.user_id, pos);
  pos = copy_bytes_to_iterator(token.authenticator_id, pos);
  pos = copy_bytes_to_iterator(
      ::keymaster::hton(static_cast<uint32_t>(token.authenticator_type)), pos);
  pos = copy_bytes_to_iterator(
      ::keymaster::hton(token.timestamp->milli_seconds), pos);
  pos = std::copy(token.mac.data(), token.mac.data() + token.mac.size(), pos);

  return result;
}

// TODO(b/274723521) : Add more required ConvertEnum functions for KeyMint
// Server.
keymaster_tag_t ConvertEnum(arc::mojom::keymint::Tag tag) {
  return static_cast<keymaster_tag_t>(tag);
}

arc::mojom::keymint::Tag ConvertKeymasterTag(keymaster_tag_t tag) {
  return static_cast<arc::mojom::keymint::Tag>(tag);
}

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

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

keymaster_key_param_t kInvalidKeyParam{.tag = KM_TAG_INVALID, .integer = 0};

keymaster_key_param_t ConvertEnum(
    const arc::mojom::keymint::KeyParameterPtr& param) {
  if (param.is_null() || param->value.is_null()) {
    return kInvalidKeyParam;
  }

  keymaster_tag_t tag = ConvertEnum(param->tag);
  switch (tag) {
    case KM_TAG_PURPOSE:
      if (param->value->is_key_purpose() &&
          param->value->get_key_purpose() !=
              arc::mojom::keymint::KeyPurpose::UNKNOWN) {
        return keymaster_param_enum(
            tag, static_cast<uint32_t>(param->value->get_key_purpose()));
      } else {
        return kInvalidKeyParam;
      }
      break;

    case KM_TAG_ALGORITHM:
      if (param->value->is_algorithm() &&
          param->value->get_algorithm() !=
              arc::mojom::keymint::Algorithm::UNKNOWN) {
        return keymaster_param_enum(
            tag, static_cast<uint32_t>(param->value->get_algorithm()));
      } else {
        return kInvalidKeyParam;
      }
      break;

    case KM_TAG_BLOCK_MODE:
      if (param->value->is_block_mode() &&
          param->value->get_block_mode() !=
              arc::mojom::keymint::BlockMode::UNKNOWN) {
        return keymaster_param_enum(
            tag, static_cast<uint32_t>(param->value->get_block_mode()));
      } else {
        return kInvalidKeyParam;
      }
      break;

    case KM_TAG_DIGEST:
    case KM_TAG_RSA_OAEP_MGF_DIGEST:
      if (param->value->is_digest() &&
          param->value->get_digest() != arc::mojom::keymint::Digest::UNKNOWN) {
        return keymaster_param_enum(
            tag, static_cast<uint32_t>(param->value->get_digest()));
      } else {
        return kInvalidKeyParam;
      }
      break;

    case KM_TAG_PADDING:
      if (param->value->is_padding_mode() &&
          param->value->get_padding_mode() !=
              arc::mojom::keymint::PaddingMode::UNKNOWN) {
        return keymaster_param_enum(
            tag, static_cast<uint32_t>(param->value->get_padding_mode()));
      } else {
        return kInvalidKeyParam;
      }
      break;

    case KM_TAG_EC_CURVE:
      if (param->value->is_ec_curve() &&
          param->value->get_ec_curve() !=
              arc::mojom::keymint::EcCurve::UNKNOWN) {
        return keymaster_param_enum(
            tag, static_cast<uint32_t>(param->value->get_ec_curve()));
      } else {
        return kInvalidKeyParam;
      }
      break;

    case KM_TAG_USER_AUTH_TYPE:
      if (param->value->is_hardware_authenticator_type() &&
          param->value->get_hardware_authenticator_type() !=
              arc::mojom::keymint::HardwareAuthenticatorType::UNKNOWN) {
        return keymaster_param_enum(
            tag, static_cast<uint32_t>(
                     param->value->get_hardware_authenticator_type()));
      } else {
        return kInvalidKeyParam;
      }
      break;

    case KM_TAG_ORIGIN:
      if (param->value->is_origin() &&
          param->value->get_origin() !=
              arc::mojom::keymint::KeyOrigin::UNKNOWN) {
        return keymaster_param_enum(
            tag, static_cast<uint32_t>(param->value->get_origin()));
      } else {
        return kInvalidKeyParam;
      }
      break;
    // The 2 Cases below are unused.
    case KM_TAG_BLOB_USAGE_REQUIREMENTS:
    case KM_TAG_KDF:

    default:
      CHECK(false) << "Unknown or unused enum tag: Something is broken";
      LOG(ERROR) << "Unknown or unused enum tag: " << tag;
      return kInvalidKeyParam;
  }
}

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

std::vector<arc::mojom::keymint::CertificatePtr> ConvertFromKeymasterMessage(
    const ::keymaster::CertificateChain& cert_chain) {
  std::vector<arc::mojom::keymint::CertificatePtr> out;
  if (cert_chain.entry_count == 0 || cert_chain.entries == nullptr) {
    return out;
  }

  out.reserve(cert_chain.entry_count);

  for (size_t i = 0; i < cert_chain.entry_count; ++i) {
    const auto& entry = cert_chain.entries[i];
    auto cert_vector =
        ConvertFromKeymasterMessage(entry.data, entry.data_length);
    auto mojo_cert =
        arc::mojom::keymint::Certificate::New(std::move(cert_vector));
    out.push_back(std::move(mojo_cert));
  }
  return out;
}

arc::mojom::keymint::KeyParameterValuePtr ConvertEnumParamFromKeymasterMessage(
    const keymaster_key_param_t& param) {
  keymaster_tag_t tag = param.tag;
  keymaster_tag_type_t tag_type = keymaster_tag_get_type(tag);

  arc::mojom::keymint::KeyParameterValuePtr out;
  if (tag_type != KM_ENUM && tag_type != KM_ENUM_REP) {
    LOG(ERROR) << "Mismatched Tag type received. Expected ENUM or ENUM_REP";
    return arc::mojom::keymint::KeyParameterValue::NewInvalid(
        static_cast<uint32_t>(param.enumerated));
  }

  switch (tag) {
    case KM_TAG_PURPOSE:
      out = arc::mojom::keymint::KeyParameterValue::NewKeyPurpose(
          static_cast<arc::mojom::keymint::KeyPurpose>(param.enumerated));
      break;
    case KM_TAG_ALGORITHM:
      out = arc::mojom::keymint::KeyParameterValue::NewAlgorithm(
          static_cast<arc::mojom::keymint::Algorithm>(param.enumerated));
      break;
    case KM_TAG_BLOCK_MODE:
      out = arc::mojom::keymint::KeyParameterValue::NewBlockMode(
          static_cast<arc::mojom::keymint::BlockMode>(param.enumerated));
      break;
    case KM_TAG_DIGEST:
    case KM_TAG_RSA_OAEP_MGF_DIGEST:
      out = arc::mojom::keymint::KeyParameterValue::NewDigest(
          static_cast<arc::mojom::keymint::Digest>(param.enumerated));
      break;
    case KM_TAG_PADDING:
      out = arc::mojom::keymint::KeyParameterValue::NewPaddingMode(
          static_cast<arc::mojom::keymint::PaddingMode>(param.enumerated));
      break;
    case KM_TAG_EC_CURVE:
      out = arc::mojom::keymint::KeyParameterValue::NewEcCurve(
          static_cast<arc::mojom::keymint::EcCurve>(param.enumerated));
      break;
    case KM_TAG_USER_AUTH_TYPE:
      out =
          arc::mojom::keymint::KeyParameterValue::NewHardwareAuthenticatorType(
              static_cast<arc::mojom::keymint::HardwareAuthenticatorType>(
                  param.enumerated));
      break;
    case KM_TAG_ORIGIN:
      out = arc::mojom::keymint::KeyParameterValue::NewOrigin(
          static_cast<arc::mojom::keymint::KeyOrigin>(param.enumerated));
      break;

    // The 2 Cases below are unused.
    case KM_TAG_BLOB_USAGE_REQUIREMENTS:
    case KM_TAG_KDF:

    default:
      CHECK(false) << "Unknown or unused enum tag: Something is broken";
      LOG(ERROR) << "Unknown or unused enum tag: " << tag;
      out = arc::mojom::keymint::KeyParameterValue::NewInvalid(
          static_cast<uint32_t>(param.enumerated));
  }
  return out;
}

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

  std::vector<arc::mojom::keymint::KeyParameterPtr> out(param_set.length);
  const 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::keymint::KeyParameterValuePtr param;
    switch (keymaster_tag_get_type(tag)) {
      case KM_ENUM:
      case KM_ENUM_REP:
        param = ConvertEnumParamFromKeymasterMessage(params[i]);
        break;
      case KM_UINT:
      case KM_UINT_REP:
        param = arc::mojom::keymint::KeyParameterValue::NewInteger(
            params[i].integer);
        break;
      case KM_ULONG:
      case KM_ULONG_REP:
        param = arc::mojom::keymint::KeyParameterValue::NewLongInteger(
            params[i].long_integer);
        break;
      case KM_DATE:
        param = arc::mojom::keymint::KeyParameterValue::NewDateTime(
            params[i].date_time);
        break;
      case KM_BOOL:
        param = arc::mojom::keymint::KeyParameterValue::NewBoolValue(
            params[i].boolean);
        break;
      case KM_BIGNUM:
      case KM_BYTES:
        param = arc::mojom::keymint::KeyParameterValue::NewBlob(
            ConvertFromKeymasterMessage(params[i].blob.data,
                                        params[i].blob.data_length));
        break;
      case KM_INVALID:
        tag = KM_TAG_INVALID;
        // just skip
        break;
    }

    out[i] = arc::mojom::keymint::KeyParameter::New(
        static_cast<arc::mojom::keymint::Tag>(tag), std::move(param));
  }

  return out;
}

arc::mojom::keymint::KeyMintKeyBlobPtr ConvertFromKeyMintKeyBlob(
    const ::keymaster::KeymasterKeyBlob& key_blob) {
  arc::mojom::keymint::KeyMintKeyBlobPtr out;
  if (key_blob.key_material == nullptr || key_blob.key_material_size == 0) {
    return out;
  }

  out = arc::mojom::keymint::KeyMintKeyBlob::New(ConvertFromKeymasterMessage(
      key_blob.key_material, key_blob.key_material_size));
  return out;
}

arc::mojom::keymint::KeyMintBlobPtr ConvertFromKeyMintBlob(
    const ::keymaster::KeymasterBlob& blob) {
  arc::mojom::keymint::KeyMintBlobPtr out;
  if (blob.data == nullptr || blob.data_length == 0) {
    return out;
  }

  out = arc::mojom::keymint::KeyMintBlob::New(
      ConvertFromKeymasterMessage(blob.data, blob.data_length));
  return out;
}

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

void ConvertToKeymasterMessage(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 ConvertToKeymasterMessage(
    const std::vector<arc::mojom::keymint::KeyParameterPtr>& data,
    ::keymaster::AuthorizationSet* out) {
  KmParamSet param_set(data);
  out->Reinitialize(param_set.param_set());
}

std::vector<arc::mojom::keymint::KeyCharacteristicsPtr>
ConvertKeyCharacteristics(const ::keymaster::AuthorizationSet& hw_enforced,
                          const ::keymaster::AuthorizationSet& sw_enforced,
                          bool include_keystore_enforced = true) {
  // TODO(b/299981713) : Add conversion for Software Security level.
  // The current function makes the assumption that we are not using Software
  // Security Level.
  std::vector<arc::mojom::keymint::KeyCharacteristicsPtr> key_chars_array;

  // KeyMint Enforced Key Characteristics.
  auto keyMintEnforcedChars = arc::mojom::keymint::KeyCharacteristics::New(
      arc::mojom::keymint::SecurityLevel::TRUSTED_ENVIRONMENT,
      ConvertFromKeymasterMessage(hw_enforced));

  if (!keyMintEnforcedChars.is_null() &&
      !keyMintEnforcedChars->authorizations.empty()) {
    key_chars_array.push_back(std::move(keyMintEnforcedChars));
  }

  // Keystore Enforced Key characteristics.
  auto keystoreEnforcedChars = arc::mojom::keymint::KeyCharacteristics::New(
      arc::mojom::keymint::SecurityLevel::KEYSTORE,
      ConvertFromKeymasterMessage(sw_enforced));

  if (include_keystore_enforced && !keystoreEnforcedChars.is_null() &&
      !keystoreEnforcedChars->authorizations.empty()) {
    key_chars_array.push_back(std::move(keystoreEnforcedChars));
  }

  return key_chars_array;
}

// Request Methods.
std::unique_ptr<::keymaster::GetKeyCharacteristicsRequest>
MakeGetKeyCharacteristicsRequest(
    const ::arc::mojom::keymint::GetKeyCharacteristicsRequestPtr& value,
    const int32_t keymint_message_version) {
  auto out = std::make_unique<::keymaster::GetKeyCharacteristicsRequest>(
      keymint_message_version);
  out->SetKeyMaterial(value->key_blob.data(), value->key_blob.size());
  ConvertToKeymasterMessage(value->app_id, value->app_data,
                            &out->additional_params);
  return out;
}

std::unique_ptr<::keymaster::GenerateKeyRequest> MakeGenerateKeyRequest(
    const arc::mojom::keymint::GenerateKeyRequestPtr& request,
    const int32_t keymint_message_version) {
  auto out = std::make_unique<::keymaster::GenerateKeyRequest>(
      keymint_message_version);
  ConvertToKeymasterMessage(request->key_params, &out->key_description);

  // If mojo request carries an attestation key, convert it to Keymaster
  // message type.
  if (!request->attestation_key.is_null()) {
    out->attestation_signing_key_blob = ::keymaster::KeymasterKeyBlob(
        request->attestation_key->key_blob.data(),
        request->attestation_key->key_blob.size());
    ConvertToKeymasterMessage(request->attestation_key->attest_key_params,
                              &out->attest_key_params);
    out->issuer_subject = ::keymaster::KeymasterBlob(
        request->attestation_key->issuer_subject_name.data(),
        request->attestation_key->issuer_subject_name.size());
  }

  return out;
}

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

  out->key_format = ConvertEnum(request->key_format);
  out->key_data = ::keymaster::KeymasterKeyBlob(request->key_data.data(),
                                                request->key_data.size());

  // If mojo request carries an attestation key, convert it to Keymaster
  // message type.
  if (!request->attestation_key.is_null()) {
    out->attestation_signing_key_blob = ::keymaster::KeymasterKeyBlob(
        request->attestation_key->key_blob.data(),
        request->attestation_key->key_blob.size());
    ConvertToKeymasterMessage(request->attestation_key->attest_key_params,
                              &out->attest_key_params);
    out->issuer_subject = ::keymaster::KeymasterBlob(
        request->attestation_key->issuer_subject_name.data(),
        request->attestation_key->issuer_subject_name.size());
  }

  return out;
}

std::unique_ptr<::keymaster::ImportWrappedKeyRequest>
MakeImportWrappedKeyRequest(
    const arc::mojom::keymint::ImportWrappedKeyRequestPtr& request,
    const int32_t keymint_message_version) {
  auto out = std::make_unique<::keymaster::ImportWrappedKeyRequest>(
      keymint_message_version);

  out->SetWrappedMaterial(request->wrapped_key_data.data(),
                          request->wrapped_key_data.size());
  out->SetWrappingMaterial(request->wrapping_key_blob.data(),
                           request->wrapping_key_blob.size());
  out->SetMaskingKeyMaterial(request->masking_key.data(),
                             request->masking_key.size());
  ConvertToKeymasterMessage(request->unwrapping_params,
                            &out->additional_params);
  out->password_sid = request->password_sid;
  out->biometric_sid = request->biometric_sid;
  return out;
}

std::unique_ptr<::keymaster::UpgradeKeyRequest> MakeUpgradeKeyRequest(
    const arc::mojom::keymint::UpgradeKeyRequestPtr& request,
    const int32_t keymint_message_version) {
  auto out =
      std::make_unique<::keymaster::UpgradeKeyRequest>(keymint_message_version);
  ConvertToKeymasterMessage(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::UpdateOperationRequest> MakeUpdateOperationRequest(
    const arc::mojom::keymint::UpdateRequestPtr& request,
    const int32_t keymint_message_version) {
  auto out = std::make_unique<::keymaster::UpdateOperationRequest>(
      keymint_message_version);

  out->op_handle = request->op_handle;
  ConvertToKeymasterMessage(request->input, &out->input);

  std::vector<arc::mojom::keymint::KeyParameterPtr> key_param_array;
  // UpdateOperationRequest also carries TimeStampTokenPtr, which is
  // unused yet and hence not converted. However, if it is used
  // in future by the reference implementation and the AIDL interface,
  // it will be added here.
  if (request->auth_token) {
    auto tokenAsVec(authToken2AidlVec(*request->auth_token));

    auto key_param_ptr = arc::mojom::keymint::KeyParameter::New(
        static_cast<arc::mojom::keymint::Tag>(KM_TAG_AUTH_TOKEN),
        arc::mojom::keymint::KeyParameterValue::NewBlob(std::move(tokenAsVec)));

    key_param_array.push_back(std::move(key_param_ptr));
  }
  ConvertToKeymasterMessage(std::move(key_param_array),
                            &out->additional_params);
  return out;
}

std::unique_ptr<::keymaster::UpdateOperationRequest>
MakeUpdateAadOperationRequest(
    const arc::mojom::keymint::UpdateRequestPtr& request,
    const int32_t keymint_message_version) {
  auto out = std::make_unique<::keymaster::UpdateOperationRequest>(
      keymint_message_version);
  out->op_handle = request->op_handle;

  std::vector<arc::mojom::keymint::KeyParameterPtr> key_param_array;
  auto associated_data_param = arc::mojom::keymint::KeyParameter::New(
      static_cast<arc::mojom::keymint::Tag>(KM_TAG_ASSOCIATED_DATA),
      arc::mojom::keymint::KeyParameterValue::NewBlob(request->input));

  key_param_array.push_back(std::move(associated_data_param));

  // UpdateAadOperationRequest also carries TimeStampTokenPtr, which is
  // unused yet and hence not converted. However, if it is used
  // in future by the reference implementation and the AIDL interface,
  // it will be added here.
  if (request->auth_token) {
    auto tokenAsVec(authToken2AidlVec(*request->auth_token));

    auto key_param_ptr = arc::mojom::keymint::KeyParameter::New(
        static_cast<arc::mojom::keymint::Tag>(KM_TAG_AUTH_TOKEN),
        arc::mojom::keymint::KeyParameterValue::NewBlob(std::move(tokenAsVec)));

    key_param_array.push_back(std::move(key_param_ptr));
  }
  ConvertToKeymasterMessage(std::move(key_param_array),
                            &out->additional_params);
  return out;
}

std::unique_ptr<::keymaster::BeginOperationRequest> MakeBeginOperationRequest(
    const arc::mojom::keymint::BeginRequestPtr& request,
    const int32_t keymint_message_version) {
  auto out = std::make_unique<::keymaster::BeginOperationRequest>(
      keymint_message_version);
  out->purpose = ConvertEnum(request->key_purpose);
  out->SetKeyMaterial(request->key_blob.data(), request->key_blob.size());

  if (request->auth_token) {
    auto tokenAsVec(authToken2AidlVec(*request->auth_token));
    auto key_param_ptr = arc::mojom::keymint::KeyParameter::New(
        static_cast<arc::mojom::keymint::Tag>(KM_TAG_AUTH_TOKEN),
        arc::mojom::keymint::KeyParameterValue::NewBlob(std::move(tokenAsVec)));
    request->params.push_back(std::move(key_param_ptr));
  }
  ConvertToKeymasterMessage(request->params, &out->additional_params);
  return out;
}

std::unique_ptr<::keymaster::DeviceLockedRequest> MakeDeviceLockedRequest(
    bool password_only,
    const arc::mojom::keymint::TimeStampTokenPtr& timestamp_token,
    const int32_t keymint_message_version) {
  auto out = std::make_unique<::keymaster::DeviceLockedRequest>(
      keymint_message_version);

  out->passwordOnly = password_only;
  if (timestamp_token) {
    out->token.challenge = timestamp_token->challenge;
    out->token.mac = {timestamp_token->mac.data(), timestamp_token->mac.size()};

    if (!timestamp_token->timestamp) {
      LOG(ERROR) << "Timestamp token should have a valid timestamp.";
      return out;
    }
    out->token.timestamp = timestamp_token->timestamp->milli_seconds;
  }
  return out;
}

std::unique_ptr<::keymaster::FinishOperationRequest> MakeFinishOperationRequest(
    const arc::mojom::keymint::FinishRequestPtr& request,
    const int32_t keymint_message_version) {
  auto out = std::make_unique<::keymaster::FinishOperationRequest>(
      keymint_message_version);

  if (request.is_null()) {
    LOG(ERROR) << "KeyMint Error: Finish Operation Request is null";
    return out;
  }

  out->op_handle = request->op_handle;
  if (request->input.has_value()) {
    ConvertToKeymasterMessage(request->input.value(), &out->input);
  }
  if (request->signature.has_value()) {
    ConvertToKeymasterMessage(request->signature.value(), &out->signature);
  }
  std::vector<arc::mojom::keymint::KeyParameterPtr> key_param_array;
  if (request->auth_token) {
    auto tokenAsVec(authToken2AidlVec(*request->auth_token));

    auto key_param_ptr = arc::mojom::keymint::KeyParameter::New(
        static_cast<arc::mojom::keymint::Tag>(KM_TAG_AUTH_TOKEN),
        arc::mojom::keymint::KeyParameterValue::NewBlob(std::move(tokenAsVec)));

    key_param_array.push_back(std::move(key_param_ptr));
  }
  // TimeStamp Token and Confirmation Token are not used
  // here since they are not passed from the AIDL.
  // If they are added in future, they will be converted here.
  ConvertToKeymasterMessage(std::move(key_param_array),
                            &out->additional_params);
  return out;
}

std::unique_ptr<::keymaster::ComputeSharedHmacRequest>
MakeComputeSharedSecretRequest(
    const std::vector<arc::mojom::keymint::SharedSecretParametersPtr>& request,
    const int32_t keymint_message_version) {
  auto out = std::make_unique<::keymaster::ComputeSharedHmacRequest>(
      keymint_message_version);

  // Allocate memory for HmacSharingParametersArray.
  out->params_array.params_array =
      new (std::nothrow)::keymaster::HmacSharingParameters[request.size()];
  if (out->params_array.params_array == nullptr) {
    LOG(ERROR)
        << "KeyMint Error: Null Pointer received for ComputeSharedHmacRequest";
    return out;
  }
  out->params_array.num_params = request.size();

  // Transform each shared secret's nonce and seed to Keymaster request.
  for (size_t i = 0; i < request.size(); ++i) {
    out->params_array.params_array[i].seed = {request[i]->seed.data(),
                                              request[i]->seed.size()};

    // Only copy memory if the nonce size is same for the Keymaster request
    // and Shared secret parameter.
    if (sizeof(out->params_array.params_array[i].nonce) !=
        request[i]->nonce.size()) {
      LOG(ERROR)
          << "KeyMint Error: Different Nonce Size for Shared Secret Parameter";
      return out;
    }
    std::copy(request[i]->nonce.data(),
              request[i]->nonce.data() + request[i]->nonce.size(),
              out->params_array.params_array[i].nonce);
  }

  return out;
}

// Mojo Result Methods.
arc::mojom::keymint::KeyCharacteristicsArrayOrErrorPtr
MakeGetKeyCharacteristicsResult(
    const ::keymaster::GetKeyCharacteristicsResponse& km_response) {
  if (km_response.error != KM_ERROR_OK) {
    return arc::mojom::keymint::KeyCharacteristicsArrayOrError::NewError(
        km_response.error);
  }

  auto output =
      ConvertKeyCharacteristics(km_response.enforced, km_response.unenforced,
                                /* include_keystore_enforced = */ false);

  return arc::mojom::keymint::KeyCharacteristicsArrayOrError::
      NewKeyCharacteristics(std::move(output));
}

arc::mojom::keymint::KeyCreationResultOrErrorPtr MakeGenerateKeyResult(
    const ::keymaster::GenerateKeyResponse& km_response) {
  if (km_response.error != KM_ERROR_OK) {
    return arc::mojom::keymint::KeyCreationResultOrError::NewError(
        km_response.error);
  }

  // Create the Key Blob.
  auto key_blob =
      ConvertFromKeymasterMessage(km_response.key_blob.key_material,
                                  km_response.key_blob.key_material_size);

  // Create the Key Characteristics Array.
  auto key_chars_array =
      ConvertKeyCharacteristics(km_response.enforced, km_response.unenforced);

  // Create the Certificate Array.
  std::vector<arc::mojom::keymint::CertificatePtr> cert_array =
      ConvertFromKeymasterMessage(km_response.certificate_chain);

  auto key_result = arc::mojom::keymint::KeyCreationResult::New(
      std::move(key_blob), std::move(key_chars_array), std::move(cert_array));

  return arc::mojom::keymint::KeyCreationResultOrError::NewKeyCreationResult(
      std::move(key_result));
}

arc::mojom::keymint::KeyCreationResultOrErrorPtr MakeImportKeyResult(
    const ::keymaster::ImportKeyResponse& km_response) {
  if (km_response.error != KM_ERROR_OK) {
    return arc::mojom::keymint::KeyCreationResultOrError::NewError(
        km_response.error);
  }

  // Create the Key Blob.
  auto key_blob =
      ConvertFromKeymasterMessage(km_response.key_blob.key_material,
                                  km_response.key_blob.key_material_size);

  // Create the Key Characteristics Array.
  auto key_chars_array =
      ConvertKeyCharacteristics(km_response.enforced, km_response.unenforced);

  // Create the Certificate Array.
  std::vector<arc::mojom::keymint::CertificatePtr> cert_array =
      ConvertFromKeymasterMessage(km_response.certificate_chain);

  auto key_creation_result = arc::mojom::keymint::KeyCreationResult::New(
      std::move(key_blob), std::move(key_chars_array), std::move(cert_array));

  return arc::mojom::keymint::KeyCreationResultOrError::NewKeyCreationResult(
      std::move(key_creation_result));
}

arc::mojom::keymint::KeyCreationResultOrErrorPtr MakeImportWrappedKeyResult(
    const ::keymaster::ImportWrappedKeyResponse& km_response) {
  if (km_response.error != KM_ERROR_OK) {
    return arc::mojom::keymint::KeyCreationResultOrError::NewError(
        km_response.error);
  }

  // Create the Key Blob.
  auto key_blob =
      ConvertFromKeymasterMessage(km_response.key_blob.key_material,
                                  km_response.key_blob.key_material_size);

  // Create the Key Characteristics Array.
  auto key_chars_array =
      ConvertKeyCharacteristics(km_response.enforced, km_response.unenforced);

  // Create the Certificate Array.
  std::vector<arc::mojom::keymint::CertificatePtr> cert_array =
      ConvertFromKeymasterMessage(km_response.certificate_chain);

  auto key_creation_result = arc::mojom::keymint::KeyCreationResult::New(
      std::move(key_blob), std::move(key_chars_array), std::move(cert_array));

  return arc::mojom::keymint::KeyCreationResultOrError::NewKeyCreationResult(
      std::move(key_creation_result));
}

arc::mojom::keymint::ByteArrayOrErrorPtr MakeUpgradeKeyResult(
    const ::keymaster::UpgradeKeyResponse& km_response) {
  if (km_response.error != KM_ERROR_OK) {
    return arc::mojom::keymint::ByteArrayOrError::NewError(km_response.error);
  }
  // Create the Key Blob.
  auto upgraded_key_blob =
      ConvertFromKeymasterMessage(km_response.upgraded_key.key_material,
                                  km_response.upgraded_key.key_material_size);

  return arc::mojom::keymint::ByteArrayOrError::NewOutput(
      std::move(upgraded_key_blob));
}

arc::mojom::keymint::ByteArrayOrErrorPtr MakeUpdateResult(
    const ::keymaster::UpdateOperationResponse& km_response) {
  if (km_response.error != KM_ERROR_OK) {
    return arc::mojom::keymint::ByteArrayOrError::NewError(km_response.error);
  }
  // UpdateOperationResponse also carries a field - |input_consumed|,
  // which is used in keymint_server.cc file.
  // It also carries another field - |output_params|, which is a
  // part of |output| returned from here.
  auto output = ConvertFromKeymasterMessage(
      km_response.output.begin(), km_response.output.available_read());

  return arc::mojom::keymint::ByteArrayOrError::NewOutput(std::move(output));
}

arc::mojom::keymint::BeginResultOrErrorPtr MakeBeginResult(
    const ::keymaster::BeginOperationResponse& km_response) {
  if (km_response.error != KM_ERROR_OK) {
    return arc::mojom::keymint::BeginResultOrError::NewError(km_response.error);
  }

  uint64_t challenge = km_response.op_handle;
  uint64_t op_handle = km_response.op_handle;

  auto begin_result = arc::mojom::keymint::BeginResult::New(
      std::move(challenge),
      ConvertFromKeymasterMessage(km_response.output_params),
      std::move(op_handle));

  return arc::mojom::keymint::BeginResultOrError::NewBeginResult(
      std::move(begin_result));
}

arc::mojom::keymint::ByteArrayOrErrorPtr MakeFinishResult(
    const ::keymaster::FinishOperationResponse& km_response) {
  if (km_response.error != KM_ERROR_OK) {
    return arc::mojom::keymint::ByteArrayOrError::NewError(km_response.error);
  }
  auto output = ConvertFromKeymasterMessage(
      km_response.output.begin(), km_response.output.available_read());

  return arc::mojom::keymint::ByteArrayOrError::NewOutput(std::move(output));
}

arc::mojom::keymint::SharedSecretParametersOrErrorPtr
MakeGetSharedSecretParametersResult(
    const ::keymaster::GetHmacSharingParametersResponse& km_response) {
  if (km_response.error != KM_ERROR_OK) {
    return arc::mojom::keymint::SharedSecretParametersOrError::NewError(
        km_response.error);
  }

  // Create seed and nonce.
  std::vector<uint8_t> seed = ConvertFromKeymasterMessage(
      km_response.params.seed.begin(), km_response.params.seed.size());
  std::vector<uint8_t> nonce(std::begin(km_response.params.nonce),
                             std::end(km_response.params.nonce));

  auto params = arc::mojom::keymint::SharedSecretParameters::New(
      std::move(seed), std::move(nonce));

  return arc::mojom::keymint::SharedSecretParametersOrError::
      NewSecretParameters(std::move(params));
}

arc::mojom::keymint::ByteArrayOrErrorPtr MakeComputeSharedSecretResult(
    const ::keymaster::ComputeSharedHmacResponse& km_response) {
  if (km_response.error != KM_ERROR_OK) {
    return arc::mojom::keymint::ByteArrayOrError::NewError(km_response.error);
  }

  std::vector<uint8_t> result(
      km_response.sharing_check.data,
      km_response.sharing_check.data + km_response.sharing_check.data_length);
  return arc::mojom::keymint::ByteArrayOrError::NewOutput(std::move(result));
}

arc::mojom::keymint::TimeStampTokenOrErrorPtr MakeGenerateTimeStampTokenResult(
    const ::keymaster::GenerateTimestampTokenResponse& km_response) {
  if (km_response.error != KM_ERROR_OK) {
    return arc::mojom::keymint::TimeStampTokenOrError::NewError(
        km_response.error);
  }

  uint64_t challenge = km_response.token.challenge;

  auto time_stamp = arc::mojom::keymint::Timestamp::New(
      base::strict_cast<uint64_t>(km_response.token.timestamp));

  std::vector<uint8_t> mac(
      km_response.token.mac.data,
      km_response.token.mac.data + km_response.token.mac.data_length);

  auto time_stamp_token = arc::mojom::keymint::TimeStampToken::New(
      std::move(challenge), std::move(time_stamp), std::move(mac));

  return arc::mojom::keymint::TimeStampTokenOrError::NewTimestampToken(
      std::move(time_stamp_token));
}

arc::mojom::keymint::GenerateEcdsaP256KeyPairResultOrErrorPtr
MakeGenerateEcdsaP256KeyPairResult(
    const ::keymaster::GenerateRkpKeyResponse& km_response) {
  if (km_response.error != KM_ERROR_OK) {
    return arc::mojom::keymint::GenerateEcdsaP256KeyPairResultOrError::NewError(
        km_response.error);
  }

  arc::mojom::keymint::KeyMintBlobPtr maced_public_key =
      ConvertFromKeyMintBlob(km_response.maced_public_key);
  arc::mojom::keymint::KeyMintKeyBlobPtr handle_to_private_key =
      ConvertFromKeyMintKeyBlob(km_response.key_blob);
  auto result = arc::mojom::keymint::GenerateEcdsaP256KeyPairResult::New(
      std::move(maced_public_key), std::move(handle_to_private_key));

  return arc::mojom::keymint::GenerateEcdsaP256KeyPairResultOrError::
      NewKeyPairResult(std::move(result));
}

}  // namespace arc::keymint
