// 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 "u2fd/u2f_daemon.h"

#include <functional>
#include <string>
#include <sysexits.h>
#include <utility>
#include <vector>

#include <attestation/proto_bindings/interface.pb.h>
#include <attestation-client/attestation/dbus-constants.h>
#include <base/bind.h>
#include <base/optional.h>
#include <base/synchronization/waitable_event.h>
#include <bindings/chrome_device_policy.pb.h>
#include <dbus/u2f/dbus-constants.h>
#include <policy/device_policy.h>
#include <policy/libpolicy.h>
#include <trunks/cr50_headers/virtual_nvmem.h>

#include "u2fd/u2fhid.h"
#include "u2fd/uhid_device.h"

namespace u2f {

namespace em = enterprise_management;

enum class U2fMode : uint8_t {
  kUnset = em::DeviceSecondFactorAuthenticationProto_U2fMode_UNSET,
  kDisabled = em::DeviceSecondFactorAuthenticationProto_U2fMode_DISABLED,
  kU2f = em::DeviceSecondFactorAuthenticationProto_U2fMode_U2F,
  kU2fExtended = em::DeviceSecondFactorAuthenticationProto_U2fMode_U2F_EXTENDED,
};

namespace {

constexpr char kDeviceName[] = "Integrated U2F";
constexpr int kWinkSignalMinIntervalMs = 1000;

// The U2F counter stored in cr50 is stored in a format resistant to rollbacks,
// and that guarantees monotonicity even in the presence of partial writes.
// See //platform/ec/include/nvcounter.h
//
// The counter is stored across 2 pages of flash - a high page and a low page,
// with each page containing 512 4-byte words. The counter increments using
// 'strikes', with each strike occupying 4 bits. The high page can represent
// numbers 0-2048, and the low page can represent numbers 0-4096.
// The pages are interpreted as two digits of a base-4097 number, giving us
// the maximum value below.
// See //platform/ec/common/nvcounter.c for more details.
constexpr uint32_t kMaxCr50U2fCounterValue = (2048 * 4097) + 4096;
// If we are supporting legacy key handles, we initialize the counter such that
// it is always larger than the maximum possible value cr50 could have returned,
// and therefore guarantee that we provide a monotonically increasing counter
// value for migrated key handles.
constexpr uint32_t kLegacyKhCounterMin = kMaxCr50U2fCounterValue + 1;

bool U2fPolicyReady() {
  policy::PolicyProvider policy_provider;

  return policy_provider.Reload();
}

U2fMode ReadU2fPolicy() {
  policy::PolicyProvider policy_provider;

  if (!policy_provider.Reload()) {
    LOG(DFATAL) << "Failed to load device policy";
  }

  int mode = 0;
  const policy::DevicePolicy* policy = &policy_provider.GetDevicePolicy();
  if (!policy->GetSecondFactorAuthenticationMode(&mode))
    return U2fMode::kUnset;

  return static_cast<U2fMode>(mode);
}

const char* U2fModeToString(U2fMode mode) {
  switch (mode) {
    case U2fMode::kUnset:
      return "unset";
    case U2fMode::kDisabled:
      return "disabled";
    case U2fMode::kU2f:
      return "U2F";
    case U2fMode::kU2fExtended:
      return "U2F+extensions";
  }
  return "unknown";
}

U2fMode GetU2fMode(bool force_u2f, bool force_g2f) {
  U2fMode policy_mode = ReadU2fPolicy();

  LOG(INFO) << "Requested Mode: Policy[" << U2fModeToString(policy_mode)
            << "], force_u2f[" << force_u2f << "], force_g2f[" << force_g2f
            << "]";

  // Always honor the administrator request to disable even if given
  // contradictory override flags.
  if (policy_mode == U2fMode::kDisabled) {
    LOG(INFO) << "Mode: Disabled (explicitly by policy)";
    return U2fMode::kDisabled;
  }

  if (force_g2f || policy_mode == U2fMode::kU2fExtended) {
    LOG(INFO) << "Mode: U2F+extensions";
    return U2fMode::kU2fExtended;
  }

  if (force_u2f || policy_mode == U2fMode::kU2f) {
    LOG(INFO) << "Mode:U2F";
    return U2fMode::kU2f;
  }

  LOG(INFO) << "Mode: Disabled";
  return U2fMode::kDisabled;
}

void OnPolicySignalConnected(const std::string& interface,
                             const std::string& signal,
                             bool success) {
  if (!success) {
    LOG(FATAL) << "Could not connect to signal " << signal << " on interface "
               << interface;
  }
}

}  // namespace

U2fDaemon::U2fDaemon(bool force_u2f,
                     bool force_g2f,
                     bool g2f_allowlist_data,
                     bool legacy_kh_fallback,
                     uint32_t vendor_id,
                     uint32_t product_id)
    : brillo::DBusServiceDaemon(u2f::kU2FServiceName),
      force_u2f_(force_u2f),
      force_g2f_(force_g2f),
      g2f_allowlist_data_(g2f_allowlist_data),
      legacy_kh_fallback_(legacy_kh_fallback),
      vendor_id_(vendor_id),
      product_id_(product_id) {}

int U2fDaemon::OnInit() {
  int rc = brillo::DBusServiceDaemon::OnInit();
  if (rc != EX_OK)
    return rc;

  if (!InitializeDBusProxies()) {
    return EX_IOERR;
  }

  sm_proxy_->RegisterPropertyChangeCompleteSignalHandler(
      base::Bind(&U2fDaemon::TryStartService, base::Unretained(this)),
      base::Bind(&OnPolicySignalConnected));

  bool policy_ready = U2fPolicyReady();

  if (policy_ready) {
    int status = StartService();

    // If U2F is not currently enabled, we'll wait for policy updates
    // that may enable it. We don't ever disable U2F on policy updates.
    // TODO(louiscollard): Fix the above.
    if (status != EX_CONFIG)
      return status;
  }

  if (policy_ready) {
    LOG(INFO) << "U2F currently disabled, waiting for policy updates...";
  } else {
    LOG(INFO) << "Policy not available, waiting...";
  }

  return EX_OK;
}

void U2fDaemon::TryStartService(
    const std::string& /* unused dbus signal status */) {
  if (!u2fhid_ && U2fPolicyReady()) {
    int status = StartService();
    if (status != EX_OK && status != EX_CONFIG) {
      exit(status);
    }
  }
}

int U2fDaemon::StartService() {
  if (u2fhid_) {
    // Any failures in previous calls to this function would have caused the
    // program to terminate, so we can assume we have successfully started.
    return EX_OK;
  }

  U2fMode u2f_mode = GetU2fMode(force_u2f_, force_g2f_);
  if (u2f_mode == U2fMode::kDisabled) {
    return EX_CONFIG;
  }

  if (!SetVendorMode(u2f_mode)) {
    return EX_PROTOCOL;
  }

  // If g2f is enabled by policy, we always include allowlisting data.
  bool include_g2f_allowlist_data =
      g2f_allowlist_data_ || (ReadU2fPolicy() == U2fMode::kU2fExtended);

  user_state_ = std::make_unique<u2f::UserState>(
      sm_proxy_.get(), legacy_kh_fallback_ ? kLegacyKhCounterMin : 0);

  CreateU2fMsgHandler(
      u2f_mode == U2fMode::kU2fExtended /* Allow G2F Attestation */,
      include_g2f_allowlist_data);

  CreateU2fHid();

  return u2fhid_->Init() ? EX_OK : EX_PROTOCOL;
}

bool U2fDaemon::InitializeDBusProxies() {
  if (!tpm_proxy_.Init()) {
    LOG(ERROR) << "Failed to initialize trunksd DBus proxy";
    return false;
  }

  attestation_proxy_ = bus_->GetObjectProxy(
      attestation::kAttestationServiceName,
      dbus::ObjectPath(attestation::kAttestationServicePath));

  if (!attestation_proxy_) {
    LOG(ERROR) << "Failed to initialize attestationd DBus proxy";
    return false;
  }

  pm_proxy_ = std::make_unique<org::chromium::PowerManagerProxy>(bus_.get());
  sm_proxy_ =
      std::make_unique<org::chromium::SessionManagerInterfaceProxy>(bus_.get());

  return true;
}

void U2fDaemon::RegisterDBusObjectsAsync(
    brillo::dbus_utils::AsyncEventSequencer* sequencer) {
  dbus_object_.reset(new brillo::dbus_utils::DBusObject(
      nullptr, bus_, dbus::ObjectPath(u2f::kU2FServicePath)));

  auto u2f_interface = dbus_object_->AddOrGetInterface(u2f::kU2FInterface);

  wink_signal_ = u2f_interface->RegisterSignal<u2f::UserNotification>(
      u2f::kU2FUserNotificationSignal);

  // Blocking handlers for the WebAuthn DBus API.
  //
  // Requests will be handled sequentially, as will commands sent to the virtual
  // USB HID device. We are not likely to need to answer multiple requests in
  // parallel, so this limitation is unlikely to cause problems, and it removes
  // a race condition (and potential security issue?) where multiple requests
  // would be competing for user presence, and for example a request received
  // later could consume a touch of the power button that the user had intended
  // for the earlier request.

  u2f_interface->AddSimpleMethodHandler(kU2FMakeCredential,
                                        base::Unretained(&webauthn_handler_),
                                        &WebAuthnHandler::MakeCredential);

  u2f_interface->AddSimpleMethodHandler(kU2FGetAssertion,
                                        base::Unretained(&webauthn_handler_),
                                        &WebAuthnHandler::GetAssertion);

  u2f_interface->AddSimpleMethodHandler(kU2FHasCredentials,
                                        base::Unretained(&webauthn_handler_),
                                        &WebAuthnHandler::HasCredentials);

  dbus_object_->RegisterAsync(
      sequencer->GetHandler("Failed to register DBus Interface.", true));
}

void U2fDaemon::CreateU2fMsgHandler(bool allow_g2f_attestation,
                                    bool include_g2f_allowlisting_data) {
  auto user_state = std::make_unique<u2f::UserState>(
      sm_proxy_.get(), legacy_kh_fallback_ ? kLegacyKhCounterMin : 0);

  std::function<void()> request_presence = [this]() {
    IgnorePowerButtonPress();
    SendWinkSignal();
  };

  auto allowlisting_util =
      include_g2f_allowlisting_data
          ? std::make_unique<u2f::AllowlistingUtil>([this](int cert_size) {
              return GetCertifiedG2fCert(cert_size);
            })
          : std::unique_ptr<u2f::AllowlistingUtil>(nullptr);

  u2f_msg_handler_ = std::make_unique<u2f::U2fMessageHandler>(
      std::move(allowlisting_util), request_presence, user_state_.get(),
      &tpm_proxy_, &metrics_library_, allow_g2f_attestation,
      legacy_kh_fallback_);
}

void U2fDaemon::CreateU2fHid() {
  std::function<void()> send_wink = [this]() { SendWinkSignal(); };

  u2fhid_ = std::make_unique<u2f::U2fHid>(
      std::make_unique<u2f::UHidDevice>(vendor_id_, product_id_, kDeviceName,
                                        "u2fd-tpm-cr50"),
      send_wink, u2f_msg_handler_.get());
}

bool U2fDaemon::SetVendorMode(U2fMode mode) {
  uint32_t vendor_mode_rc =
      tpm_proxy_.SetU2fVendorMode(static_cast<uint8_t>(mode));

  if (vendor_mode_rc == u2f::kVendorRcNoSuchCommand) {
    LOG(WARNING) << "U2F Vendor Mode not supported in firmware, ignoring.";
  } else if (vendor_mode_rc) {
    LOG(ERROR) << "Failed to set U2F Vendor Mode.";
    return false;
  }

  return true;
}

void U2fDaemon::SendWinkSignal() {
  static base::TimeTicks last_sent;
  base::TimeDelta elapsed = base::TimeTicks::Now() - last_sent;

  if (elapsed.InMilliseconds() > kWinkSignalMinIntervalMs) {
    u2f::UserNotification notification;
    notification.set_event_type(u2f::UserNotification::TOUCH_NEEDED);

    wink_signal_.lock()->Send(notification);

    last_sent = base::TimeTicks::Now();
  }
}

void U2fDaemon::IgnorePowerButtonPress() {
  // Duration of the user presence persistence on the firmware side.
  const base::TimeDelta kPresenceTimeout = base::TimeDelta::FromSeconds(10);

  brillo::ErrorPtr err;
  // Mask the next power button press for the UI
  pm_proxy_->IgnoreNextPowerButtonPress(kPresenceTimeout.ToInternalValue(),
                                        &err, -1);
}

namespace {

constexpr char kKeyLabelEmk[] = "attest-ent-machine";

}  // namespace

base::Optional<attestation::GetCertifiedNvIndexReply>
U2fDaemon::GetCertifiedG2fCert(int g2f_cert_size) {
  if (g2f_cert_size < 1 || g2f_cert_size > VIRTUAL_NV_INDEX_G2F_CERT_SIZE) {
    LOG(ERROR)
        << "Invalid G2F cert size specified for whitelisting data request";
    return base::nullopt;
  }

  attestation::GetCertifiedNvIndexRequest request;

  request.set_nv_index(VIRTUAL_NV_INDEX_G2F_CERT);
  request.set_nv_size(g2f_cert_size);
  request.set_key_label(kKeyLabelEmk);

  brillo::ErrorPtr error;

  std::unique_ptr<dbus::Response> dbus_response =
      brillo::dbus_utils::CallMethodAndBlock(
          attestation_proxy_, attestation::kAttestationInterface,
          attestation::kGetCertifiedNvIndex, &error, request);

  if (!dbus_response) {
    LOG(ERROR) << "Failed to retrieve certified G2F cert from attestationd";
    return base::nullopt;
  }

  attestation::GetCertifiedNvIndexReply reply;

  dbus::MessageReader reader(dbus_response.get());
  if (!reader.PopArrayOfBytesAsProto(&reply)) {
    LOG(ERROR) << "Failed to parse GetCertifiedNvIndexReply";
    return base::nullopt;
  }

  if (reply.status() != attestation::AttestationStatus::STATUS_SUCCESS) {
    LOG(ERROR) << "Call get GetCertifiedNvIndex failed, status: "
               << reply.status();
    return base::nullopt;
  }

  return reply;
}

}  // namespace u2f
