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

#include "secagentd/plugins.h"

#include <unistd.h>

#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <sys/utsname.h>

#if __has_include(<asm/bootparam.h>)
#include <asm/bootparam.h>
#define HAVE_BOOTPARAM
#endif
#include "attestation/proto_bindings/interface.pb.h"
#include "attestation-client/attestation/dbus-proxies.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "missive/proto/record_constants.pb.h"
#include "secagentd/device_user.h"
#include "secagentd/message_sender.h"
#include "secagentd/proto/security_xdr_events.pb.h"
#include "tpm_manager/proto_bindings/tpm_manager.pb.h"
#include "vboot/crossystem.h"

namespace {

constexpr int kWaitForServicesTimeoutMs = 2000;

std::string TpmPropertyToStr(uint32_t value) {
  std::string str;

  for (int i = 0, shift = 24; i < 4; i++, shift -= 8) {
    auto c = static_cast<char>((value >> shift) & 0xFF);
    if (c == 0)
      break;
    str.push_back((c >= 32 && c < 127) ? c : ' ');
  }

  return str;
}
}  // namespace

namespace secagentd {

namespace pb = cros_xdr::reporting;

AgentPlugin::AgentPlugin(
    scoped_refptr<MessageSenderInterface> message_sender,
    scoped_refptr<DeviceUserInterface> device_user,
    std::unique_ptr<org::chromium::AttestationProxyInterface> attestation_proxy,
    std::unique_ptr<org::chromium::TpmManagerProxyInterface> tpm_manager_proxy,
    base::OnceCallback<void()> cb,
    uint32_t heartbeat_timer)
    : AgentPlugin(message_sender,
                  device_user,
                  std::move(attestation_proxy),
                  std::move(tpm_manager_proxy),
                  std::move(cb),
                  base::FilePath("/"),
                  heartbeat_timer) {}

AgentPlugin::AgentPlugin(
    scoped_refptr<MessageSenderInterface> message_sender,
    scoped_refptr<DeviceUserInterface> device_user,
    std::unique_ptr<org::chromium::AttestationProxyInterface> attestation_proxy,
    std::unique_ptr<org::chromium::TpmManagerProxyInterface> tpm_manager_proxy,
    base::OnceCallback<void()> cb,
    const base::FilePath& root_path,
    uint32_t heartbeat_timer)
    : weak_ptr_factory_(this),
      message_sender_(message_sender),
      device_user_(device_user),
      attestation_proxy_(std::move(attestation_proxy)),
      tpm_manager_proxy_((std::move(tpm_manager_proxy))),
      daemon_cb_(std::move(cb)),
      root_path_(root_path),
      heartbeat_timer_(base::Seconds(std::max(heartbeat_timer, uint32_t(1)))) {
  CHECK(message_sender != nullptr);
}

std::string AgentPlugin::GetName() const {
  return "Agent";
}

absl::Status AgentPlugin::Activate() {
  if (is_active_) {
    // Calling activate on an activated plugin does nothing.
    return absl::OkStatus();
  }
  StartInitializingAgentProto();
  base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&AgentPlugin::SendStartEvent,
                     weak_ptr_factory_.GetWeakPtr()),
      // Add delay for tpm_manager and attestation to initialize.
      base::Seconds(1));

  is_active_ = true;
  return absl::OkStatus();
}

absl::Status AgentPlugin::Deactivate() {
  return absl::UnimplementedError(
      "Deactivate is not implemented for Agent Plugin");
}

void AgentPlugin::StartInitializingAgentProto() {
  attestation_proxy_->GetObjectProxy()->WaitForServiceToBeAvailable(
      base::BindOnce(&AgentPlugin::AttestationCb,
                     weak_ptr_factory_.GetWeakPtr()));
  tpm_manager_proxy_->GetObjectProxy()->WaitForServiceToBeAvailable(
      base::BindOnce(&AgentPlugin::TpmCb, weak_ptr_factory_.GetWeakPtr()));

  char buffer[VB_MAX_STRING_PROPERTY];
  auto get_fwid_rv =
      VbGetSystemPropertyString("fwid", buffer, std::size(buffer));

  // Get linux version.
  struct utsname buf;
  int get_uname_rv = uname(&buf);

  auto uefi_metric =
      GetUefiSecureBootInformation(root_path_.Append(kBootDataFilepath));
  MetricsSender::GetInstance().SendEnumMetricToUMA(metrics::kUefiBootmode,
                                                   uefi_metric);

  base::AutoLock lock(tcb_attributes_lock_);
  if (get_fwid_rv == 0) {
    tcb_attributes_.set_system_firmware_version(buffer);
  } else {
    LOG(ERROR) << "Failed to retrieve fwid";
  }
  if (!get_uname_rv) {
    tcb_attributes_.set_linux_kernel_version(buf.release);
  } else {
    LOG(ERROR) << "Failed to retrieve uname";
  }
}

