// 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 "biod/cros_fp_biometrics_manager.h"

#include <utility>

#include <errno.h>
#include <poll.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <base/base64.h>
#include <base/bind.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_piece.h>
#include <base/threading/platform_thread.h>
#include <base/time/time.h>
#include <crypto/random.h>
#include <metrics/metrics_library.h>

#include "biod/biod_crypto.h"
#include "biod/biod_metrics.h"
#include "biod/cros_fp_device_factory_impl.h"
#include "biod/power_button_filter.h"

namespace {

std::string MatchResultToString(int result) {
  switch (result) {
    case EC_MKBP_FP_ERR_MATCH_NO:
      return "No match";
    case EC_MKBP_FP_ERR_MATCH_NO_INTERNAL:
      return "Internal error";
    case EC_MKBP_FP_ERR_MATCH_NO_TEMPLATES:
      return "No templates";
    case EC_MKBP_FP_ERR_MATCH_NO_LOW_QUALITY:
      return "Low quality";
    case EC_MKBP_FP_ERR_MATCH_NO_LOW_COVERAGE:
      return "Low coverage";
    case EC_MKBP_FP_ERR_MATCH_YES:
      return "Finger matched";
    case EC_MKBP_FP_ERR_MATCH_YES_UPDATED:
      return "Finger matched, template updated";
    case EC_MKBP_FP_ERR_MATCH_YES_UPDATE_FAILED:
      return "Finger matched, template updated failed";
    default:
      return "Unknown matcher result";
  }
}

std::string EnrollResultToString(int result) {
  switch (result) {
    case EC_MKBP_FP_ERR_ENROLL_OK:
      return "Success";
    case EC_MKBP_FP_ERR_ENROLL_LOW_QUALITY:
      return "Low quality";
    case EC_MKBP_FP_ERR_ENROLL_IMMOBILE:
      return "Same area";
    case EC_MKBP_FP_ERR_ENROLL_LOW_COVERAGE:
      return "Low coverage";
    case EC_MKBP_FP_ERR_ENROLL_INTERNAL:
      return "Internal error";
    default:
      return "Unknown enrollment result";
  }
}

};  // namespace

