// 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 <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_";
constexpr const char kAuthTimeSecretHashFileName[] = "AuthTimeSecretHash";

// Members of the JSON file
constexpr const char kCredentialIdKey[] = "credential_id";
constexpr const char kSecretKey[] = "secret";
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(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* 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 base::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 base::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, brillo::Blob(secret.begin(), secret.end()), *rp_id,
        *rp_display_name, user_id, *user_display_name, *timestamp,
        *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);
}

base::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 base::nullopt;
}

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

bool WebAuthnStorage::PersistAuthTimeSecretHash(const brillo::Blob& hash) {
  DCHECK(allow_access_ && !sanitized_user_.empty());

  FilePath path = FilePath(kDaemonStorePath)
                      .Append(sanitized_user_)
                      .Append(kWebAuthnDirName)
                      .Append(kAuthTimeSecretHashFileName);

  {
    brillo::ScopedUmask owner_only_umask(~(0700));
    if (!base::CreateDirectory(path.DirName())) {
      LOG(ERROR) << "Cannot create directory: " << path.DirName().value()
                 << ".";
      return false;
    }
  }

  {
    brillo::ScopedUmask owner_only_umask(~(0600));
    if (!base::ImportantFileWriter::WriteFileAtomically(
            path, base::Base64Encode(hash))) {
      LOG(ERROR) << "Failed to persist auth time secret hash to disk.";
      return false;
    }
  }

  return true;
}

std::unique_ptr<brillo::Blob> WebAuthnStorage::LoadAuthTimeSecretHash() {
  DCHECK(allow_access_ && !sanitized_user_.empty());

  FilePath path = FilePath(kDaemonStorePath)
                      .Append(sanitized_user_)
                      .Append(kWebAuthnDirName)
                      .Append(kAuthTimeSecretHashFileName);
  std::string hash_str_base64;
  std::string hash_str;
  if (!base::ReadFileToString(path, &hash_str_base64) ||
      !base::Base64Decode(hash_str_base64, &hash_str)) {
    LOG(ERROR) << "Failed to read auth time secret hash from disk.";
    return nullptr;
  }

  return std::make_unique<brillo::Blob>(hash_str.begin(), hash_str.end());
}

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

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

}  // namespace u2f