metrics::UefiBootmode AgentPlugin::GetUefiSecureBootInformation(
    const base::FilePath& boot_params_filepath) {
#ifdef HAVE_BOOTPARAM
  std::string content;

  if (!base::ReadFileToStringWithMaxSize(boot_params_filepath, &content,
                                         sizeof(boot_params))) {
    LOG(ERROR) << "Failed to read file: " << boot_params_filepath.value();
    return metrics::UefiBootmode::kFailedToReadBootParams;
  }
  if (content.size() != sizeof(boot_params)) {
    LOG(ERROR) << boot_params_filepath.value()
               << " boot params invalid file size";
    return metrics::UefiBootmode::kBootParamInvalidSize;
  }
  const boot_params* boot =
      reinterpret_cast<const boot_params*>(content.c_str());

  // defined in kernel's include/linux/efi.h
  static constexpr int kEfiSecurebootModeEnabled = 3;
  if (boot->secure_boot == kEfiSecurebootModeEnabled) {
    base::AutoLock lock(tcb_attributes_lock_);
    tcb_attributes_.set_firmware_secure_boot(
        pb::TcbAttributes_FirmwareSecureBoot_CROS_FLEX_UEFI_SECURE_BOOT);
  }
  return metrics::UefiBootmode::kSuccess;
#else
  LOG(WARNING)
      << "Header bootparam.h is not present. Assuming not uefi secure boot.";
  return metrics::UefiBootmode::kFileNotFound;
#endif
}

void AgentPlugin::AttestationCb(bool available) {
  auto metric = GetCrosSecureBootInformation(available);
  MetricsSender::GetInstance().SendEnumMetricToUMA(metrics::kCrosBootmode,
                                                   metric);
}

metrics::CrosBootmode AgentPlugin::GetCrosSecureBootInformation(
    bool available) {
  if (!available) {
    LOG(ERROR) << "Failed waiting for attestation to become available";
    return metrics::CrosBootmode::kUnavailable;
  }

  // Get boot information.
  attestation::GetStatusRequest request;
  attestation::GetStatusReply out_reply;
  brillo::ErrorPtr error;

  if (!attestation_proxy_->GetStatus(request, &out_reply, &error,
                                     kWaitForServicesTimeoutMs) ||
      error.get()) {
    LOG(ERROR) << "Failed to get boot information " << error->GetMessage();
    return metrics::CrosBootmode::kFailedRetrieval;
  }

  base::AutoLock lock(tcb_attributes_lock_);
  if (out_reply.verified_boot()) {
    tcb_attributes_.set_firmware_secure_boot(
        pb::TcbAttributes_FirmwareSecureBoot_CROS_VERIFIED_BOOT);
  } else {
    if (!tcb_attributes_.has_firmware_secure_boot()) {
      tcb_attributes_.set_firmware_secure_boot(
          pb::TcbAttributes_FirmwareSecureBoot_NONE);
    }
  }

  return metrics::CrosBootmode::kSuccess;
}

void AgentPlugin::TpmCb(bool available) {
  auto metric = GetTpmInformation(available);
  MetricsSender::GetInstance().SendEnumMetricToUMA(metrics::kTpm, metric);
}