namespace biod {

using Mode = FpMode::Mode;

const std::string& CrosFpBiometricsManager::Record::GetId() const {
  CHECK(biometrics_manager_);
  CHECK(index_ < biometrics_manager_->records_.size());
  return biometrics_manager_->records_[index_].record_id;
}

const std::string& CrosFpBiometricsManager::Record::GetUserId() const {
  CHECK(biometrics_manager_);
  CHECK(index_ <= biometrics_manager_->records_.size());
  return biometrics_manager_->records_[index_].user_id;
}

const std::string& CrosFpBiometricsManager::Record::GetLabel() const {
  CHECK(biometrics_manager_);
  CHECK(index_ < biometrics_manager_->records_.size());
  return biometrics_manager_->records_[index_].label;
}

const std::vector<uint8_t>& CrosFpBiometricsManager::Record::GetValidationVal()
    const {
  CHECK(biometrics_manager_);
  CHECK(index_ <= biometrics_manager_->records_.size());
  return biometrics_manager_->records_[index_].validation_val;
}

bool CrosFpBiometricsManager::Record::SetLabel(std::string label) {
  CHECK(biometrics_manager_);
  CHECK(index_ < biometrics_manager_->records_.size());
  std::string old_label = biometrics_manager_->records_[index_].label;

  VendorTemplate tmpl;
  // TODO(vpalatin): would be faster to read it from disk
  if (!biometrics_manager_->cros_dev_->GetTemplate(index_, &tmpl))
    return false;
  biometrics_manager_->records_[index_].label = std::move(label);

  if (!biometrics_manager_->WriteRecord(*this, tmpl.data(), tmpl.size())) {
    biometrics_manager_->records_[index_].label = std::move(old_label);
    return false;
  }
  return true;
}

bool CrosFpBiometricsManager::Record::NeedsNewValidationValue() const {
  return biometrics_manager_->records_[index_].record_format_version ==
             kRecordFormatVersionNoValidationValue &&
         biometrics_manager_->records_[index_].validation_val.empty();
}

bool CrosFpBiometricsManager::Record::SupportsPositiveMatchSecret() const {
  return biometrics_manager_->use_positive_match_secret_;
}

bool CrosFpBiometricsManager::Record::Remove() {
  if (!biometrics_manager_)
    return false;
  if (index_ >= biometrics_manager_->records_.size())
    return false;

  std::vector<InternalRecord>::iterator record =
      biometrics_manager_->records_.begin() + index_;
  std::string user_id = record->user_id;

  // TODO(mqg): only delete record if user_id is primary user.
  if (!biometrics_manager_->biod_storage_.DeleteRecord(user_id,
                                                       record->record_id))
    return false;

  // We cannot remove only one record if we want to stay in sync with the MCU,
  // Clear and reload everything.
  return biometrics_manager_->ReloadAllRecords(user_id);
}

bool CrosFpBiometricsManager::ReloadAllRecords(std::string user_id) {
  // Here we need a copy of user_id because the user_id could be part of
  // records_ which is cleared in this method.
  records_.clear();
  suspicious_templates_.clear();
  cros_dev_->SetContext(user_id);
  return biod_storage_.ReadRecordsForSingleUser(user_id);
}

std::unique_ptr<CrosFpBiometricsManager> CrosFpBiometricsManager::Create(
    const scoped_refptr<dbus::Bus>& bus,
    std::unique_ptr<CrosFpDeviceFactory> cros_fp_device_factory) {
  std::unique_ptr<CrosFpBiometricsManager> biometrics_manager(
      new CrosFpBiometricsManager(PowerButtonFilter::Create(bus),
                                  std::move(cros_fp_device_factory)));
  if (!biometrics_manager->Init())
    return nullptr;

  return biometrics_manager;
}

BiometricType CrosFpBiometricsManager::GetType() {
  return BIOMETRIC_TYPE_FINGERPRINT;
}

BiometricsManager::EnrollSession CrosFpBiometricsManager::StartEnrollSession(
    std::string user_id, std::string label) {
  LOG(INFO) << __func__;
  // Another session is on-going, fail early ...
  if (!next_session_action_.is_null()) {
    LOG(ERROR) << "Another EnrollSession already exists";
    return BiometricsManager::EnrollSession();
  }

  if (records_.size() >= cros_dev_->MaxTemplateCount()) {
    LOG(ERROR) << "No space for an additional template.";
    return BiometricsManager::EnrollSession();
  }

  std::vector<uint8_t> validation_val;
  if (!RequestEnrollImage(InternalRecord{
          kRecordFormatVersion, biod_storage_.GenerateNewRecordId(),
          std::move(user_id), std::move(label), std::move(validation_val)}))
    return BiometricsManager::EnrollSession();

  return BiometricsManager::EnrollSession(session_weak_factory_.GetWeakPtr());
}

BiometricsManager::AuthSession CrosFpBiometricsManager::StartAuthSession() {
  LOG(INFO) << __func__;
  // Another session is on-going, fail early ...
  if (!next_session_action_.is_null()) {
    LOG(ERROR) << "Another AuthSession already exists";
    return BiometricsManager::AuthSession();
  }

  if (!RequestMatch())
    return BiometricsManager::AuthSession();

  return BiometricsManager::AuthSession(session_weak_factory_.GetWeakPtr());
}

std::vector<std::unique_ptr<BiometricsManager::Record>>
CrosFpBiometricsManager::GetRecords() {
  std::vector<std::unique_ptr<BiometricsManager::Record>> records;
  for (int i = 0; i < records_.size(); i++)
    records.emplace_back(std::unique_ptr<BiometricsManager::Record>(
        new Record(weak_factory_.GetWeakPtr(), i)));
  return records;
}

bool CrosFpBiometricsManager::DestroyAllRecords() {
  // Enumerate through records_ and delete each record.
  bool delete_all_records = true;
  for (auto& record : records_) {
    delete_all_records &=
        biod_storage_.DeleteRecord(record.user_id, record.record_id);
  }
  RemoveRecordsFromMemory();
  return delete_all_records;
}

void CrosFpBiometricsManager::RemoveRecordsFromMemory() {
  records_.clear();
  suspicious_templates_.clear();
  cros_dev_->ResetContext();
}

bool CrosFpBiometricsManager::ReadRecords(
    const std::unordered_set<std::string>& user_ids) {
  // TODO(mqg): delete this function and adjust parent class accordingly.
  LOG(WARNING) << __func__ << " should not be used.";
  return false;
}

bool CrosFpBiometricsManager::ReadRecordsForSingleUser(
    const std::string& user_id) {
  cros_dev_->SetContext(user_id);
  return biod_storage_.ReadRecordsForSingleUser(user_id);
}

void CrosFpBiometricsManager::SetEnrollScanDoneHandler(
    const BiometricsManager::EnrollScanDoneCallback& on_enroll_scan_done) {
  on_enroll_scan_done_ = on_enroll_scan_done;
}

void CrosFpBiometricsManager::SetAuthScanDoneHandler(
    const BiometricsManager::AuthScanDoneCallback& on_auth_scan_done) {
  on_auth_scan_done_ = on_auth_scan_done;
}

void CrosFpBiometricsManager::SetSessionFailedHandler(
    const BiometricsManager::SessionFailedCallback& on_session_failed) {
  on_session_failed_ = on_session_failed;
}

bool CrosFpBiometricsManager::SendStatsOnLogin() {
  bool rc = true;
  rc = biod_metrics_->SendEnrolledFingerCount(records_.size()) && rc;
  // Even though it looks a bit redundant with the finger count, it's easier to
  // discover and interpret.
  rc = biod_metrics_->SendFpUnlockEnabled(!records_.empty()) && rc;
  return rc;
}

void CrosFpBiometricsManager::SetDiskAccesses(bool allow) {
  biod_storage_.set_allow_access(allow);
}

bool CrosFpBiometricsManager::ResetSensor() {
  if (!cros_dev_->SetFpMode(FpMode(Mode::kResetSensor))) {
    LOG(ERROR) << "Failed to send reset_sensor command to FPMCU.";
    return false;
  }

  int retries = 50;
  bool reset_complete = false;
  while (retries--) {
    FpMode cur_mode;
    if (!cros_dev_->GetFpMode(&cur_mode)) {
      LOG(ERROR) << "Failed to query sensor state during reset.";
      return false;
    }

    if (cur_mode != FpMode(Mode::kResetSensor)) {
      reset_complete = true;
      break;
    }
    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
  }

  if (!reset_complete) {
    LOG(ERROR) << "Reset on FPMCU failed to complete.";
    return false;
  }

  if (!Init()) {
    LOG(ERROR) << "Failed to reinitialize CrosFpBiometricsManager.";
    return false;
  }

  return true;
}

bool CrosFpBiometricsManager::ResetEntropy(bool factory_init) {
  bool success = cros_dev_->InitEntropy(!factory_init);
  if (!success) {
    LOG(INFO) << "Entropy source reset failed.";
    return false;
  }
  LOG(INFO) << "Entropy source has been successfully reset.";
  return true;
}

void CrosFpBiometricsManager::EndEnrollSession() {
  LOG(INFO) << __func__;
  KillMcuSession();
}

void CrosFpBiometricsManager::EndAuthSession() {
  LOG(INFO) << __func__;
  KillMcuSession();
}

void CrosFpBiometricsManager::KillMcuSession() {
  // TODO(vpalatin): test cros_dev_->FpMode(FP_MODE_DEEPSLEEP);
  cros_dev_->SetFpMode(FpMode(Mode::kNone));
  session_weak_factory_.InvalidateWeakPtrs();
  OnTaskComplete();
}

CrosFpBiometricsManager::CrosFpBiometricsManager(
    std::unique_ptr<PowerButtonFilterInterface> power_button_filter,
    std::unique_ptr<CrosFpDeviceFactory> cros_fp_device_factory)
    : biod_metrics_(std::make_unique<BiodMetrics>()),
      session_weak_factory_(this),
      weak_factory_(this),
      power_button_filter_(std::move(power_button_filter)),
      cros_fp_device_factory_(std::move(cros_fp_device_factory)),
      biod_storage_(kCrosFpBiometricsManagerName,
                    base::Bind(&CrosFpBiometricsManager::LoadRecord,
                               base::Unretained(this))),
      use_positive_match_secret_(false) {}

CrosFpBiometricsManager::~CrosFpBiometricsManager() {}

bool CrosFpBiometricsManager::Init() {
  cros_dev_ = cros_fp_device_factory_->Create(
      base::Bind(&CrosFpBiometricsManager::OnMkbpEvent, base::Unretained(this)),
      biod_metrics_.get());
  if (cros_dev_ == nullptr)
    return false;

  use_positive_match_secret_ = cros_dev_->SupportsPositiveMatchSecret();
  return true;
}

void CrosFpBiometricsManager::OnEnrollScanDone(
    ScanResult result, const BiometricsManager::EnrollStatus& enroll_status) {
  if (!on_enroll_scan_done_.is_null())
    on_enroll_scan_done_.Run(result, enroll_status);
}

void CrosFpBiometricsManager::OnAuthScanDone(
    ScanResult result, const BiometricsManager::AttemptMatches& matches) {
  if (!on_auth_scan_done_.is_null())
    on_auth_scan_done_.Run(result, matches);
}

void CrosFpBiometricsManager::OnSessionFailed() {
  LOG(INFO) << __func__;

  if (!on_session_failed_.is_null())
    on_session_failed_.Run();
}

void CrosFpBiometricsManager::OnMkbpEvent(uint32_t event) {
  if (!next_session_action_.is_null())
    next_session_action_.Run(event);
}

bool CrosFpBiometricsManager::RequestEnrollImage(InternalRecord record) {
  next_session_action_ =
      base::Bind(&CrosFpBiometricsManager::DoEnrollImageEvent,
                 base::Unretained(this), std::move(record));
  if (!cros_dev_->SetFpMode(FpMode(Mode::kEnrollSessionEnrollImage))) {
    next_session_action_ = SessionAction();
    LOG(ERROR) << "Failed to start enrolling mode";
    return false;
  }
  return true;
}

bool CrosFpBiometricsManager::RequestEnrollFingerUp(InternalRecord record) {
  next_session_action_ =
      base::Bind(&CrosFpBiometricsManager::DoEnrollFingerUpEvent,
                 base::Unretained(this), std::move(record));
  if (!cros_dev_->SetFpMode(FpMode(Mode::kEnrollSessionFingerUp))) {
    next_session_action_ = SessionAction();
    LOG(ERROR) << "Failed to wait for finger up";
    return false;
  }
  return true;
}

bool CrosFpBiometricsManager::RequestMatch(int attempt) {
  next_session_action_ = base::Bind(&CrosFpBiometricsManager::DoMatchEvent,
                                    base::Unretained(this), attempt);
  if (!cros_dev_->SetFpMode(FpMode(Mode::kMatch))) {
    next_session_action_ = SessionAction();
    LOG(ERROR) << "Failed to start matching mode";
    return false;
  }
  return true;
}

bool CrosFpBiometricsManager::RequestMatchFingerUp() {
  next_session_action_ = base::Bind(
      &CrosFpBiometricsManager::DoMatchFingerUpEvent, base::Unretained(this));
  if (!cros_dev_->SetFpMode(FpMode(Mode::kFingerUp))) {
    next_session_action_ = SessionAction();
    LOG(ERROR) << "Failed to request finger up event";
    return false;
  }
  return true;
}

void CrosFpBiometricsManager::DoEnrollImageEvent(InternalRecord record,
                                                 uint32_t event) {
  if (!(event & EC_MKBP_FP_ENROLL)) {
    LOG(WARNING) << "Unexpected MKBP event: 0x" << std::hex << event;
    // Continue waiting for the proper event, do not abort session.
    return;
  }

  int image_result = EC_MKBP_FP_ERRCODE(event);
  LOG(INFO) << __func__ << " result: '" << EnrollResultToString(image_result)
            << "'";
  ScanResult scan_result;
  switch (image_result) {
    case EC_MKBP_FP_ERR_ENROLL_OK:
      scan_result = ScanResult::SCAN_RESULT_SUCCESS;
      break;
    case EC_MKBP_FP_ERR_ENROLL_IMMOBILE:
      scan_result = ScanResult::SCAN_RESULT_IMMOBILE;
      break;
    case EC_MKBP_FP_ERR_ENROLL_LOW_COVERAGE:
      scan_result = ScanResult::SCAN_RESULT_PARTIAL;
      break;
    case EC_MKBP_FP_ERR_ENROLL_LOW_QUALITY:
      scan_result = ScanResult::SCAN_RESULT_INSUFFICIENT;
      break;
    case EC_MKBP_FP_ERR_ENROLL_INTERNAL:
    default:
      LOG(ERROR) << "Unexpected result from capture: " << std::hex << event;
      OnSessionFailed();
      return;
  }

  int percent = EC_MKBP_FP_ENROLL_PROGRESS(event);

  if (percent < 100) {
    BiometricsManager::EnrollStatus enroll_status = {false, percent};

    OnEnrollScanDone(scan_result, enroll_status);

    // The user needs to remove the finger before the next enrollment image.
    if (!RequestEnrollFingerUp(std::move(record)))
      OnSessionFailed();

    return;
  }

  // we are done with captures, save the template.
  OnTaskComplete();

  VendorTemplate tmpl;
  if (!cros_dev_->GetTemplate(CrosFpDevice::kLastTemplate, &tmpl)) {
    LOG(ERROR) << "Failed to retrieve enrolled finger";
    OnSessionFailed();
    return;
  }

  if (use_positive_match_secret_) {
    brillo::SecureBlob secret(FP_POSITIVE_MATCH_SECRET_BYTES);
    if (!cros_dev_->GetPositiveMatchSecret(CrosFpDevice::kLastTemplate,
                                           &secret)) {
      LOG(ERROR) << "Failed to get positive match secret.";
      OnSessionFailed();
      return;
    }

    std::vector<uint8_t> validation_val;
    if (!BiodCrypto::ComputeValidationValue(secret, record.user_id,
                                            &validation_val)) {
      LOG(ERROR) << "Failed to compute validation value.";
      OnSessionFailed();
      return;
    }
    record.validation_val = std::move(validation_val);
    LOG(INFO) << "Computed validation value for enrolled finger.";
  }

  records_.emplace_back(record);
  Record current_record(weak_factory_.GetWeakPtr(), records_.size() - 1);
  if (!WriteRecord(current_record, tmpl.data(), tmpl.size())) {
    records_.pop_back();
    OnSessionFailed();
    return;
  }

  BiometricsManager::EnrollStatus enroll_status = {true, 100};
  OnEnrollScanDone(ScanResult::SCAN_RESULT_SUCCESS, enroll_status);
}

void CrosFpBiometricsManager::DoEnrollFingerUpEvent(InternalRecord record,
                                                    uint32_t event) {
  if (!(event & EC_MKBP_FP_FINGER_UP)) {
    LOG(WARNING) << "Unexpected MKBP event: 0x" << std::hex << event;
    // Continue waiting for the proper event, do not abort session.
    return;
  }

  if (!RequestEnrollImage(std::move(record)))
    OnSessionFailed();
}

void CrosFpBiometricsManager::DoMatchFingerUpEvent(uint32_t event) {
  if (!(event & EC_MKBP_FP_FINGER_UP)) {
    LOG(WARNING) << "Unexpected MKBP event: 0x" << std::hex << event;
    // Continue waiting for the proper event, do not abort session.
    return;
  }
  // The user has lifted their finger, try to match the next touch.
  if (!RequestMatch())
    OnSessionFailed();
}

bool CrosFpBiometricsManager::ValidationValueIsCorrect(uint32_t match_idx) {
  brillo::SecureBlob secret(FP_POSITIVE_MATCH_SECRET_BYTES);
  bool read_secret_success =
      cros_dev_->GetPositiveMatchSecret(match_idx, &secret);
  biod_metrics_->SendReadPositiveMatchSecretSuccess(read_secret_success);
  if (!read_secret_success) {
    LOG(ERROR) << "Failed to read positive match secret on match for finger "
               << match_idx << ".";
    return false;
  }

  std::vector<uint8_t> validation_value;
  if (!BiodCrypto::ComputeValidationValue(secret, records_[match_idx].user_id,
                                          &validation_value)) {
    LOG(ERROR) << "Got positive match secret but failed to compute validation "
                  "value for finger "
               << match_idx << ".";
    return false;
  }

  if (validation_value != records_[match_idx].validation_val) {
    LOG(ERROR) << "Validation value does not match for finger " << match_idx;
    biod_metrics_->SendPositiveMatchSecretCorrect(false);
    suspicious_templates_.emplace(match_idx);
    return false;
  }

  LOG(INFO) << "Verified validation value for finger " << match_idx;
  biod_metrics_->SendPositiveMatchSecretCorrect(true);
  suspicious_templates_.erase(match_idx);
  return true;
}

BiometricsManager::AttemptMatches CrosFpBiometricsManager::CalculateMatches(
    int match_idx, bool matched) {
  BiometricsManager::AttemptMatches matches;
  if (!matched)
    return matches;

  Record current_record(weak_factory_.GetWeakPtr(), match_idx);
  if (match_idx >= records_.size()) {
    LOG(ERROR) << "Invalid finger index " << match_idx;
    return matches;
  }

  if (!use_positive_match_secret_ || current_record.NeedsNewValidationValue() ||
      ValidationValueIsCorrect(match_idx)) {
    matches.emplace(records_[match_idx].user_id,
                    std::vector<std::string>({records_[match_idx].record_id}));
  }
  return matches;
}

CrosFpBiometricsManager::MigrationStatus
CrosFpBiometricsManager::MigrateToValidationValue(int match_idx) {
  brillo::SecureBlob secret(FP_POSITIVE_MATCH_SECRET_BYTES);
  if (!cros_dev_->GetPositiveMatchSecret(match_idx, &secret)) {
    LOG(ERROR) << "In migration to validation value: failed to read positive "
                  "match secret on match for finger "
               << match_idx << ".";
    return MigrationStatus::kError;
  }

  if (!BiodCrypto::ComputeValidationValue(
          secret, records_[match_idx].user_id,
          &records_[match_idx].validation_val)) {
    LOG(ERROR) << "In migration to validation value: failed to compute "
                  "validation value from secret on match for finger "
               << match_idx << ".";
    return MigrationStatus::kError;
  }

  return MigrationStatus::kSuccess;
}

void CrosFpBiometricsManager::DoMatchEvent(int attempt, uint32_t event) {
  if (!(event & EC_MKBP_FP_MATCH)) {
    LOG(WARNING) << "Unexpected MKBP event: 0x" << std::hex << event;
    // Continue waiting for the proper event, do not abort session.
    return;
  }

  // The user intention might be to press the power button. If so, ignore the
  // current match.
  if (power_button_filter_->ShouldFilterFingerprintMatch()) {
    LOG(INFO)
        << "Power button event seen along with fp match. Ignoring fp match.";

    // Try to match the next touch once the user lifts the finger as the client
    // is still waiting for an auth. Wait for finger up event here is to prevent
    // the following scenario.
    // 1. Display is on. Now user presses power button with an enrolled finger.
    // 3. Display goes off. biod starts auth session.
    // 4. Fp match happens and is filtered by biod. biod immediately restarts
    //    a new auth session (if we do not wait for finger up).
    // 5. fp sensor immediately sends a match event before user gets a chance to
    //    lift the finger.
    // 6. biod sees a match again and this time notifies chrome without
    //    filtering it as it has filtered one already.

    if (!RequestMatchFingerUp())
      OnSessionFailed();

    biod_metrics_->SendIgnoreMatchEventOnPowerButtonPress(true);
    return;
  }

  biod_metrics_->SendIgnoreMatchEventOnPowerButtonPress(false);
  ScanResult result;
  int match_result = EC_MKBP_FP_ERRCODE(event);

  // If the finger is positioned slightly off the sensor, retry a few times
  // before failing. Typically the user has put their finger down and is now
  // moving their finger to the correct position on the sensor. Instead of
  // immediately failing, retry until we get a good image.
  // Retry 20 times, which takes about 5 to 15s, before giving up and sending
  // an error back to the user. Assume ~1s for user noticing that no matching
  // happened, some time to move the finger on the sensor to allow a full
  // capture and another 1s for the second matching attempt. 5s gives a bit of
  // margin to avoid interrupting the user while they're moving the finger on
  // the sensor.
  const int kMaxPartialAttempts = 20;

  if (match_result == EC_MKBP_FP_ERR_MATCH_NO_LOW_COVERAGE &&
      attempt < kMaxPartialAttempts) {
    /* retry a match */
    if (!RequestMatch(attempt + 1))
      OnSessionFailed();
    return;
  }

  // Don't try to match again until the user has lifted their finger from the
  // sensor. Request the FingerUp event as soon as the HW signaled a match so it
  // doesn't attempt a new match while the host is processing the first
  // match event.
  if (!RequestMatchFingerUp()) {
    OnSessionFailed();
    return;
  }

  std::vector<int> dirty_list;
  if (match_result == EC_MKBP_FP_ERR_MATCH_YES_UPDATED) {
    std::bitset<32> dirty_bitmap(0);
    // Retrieve which templates have been updated.
    if (!cros_dev_->GetDirtyMap(&dirty_bitmap))
      LOG(ERROR) << "Failed to get updated templates map";
    // Create a list of modified template indexes from the bitmap.
    dirty_list.reserve(dirty_bitmap.count());
    for (int i = 0; dirty_bitmap.any() && i < dirty_bitmap.size(); i++)
      if (dirty_bitmap[i]) {
        dirty_list.emplace_back(i);
        dirty_bitmap.reset(i);
      }
  }

  bool matched = false;

  uint32_t match_idx = EC_MKBP_FP_MATCH_IDX(event);
  LOG(INFO) << __func__ << " result: '" << MatchResultToString(match_result)
            << "' (finger: " << match_idx << ")";
  switch (match_result) {
    case EC_MKBP_FP_ERR_MATCH_NO_TEMPLATES:
      LOG(ERROR) << "No templates to match: " << std::hex << event;
      result = ScanResult::SCAN_RESULT_SUCCESS;
      break;
    case EC_MKBP_FP_ERR_MATCH_NO_INTERNAL:
      LOG(ERROR) << "Internal error when matching templates: " << std::hex
                 << event;
      result = ScanResult::SCAN_RESULT_SUCCESS;
      break;
    case EC_MKBP_FP_ERR_MATCH_NO:
      // This is the API: empty matches but still SCAN_RESULT_SUCCESS.
      result = ScanResult::SCAN_RESULT_SUCCESS;
      break;
    case EC_MKBP_FP_ERR_MATCH_YES:
    case EC_MKBP_FP_ERR_MATCH_YES_UPDATED:
    case EC_MKBP_FP_ERR_MATCH_YES_UPDATE_FAILED:
      result = ScanResult::SCAN_RESULT_SUCCESS;
      matched = true;
      break;
    case EC_MKBP_FP_ERR_MATCH_NO_LOW_QUALITY:
      result = ScanResult::SCAN_RESULT_INSUFFICIENT;
      break;
    case EC_MKBP_FP_ERR_MATCH_NO_LOW_COVERAGE:
      result = ScanResult::SCAN_RESULT_PARTIAL;
      break;
    default:
      LOG(ERROR) << "Unexpected result from matching templates: " << std::hex
                 << event;
      OnSessionFailed();
      return;
  }

  BiometricsManager::AttemptMatches matches =
      CalculateMatches(match_idx, matched);
  if (matches.empty())
    matched = false;

  Record current_record(weak_factory_.GetWeakPtr(), match_idx);
  MigrationStatus migration_status;
  if (use_positive_match_secret_ && current_record.NeedsNewValidationValue()) {
    migration_status = MigrateToValidationValue(match_idx);
    if (migration_status == MigrationStatus::kError)
      matched = false;
  } else {
    migration_status = MigrationStatus::kNotDoingMigration;
  }

  // Fetch template even if it's not updated so that we have the
  // positive_match_salt.
  if (migration_status == MigrationStatus::kSuccess &&
      std::find(dirty_list.begin(), dirty_list.end(), match_idx) ==
          dirty_list.end())
    dirty_list.emplace_back(match_idx);

  // Send back the result directly (as we are running on the main thread).
  OnAuthScanDone(result, std::move(matches));

  int capture_ms, matcher_ms, overall_ms;
  if (cros_dev_->GetFpStats(&capture_ms, &matcher_ms, &overall_ms)) {
    biod_metrics_->SendFpLatencyStats(matched, capture_ms, matcher_ms,
                                      overall_ms);
  }

  // Record updated templates
  // TODO(vpalatin): this is slow, move to end of session ?
  for (int i : dirty_list) {
    // If the template previously came with wrong validation value, do not
    // accept it until it comes with correct validation value.
    if (suspicious_templates_.find(i) != suspicious_templates_.end())
      continue;
    // If we are doing migration and already have an error, do not write the
    // template into record.
    if (i == match_idx && migration_status == MigrationStatus::kError)
      continue;

    VendorTemplate templ;
    bool rc = cros_dev_->GetTemplate(i, &templ);
    LOG(INFO) << "Retrieve updated template " << i << " -> " << rc;
    if (!rc) {
      if (i == match_idx && migration_status == MigrationStatus::kSuccess)
        migration_status = MigrationStatus::kError;
      continue;
    }

    Record current_record(weak_factory_.GetWeakPtr(), i);
    if (!WriteRecord(current_record, templ.data(), templ.size())) {
      LOG(ERROR) << "Cannot update record " << records_[i].record_id
                 << " in storage during AuthSession because writing failed.";
      if (i == match_idx && migration_status == MigrationStatus::kSuccess)
        migration_status = MigrationStatus::kError;
      continue;
    }
  }

  if (migration_status == MigrationStatus::kSuccess) {
    LOG(INFO) << "Successfully migrated record "
              << records_[match_idx].record_id << " to have validation value.";
    biod_metrics_->SendMigrationForPositiveMatchSecretResult(true);
  } else if (migration_status == MigrationStatus::kError) {
    // If in migration we never succeeded to fetch template (with new
    // positive_match_salt) and write it to record before biod stops, the
    // template on record would remain kRecordFormatVersionNoValidationValue and
    // has empty validation value, and will be migrated next time biod starts.
    LOG(ERROR) << "Failed to migrate record " << records_[match_idx].record_id
               << " to have validation value.";
    biod_metrics_->SendMigrationForPositiveMatchSecretResult(false);
  }
}

void CrosFpBiometricsManager::OnTaskComplete() {
  next_session_action_ = SessionAction();
}

void CrosFpBiometricsManager::InsertEmptyPositiveMatchSalt(
    VendorTemplate* tmpl) {
  tmpl->resize(tmpl->size() + FP_POSITIVE_MATCH_SALT_BYTES);
}

bool CrosFpBiometricsManager::LoadRecord(
    int record_format_version,
    const std::string& user_id,
    const std::string& label,
    const std::string& record_id,
    const std::vector<uint8_t>& validation_val,
    const base::Value& data) {
  std::string tmpl_data_base64;
  if (!data.GetAsString(&tmpl_data_base64)) {
    LOG(ERROR) << "Cannot load data string from record " << record_id << ".";
    return false;
  }

  base::StringPiece tmpl_data_base64_sp(tmpl_data_base64);
  std::string tmpl_data_str;
  base::Base64Decode(tmpl_data_base64_sp, &tmpl_data_str);

  if (records_.size() >= cros_dev_->MaxTemplateCount()) {
    LOG(ERROR) << "No space to upload template from " << record_id << ".";
    return false;
  }

  biod_metrics_->SendRecordFormatVersion(record_format_version);
  LOG(INFO) << "Upload record " << record_id;
  VendorTemplate tmpl(tmpl_data_str.begin(), tmpl_data_str.end());
  auto* metadata =
      reinterpret_cast<const ec_fp_template_encryption_metadata*>(tmpl.data());
  if (metadata->struct_version != cros_dev_->TemplateVersion()) {
    bool should_migrate =
        (metadata->struct_version == 3 && cros_dev_->TemplateVersion() == 4);
    if (!use_positive_match_secret_ || !should_migrate) {
      LOG(ERROR) << "use_positive_match_secret_ = "
                 << use_positive_match_secret_
                 << ", should_migrate = " << should_migrate
                 << ". Version mismatch between template ("
                 << metadata->struct_version << ") and hardware ("
                 << cros_dev_->TemplateVersion() << ")";
      biod_storage_.DeleteRecord(user_id, record_id);
      return false;
    }
    if (should_migrate)
      InsertEmptyPositiveMatchSalt(&tmpl);
  }
  if (!cros_dev_->UploadTemplate(tmpl)) {
    LOG(ERROR) << "Cannot send template to the MCU from " << record_id << ".";
    return false;
  }

  InternalRecord internal_record = {record_format_version, record_id, user_id,
                                    label, validation_val};
  records_.emplace_back(std::move(internal_record));
  return true;
}

bool CrosFpBiometricsManager::WriteRecord(
    const BiometricsManager::Record& record,
    uint8_t* tmpl_data,
    size_t tmpl_size) {
  base::StringPiece tmpl_sp(reinterpret_cast<char*>(tmpl_data), tmpl_size);
  std::string tmpl_base64;
  base::Base64Encode(tmpl_sp, &tmpl_base64);

  return biod_storage_.WriteRecord(record,
                                   std::make_unique<base::Value>(tmpl_base64));
}
}  // namespace biod
