// Copyright 2020 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/webauthn_storage.h"

#include <memory>
#include <optional>
#include <utility>
#include <vector>

#include <base/base64.h>
#include <base/check.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include <base/files/important_file_writer.h>
#include <base/json/json_reader.h>
#include <base/json/json_string_value_serializer.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/values.h>

#include "brillo/scoped_umask.h"
#include "u2fd/util.h"

namespace u2f {

using base::FilePath;

namespace {

constexpr const char kDaemonStorePath[] = "/run/daemon-store/u2f";
constexpr const char kWebAuthnDirName[] = "webauthn";
constexpr const char kRecordFileNamePrefix[] = "Record_";

// Members of the JSON file
constexpr const char kCredentialIdKey[] = "credential_id";
constexpr const char kSecretKey[] = "secret";
constexpr const char kKeyBlobKey[] = "key_blob";
constexpr const char kRpIdKey[] = "rp_id";
constexpr const char kRpDisplayNameKey[] = "rp_display_name";
constexpr const char kUserIdKey[] = "user_id";
constexpr const char kUserDisplayNameKey[] = "user_display_name";
constexpr const char kCreatedTimestampKey[] = "created";
constexpr const char kIsResidentKeyKey[] = "is_resident_key";

constexpr char kWebAuthnRecordCountMetric[] =
    "WebAuthentication.ChromeOS.StartupRecordCount";
constexpr int kMinRecordCount = 0;
constexpr int kMaxRecordCount = 50;
constexpr int kRecordCountBuckets = 50;

}  // namespace

WebAuthnStorage::WebAuthnStorage() : root_path_(kDaemonStorePath) {}
WebAuthnStorage::~WebAuthnStorage() = default;

bool WebAuthnStorage::WriteRecord(const WebAuthnRecord& record) {
  DCHECK(allow_access_ && !sanitized_user_.empty());

  const std::string credential_id_hex =
      base::HexEncode(record.credential_id.data(), record.credential_id.size());

  if (record.secret.size() != kCredentialSecretSize) {
    LOG(ERROR) << "Wrong secret size in record with id " << credential_id_hex;
    return false;
  }

  base::Value record_value(base::Value::Type::DICTIONARY);
  record_value.SetStringKey(kCredentialIdKey, credential_id_hex);
  record_value.SetStringKey(kSecretKey, base::Base64Encode(record.secret));
  record_value.SetStringKey(kKeyBlobKey, base::Base64Encode(record.key_blob));
  record_value.SetStringKey(kRpIdKey, record.rp_id);
  record_value.SetStringKey(kRpDisplayNameKey, record.rp_display_name);
  record_value.SetStringKey(kUserIdKey, base::HexEncode(record.user_id.data(),
                                                        record.user_id.size()));
  record_value.SetStringKey(kUserDisplayNameKey, record.user_display_name);
  record_value.SetDoubleKey(kCreatedTimestampKey, record.timestamp);
  record_value.SetBoolKey(kIsResidentKeyKey, record.is_resident_key);

  std::string json_string;
  JSONStringValueSerializer json_serializer(&json_string);
  if (!json_serializer.Serialize(record_value)) {
    LOG(ERROR) << "Failed to serialize record with id " << credential_id_hex
               << " to JSON.";
    return false;
  }

  // Use the hash of credential_id for the filename because the hex encode of
  // credential_id itself is too long and would cause ENAMETOOLONG.
  const std::vector<uint8_t> credential_id_hash =
      util::Sha256(record.credential_id);
  std::vector<FilePath> paths = {
      FilePath(sanitized_user_), FilePath(kWebAuthnDirName),
      FilePath(kRecordFileNamePrefix +
               base::HexEncode(credential_id_hash.data(),
                               credential_id_hash.size()))};

  FilePath record_storage_filename = root_path_;
  for (const auto& path : paths) {
    DCHECK(!path.IsAbsolute());
    record_storage_filename = record_storage_filename.Append(path);
  }

  {
    brillo::ScopedUmask owner_only_umask(~(0700));

    if (!base::CreateDirectory(record_storage_filename.DirName())) {
      PLOG(ERROR) << "Cannot create directory: "
                  << record_storage_filename.DirName().value() << ".";
      return false;
    }
  }

  {
    brillo::ScopedUmask owner_only_umask(~(0600));

    if (!base::ImportantFileWriter::WriteFileAtomically(record_storage_filename,
                                                        json_string)) {
      LOG(ERROR) << "Failed to write JSON file: "
                 << record_storage_filename.value() << ".";
      return false;
    }
  }

  LOG(INFO) << "Done writing record with id " << credential_id_hex
            << " to file successfully. ";

  records_.emplace_back(record);
  return true;
}

bool WebAuthnStorage::LoadRecords() {
  DCHECK(allow_access_ && !sanitized_user_.empty());

  FilePath webauthn_path =
      root_path_.Append(sanitized_user_).Append(kWebAuthnDirName);
  base::FileEnumerator enum_records(webauthn_path, false,
                                    base::FileEnumerator::FILES,
                                    std::string(kRecordFileNamePrefix) + "*");
  bool read_all_records_successfully = true;
  for (FilePath record_path = enum_records.Next(); !record_path.empty();
       record_path = enum_records.Next()) {
    std::string json_string;
    if (!base::ReadFileToString(record_path, &json_string)) {
      LOG(ERROR) << "Failed to read the string from " << record_path.value()
                 << ".";
      read_all_records_successfully = false;
      continue;
    }

    auto record_value = base::JSONReader::ReadAndReturnValueWithError(
        json_string, base::JSON_ALLOW_TRAILING_COMMAS);

    if (!record_value.value) {
      LOG(ERROR) << "Error in deserializing JSON from path "
                 << record_path.value();
      LOG_IF(ERROR, !record_value.error_message.empty())
          << "JSON error message: " << record_value.error_message << ".";
      read_all_records_successfully = false;
      continue;
    }

    if (!record_value.value->is_dict()) {
      LOG(ERROR) << "Value " << record_path.value() << " is not a dictionary.";
      read_all_records_successfully = false;
      continue;
    }
    base::Value record_dictionary = std::move(*record_value.value);

    const std::string* credential_id_hex =
        record_dictionary.FindStringKey(kCredentialIdKey);
    std::string credential_id;
    if (!credential_id_hex ||
        !base::HexStringToString(*credential_id_hex, &credential_id)) {
      LOG(ERROR) << "Cannot read credential_id from " << record_path.value()
                 << ".";
      read_all_records_successfully = false;
      continue;
    }

    const std::string* secret_base64 =
        record_dictionary.FindStringKey(kSecretKey);
    std::string secret;
    if (!secret_base64 || !base::Base64Decode(*secret_base64, &secret)) {
      LOG(ERROR) << "Cannot read credential secret from " << record_path.value()
                 << ".";
      read_all_records_successfully = false;
      continue;
    }

    const std::string* key_blob_base64 =
        record_dictionary.FindStringKey(kKeyBlobKey);
    std::string key_blob;
    // key blob can be empty for backward compatibility. New key blobs generated
    // in gsc case are empty strings.
    if (key_blob_base64 && !base::Base64Decode(*key_blob_base64, &key_blob)) {
      LOG(ERROR) << "Failed to decode credential secret from "
                 << record_path.value() << ".";
      read_all_records_successfully = false;
      continue;
    }

    const std::string* rp_id = record_dictionary.FindStringKey(kRpIdKey);
    if (!rp_id) {
      LOG(ERROR) << "Cannot read rp_id from " << record_path.value() << ".";
      read_all_records_successfully = false;
      continue;
    }

    const std::string* rp_display_name =
        record_dictionary.FindStringKey(kRpDisplayNameKey);
    if (!rp_display_name) {
      LOG(ERROR) << "Cannot read rp_display_name from " << record_path.value()
                 << ".";
      read_all_records_successfully = false;
      continue;
    }

    const std::string* user_id_hex =
        record_dictionary.FindStringKey(kUserIdKey);
    std::string user_id;
    if (!user_id_hex) {
      LOG(ERROR) << "Cannot read user_id from " << record_path.value() << ".";
      read_all_records_successfully = false;
      continue;
    }
    // Empty user_id is allowed:
    // https://w3c.github.io/webauthn/#dom-publickeycredentialuserentity-id
    if (!user_id_hex->empty() &&
        !base::HexStringToString(*user_id_hex, &user_id)) {
      LOG(ERROR) << "Cannot parse user_id from " << record_path.value() << ".";
      read_all_records_successfully = false;
      continue;
    }

    const std::string* user_display_name =
        record_dictionary.FindStringKey(kUserDisplayNameKey);
    if (!user_display_name) {
      LOG(ERROR) << "Cannot read user_display_name from " << record_path.value()
                 << ".";
      read_all_records_successfully = false;
      continue;
    }

    const std::optional<double> timestamp =
        record_dictionary.FindDoubleKey(kCreatedTimestampKey);
    if (!timestamp) {
      LOG(ERROR) << "Cannot read timestamp from " << record_path.value() << ".";
      read_all_records_successfully = false;
      continue;
    }

    const std::optional<bool> is_resident_key =
        record_dictionary.FindBoolKey(kIsResidentKeyKey);
    if (!is_resident_key.has_value()) {
      LOG(ERROR) << "Cannot read is_resident_key from " << record_path.value()
                 << ".";
      read_all_records_successfully = false;
      continue;
    }

    records_.emplace_back(WebAuthnRecord{
        .credential_id = credential_id,
        .secret = brillo::Blob(secret.begin(), secret.end()),
        .key_blob = brillo::Blob(key_blob.begin(), key_blob.end()),
        .rp_id = *rp_id,
        .rp_display_name = *rp_display_name,
        .user_id = user_id,
        .user_display_name = *user_display_name,
        .timestamp = *timestamp,
        .is_resident_key = *is_resident_key});
  }
  LOG(INFO) << "Loaded " << records_.size() << " WebAuthn records to memory.";
  return read_all_records_successfully;
}

bool WebAuthnStorage::SendRecordCountToUMA(MetricsLibraryInterface* metrics) {
  return metrics->SendToUMA(kWebAuthnRecordCountMetric, records_.size(),
                            kMinRecordCount, kMaxRecordCount,
                            kRecordCountBuckets);
}

std::optional<brillo::Blob> WebAuthnStorage::GetSecretByCredentialId(
    const std::string& credential_id) {
  for (const WebAuthnRecord& record : records_) {
    if (record.credential_id == credential_id) {
      return record.secret;
    }
  }
  return std::nullopt;
}

bool WebAuthnStorage::GetSecretAndKeyBlobByCredentialId(
    const std::string& credential_id,
    brillo::Blob* secret,
    brillo::Blob* key_blob) {
  for (const WebAuthnRecord& record : records_) {
    if (record.credential_id == credential_id) {
      if (secret) {
        *secret = record.secret;
      }
      if (key_blob) {
        *key_blob = record.key_blob;
      }
      return true;
    }
  }
  return false;
}

std::optional<WebAuthnRecord> WebAuthnStorage::GetRecordByCredentialId(
    const std::string& credential_id) {
  for (const WebAuthnRecord& record : records_) {
    if (record.credential_id == credential_id) {
      return record;
    }
  }
  return std::nullopt;
}

int WebAuthnStorage::CountRecordsInTimeRange(int64_t timestamp_min,
                                             int64_t timestamp_max) {
  int num_records = 0;
  for (const WebAuthnRecord& record : records_) {
    if (timestamp_min <= record.timestamp &&
        record.timestamp <= timestamp_max) {
      num_records++;
    }
  }
  return num_records;
}

int WebAuthnStorage::DeleteRecordsInTimeRange(int64_t timestamp_min,
                                              int64_t timestamp_max) {
  size_t original_size = records_.size();
  auto remove_begin =
      std::remove_if(records_.begin(), records_.end(),
                     [timestamp_min, timestamp_max](const auto& record) {
                       return timestamp_min <= record.timestamp &&
                              record.timestamp <= timestamp_max;
                     });
  for (auto record = remove_begin; record != records_.end(); record++) {
    DeleteRecordWithCredentialId(record->credential_id);
  }
  records_.erase(remove_begin, records_.end());
  size_t updated_size = records_.size();
  return original_size - updated_size;
}

void WebAuthnStorage::Reset() {
  allow_access_ = false;
  sanitized_user_.clear();
  records_.clear();
}

void WebAuthnStorage::SetRootPathForTesting(const base::FilePath& root_path) {
  root_path_ = root_path;
}

bool WebAuthnStorage::DeleteRecordWithCredentialId(
    const std::string& credential_id) {
  // Use the hash of credential_id for the filename because the hex encode of
  // credential_id itself is too long and would cause ENAMETOOLONG.
  const std::vector<uint8_t> credential_id_hash = util::Sha256(credential_id);
  std::vector<FilePath> paths = {
      FilePath(sanitized_user_), FilePath(kWebAuthnDirName),
      FilePath(kRecordFileNamePrefix +
               base::HexEncode(credential_id_hash.data(),
                               credential_id_hash.size()))};

  FilePath record_storage_filename = root_path_;
  for (const auto& path : paths) {
    DCHECK(!path.IsAbsolute());
    record_storage_filename = record_storage_filename.Append(path);
  }

  if (!base::DeleteFile(record_storage_filename)) {
    LOG(ERROR) << "Failed to delete file: " << record_storage_filename.value()
               << ".";
    return false;
  }
  LOG(INFO) << "Successfully deleted file: " << record_storage_filename.value()
            << ".";
  return true;
}

}  // namespace u2f