metrics::Tpm AgentPlugin::GetTpmInformation(bool available) {
  if (!available) {
    LOG(ERROR) << "Failed waiting for tpm_manager to become available";
    return metrics::Tpm::kUnavailable;
  }

  // Check if TPM is enabled.
  tpm_manager::GetTpmNonsensitiveStatusRequest status_request;
  tpm_manager::GetTpmNonsensitiveStatusReply status_reply;
  brillo::ErrorPtr error;

  if (!tpm_manager_proxy_->GetTpmNonsensitiveStatus(
          status_request, &status_reply, &error, kWaitForServicesTimeoutMs) ||
      error.get()) {
    LOG(ERROR) << "Failed to get TPM status " << error->GetMessage();
    return metrics::Tpm::kFailedRetrieval;
  }
  if (!status_reply.is_enabled()) {
    LOG(INFO) << "TPM is disabled on device";
    return metrics::Tpm::kSuccess;
  }

  // Get TPM information.
  tpm_manager::GetVersionInfoRequest version_request;
  tpm_manager::GetVersionInfoReply version_reply;

  if (!tpm_manager_proxy_->GetVersionInfo(version_request, &version_reply,
                                          &error, kWaitForServicesTimeoutMs) ||
      error.get()) {
    LOG(ERROR) << "Failed to get TPM information " << error->GetMessage();
    return metrics::Tpm::kFailedRetrieval;
  }

  base::AutoLock lock(tcb_attributes_lock_);
  auto security_chip = tcb_attributes_.mutable_security_chip();
  if (version_reply.has_gsc_version()) {
    switch (version_reply.gsc_version()) {
      case tpm_manager::GSC_VERSION_NOT_GSC: {
        security_chip->set_kind(pb::TcbAttributes_SecurityChip::Kind::
                                    TcbAttributes_SecurityChip_Kind_TPM);
        break;
      }
      case tpm_manager::GSC_VERSION_CR50:
      case tpm_manager::GSC_VERSION_TI50:
        security_chip->set_kind(
            pb::TcbAttributes_SecurityChip::Kind::
                TcbAttributes_SecurityChip_Kind_GOOGLE_SECURITY_CHIP);
    }
    auto family = TpmPropertyToStr(version_reply.family());
    auto level =
        std::to_string((version_reply.spec_level() >> 32) & 0xffffffff);
    security_chip->set_chip_version(base::StringPrintf(
        "%s.%s.%s", family.c_str(), level.c_str(),
        std::to_string(version_reply.spec_level() & 0xffffffff).c_str()));
    security_chip->set_spec_family(family);
    security_chip->set_spec_level(level);
    security_chip->set_manufacturer(
        TpmPropertyToStr(version_reply.manufacturer()));
    security_chip->set_vendor_id(version_reply.vendor_specific());
    security_chip->set_tpm_model(std::to_string(version_reply.tpm_model()));
    security_chip->set_firmware_version(
        std::to_string(version_reply.firmware_version()));
  } else {
    security_chip->set_kind(pb::TcbAttributes_SecurityChip::Kind::
                                TcbAttributes_SecurityChip_Kind_NONE);
  }

  return metrics::Tpm::kSuccess;
}

void AgentPlugin::SendAgentEvent(bool is_agent_start) {
  auto agent_event = std::make_unique<pb::AgentEventAtomicVariant>();
  base::AutoLock lock(tcb_attributes_lock_);

  if (is_agent_start) {
    agent_event->mutable_agent_start()->mutable_tcb()->CopyFrom(
        tcb_attributes_);
  } else {
    agent_event->mutable_agent_heartbeat()->mutable_tcb()->CopyFrom(
        tcb_attributes_);
  }
  agent_event->mutable_common()->set_create_timestamp_us(
      base::Time::Now().InMillisecondsSinceUnixEpoch() *
      base::Time::kMicrosecondsPerMillisecond);
  device_user_->GetDeviceUserAsync(
      base::BindOnce(&AgentPlugin::OnDeviceUserRetrieved,
                     weak_ptr_factory_.GetWeakPtr(), std::move(agent_event)));
}

void AgentPlugin::OnDeviceUserRetrieved(
    std::unique_ptr<pb::AgentEventAtomicVariant> agent_event,
    const std::string& device_user) {
  agent_event->mutable_common()->set_device_user(device_user);
  auto xdr_proto = std::make_unique<pb::XdrAgentEvent>();
  auto batched_event = xdr_proto->add_batched_events();

  base::OnceCallback<void(reporting::Status)> cb;
  if (agent_event->has_agent_start()) {
    batched_event->set_allocated_agent_start(
        agent_event->release_agent_start());
    cb = base::BindOnce(&AgentPlugin::StartEventStatusCallback,
                        weak_ptr_factory_.GetWeakPtr());
  } else {
    batched_event->set_allocated_agent_heartbeat(
        agent_event->release_agent_heartbeat());
    cb = base::DoNothingAs<void(reporting::Status)>();
  }
  batched_event->set_allocated_common(agent_event->release_common());

  message_sender_->SendMessage(reporting::CROS_SECURITY_AGENT,
                               xdr_proto->mutable_common(),
                               std::move(xdr_proto), std::move(cb));
}

void AgentPlugin::StartEventStatusCallback(reporting::Status status) {
  if (status.ok()) {
    // Start heartbeat timer.
    agent_heartbeat_timer_.Start(
        FROM_HERE, heartbeat_timer_,
        base::BindRepeating(&AgentPlugin::SendHeartbeatEvent,
                            weak_ptr_factory_.GetWeakPtr()));

    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, std::move(daemon_cb_));
  } else {
    LOG(ERROR) << "Agent Start failed to send. Will retry in 3s.";
    base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&AgentPlugin::SendStartEvent,
                       weak_ptr_factory_.GetWeakPtr()),
        base::Seconds(3));
  }
}

}  // namespace secagentd
