// Copyright (c) 2012 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 "chaps/object_store_impl.h"

#include <limits>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include "base/files/file_enumerator.h"
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_piece.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <brillo/secure_blob.h>
#include <leveldb/db.h>
#include <leveldb/env.h>
#ifndef NO_MEMENV
#include <leveldb/helpers/memenv.h>
#endif
#ifndef NO_METRICS
#include <metrics/metrics_library.h>
#endif

#include "chaps/chaps_utility.h"
#include "pkcs11/cryptoki.h"

using base::FilePath;
using brillo::SecureBlob;
using std::map;
using std::string;
using std::vector;

namespace {

// Encapsulate UMA event generation.
class MetricsWrapper {
 public:
  MetricsWrapper() {}

  bool SendUMAEvent(const std::string& event) {
#ifndef NO_METRICS
    return metrics_.SendCrosEventToUMA(event);
#else
    return false;
#endif
  }

 private:
#ifndef NO_METRICS
  MetricsLibrary metrics_;
#endif
};

// Logs information about |db_dir| before opening the leveldb.
// TODO(https://crbug.com/844537): Remove or decrease log level when root cause
// of disappearing system token certificates is found.
void LogDatabaseDirectoryStats(const FilePath& db_dir) {
  if (!base::DirectoryExists(db_dir)) {
    LOG(INFO) << "leveldb " << db_dir.value() << " directory did not exist.";
    return;
  }
  base::FileEnumerator file_enumerator(db_dir, false /* recursive */,
                                       base::FileEnumerator::FILES);
  std::ostringstream db_info;
  for (base::FilePath db_file = file_enumerator.Next(); !db_file.empty();
       db_file = file_enumerator.Next()) {
    base::FileEnumerator::FileInfo db_file_info = file_enumerator.GetInfo();
    db_info << "\n  " << db_file.value() << " (" << db_file_info.GetSize()
            << " bytes, " << db_file_info.GetLastModifiedTime() << ")";
  }
  LOG(INFO) << "leveldb " << db_dir.value() << " dump:" << db_info.str();
}

// Logs information about |db|.
// TODO(https://crbug.com/844537): Remove or decrease log level when root cause
// of disappearing system token certificates is found.
void LogDatabaseStats(leveldb::DB* db) {
  std::string leveldb_stats;
  if (db->GetProperty("leveldb.stats", &leveldb_stats)) {
    LOG(INFO) << "leveldb.stats:\n" << leveldb_stats;
  } else {
    LOG(WARNING) << "Failed to retrieve leveldb.stats";
  }

  // Also log the number of objects in the database. This needs to be explicitly
  // counted in leveldb.
  int key_count = 0;
  leveldb::ReadOptions read_options;
  read_options.fill_cache = false;
  std::unique_ptr<leveldb::Iterator> it(db->NewIterator(read_options));
  for (it->SeekToFirst(); it->Valid(); it->Next()) {
    ++key_count;
  }
  LOG(INFO) << "leveldb contains " << key_count << " keys.";
}

}  // namespace

namespace chaps {

const char ObjectStoreImpl::kInternalBlobKeyPrefix[] = "InternalBlob";
const char ObjectStoreImpl::kPublicBlobKeyPrefix[] = "PublicBlob";
const char ObjectStoreImpl::kPrivateBlobKeyPrefix[] = "PrivateBlob";
const char ObjectStoreImpl::kBlobKeySeparator[] = "&";
const char ObjectStoreImpl::kDatabaseVersionKey[] = "DBVersion";
const char ObjectStoreImpl::kIDTrackerKey[] = "NextBlobID";
const int ObjectStoreImpl::kAESKeySizeBytes = 32;
const int ObjectStoreImpl::kHMACSizeBytes = 64;
const char ObjectStoreImpl::kDatabaseDirectory[] = "database";
const char ObjectStoreImpl::kCorruptDatabaseDirectory[] = "database_corrupt";
const char ObjectStoreImpl::kObfuscationKey[] = {
    '\x6f', '\xaa', '\x0a', '\xb6', '\x10', '\xc0', '\xa6', '\xe4',
    '\x07', '\x8b', '\x05', '\x1c', '\xd2', '\x8b', '\xac', '\x2d',
    '\xba', '\x5e', '\x14', '\x9c', '\xae', '\x57', '\xfb', '\x04',
    '\x13', '\x92', '\xc0', '\x84', '\x2a', '\xea', '\xf6', '\xfb'};
const int ObjectStoreImpl::kBlobVersion = 1;

ObjectStoreImpl::ObjectStoreImpl() {}

ObjectStoreImpl::~ObjectStoreImpl() {
  // TODO(https://crbug.com/844537): Remove or decrease log level when root
  // cause of disappearing system token certificates is found.
  if (db_) {
    LOG(INFO) << "Closing database for " << database_name_.value();
    db_.reset();
    LogDatabaseDirectoryStats(database_name_);
  }
}

bool ObjectStoreImpl::Init(const FilePath& database_path) {
  MetricsWrapper metrics;

  LOG(INFO) << "Opening database in: " << database_path.value();
  leveldb::Options options;
  options.create_if_missing = true;
  options.paranoid_checks = true;
  if (database_path.value() == ":memory:") {
#ifndef NO_MEMENV
    // Memory only environment, useful for testing.
    LOG(INFO) << "Using memory-only environment.";
    env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
    options.env = env_.get();
#else
    LOG(ERROR) << "Compiled without memory-only environment support.";
    return false;
#endif
  }
  FilePath database_name = database_path.Append(kDatabaseDirectory);
  database_name_ = database_name;
  // TODO(https://crbug.com/844537): Remove or decrease log level when root
  // cause of disappearing system token certificates is found.
  LogDatabaseDirectoryStats(database_name);
  leveldb::DB* db = NULL;
  leveldb::Status status =
      leveldb::DB::Open(options, database_name.value(), &db);
  if (!status.ok()) {
    LOG(ERROR) << "Failed to open database: " << status.ToString();
    metrics.SendUMAEvent("Chaps.DatabaseCorrupted");
    LOG(WARNING) << "Attempting to repair database.";
    status = leveldb::RepairDB(database_name.value(), leveldb::Options());
    if (status.ok())
      status = leveldb::DB::Open(options, database_name.value(), &db);
  }

  if (!status.ok()) {
    LOG(ERROR) << "Failed to repair database: " << status.ToString();
    metrics.SendUMAEvent("Chaps.DatabaseRepairFailure");
    // We don't want to risk using a database that has been corrupted. Recreate
    // the database from scratch but save the corrupted database for diagnostic
    // purposes.
    LOG(WARNING) << "Recreating database from scratch. Moving current database "
                 << "to " << kCorruptDatabaseDirectory;
    FilePath corrupt_db_path = database_path.Append(kCorruptDatabaseDirectory);
    base::DeleteFile(corrupt_db_path, true);
    if (!base::Move(database_name, corrupt_db_path)) {
      LOG(ERROR) << "Failed to move database." << status.ToString();
      return false;
    }
    status = leveldb::DB::Open(options, database_name.value(), &db);
  }

  if (!status.ok()) {
    LOG(ERROR) << "Failed to create new database: " << status.ToString();
    metrics.SendUMAEvent("Chaps.DatabaseCreateFailure");
    return false;
  }

  // TODO(https://crbug.com/844537): Remove or decrease log level when root
  // cause of disappearing system token certificates is found.
  LogDatabaseStats(db);

  db_.reset(db);
  int version = 0;
  if (!ReadInt(kDatabaseVersionKey, &version)) {
    if (!WriteInt(kIDTrackerKey, 1)) {
      LOG(ERROR) << "Failed to initialize the blob ID tracker.";
      return false;
    }
    if (!WriteInt(kDatabaseVersionKey, 1)) {
      LOG(ERROR) << "Failed to initialize the database version.";
      return false;
    }
  }
  return true;
}

bool ObjectStoreImpl::GetInternalBlob(int blob_id, string* blob) {
  if (!ReadBlob(CreateBlobKey(kInternal, blob_id), blob)) {
    // Don't log this since it happens legitimately when a blob has not yet been
    // set.
    return false;
  }
  return true;
}

bool ObjectStoreImpl::SetInternalBlob(int blob_id, const string& blob) {
  if (!WriteBlob(CreateBlobKey(kInternal, blob_id), blob)) {
    LOG(ERROR) << "Failed to write internal blob: " << blob_id;
    return false;
  }
  return true;
}

bool ObjectStoreImpl::SetEncryptionKey(const SecureBlob& key) {
  if (key.size() != static_cast<size_t>(kAESKeySizeBytes)) {
    LOG(ERROR) << "Unexpected key size: " << key.size();
    return false;
  }
  key_ = key;
  return true;
}

bool ObjectStoreImpl::InsertObjectBlob(const ObjectBlob& blob, int* handle) {
  if (blob.is_private && key_.empty()) {
    LOG(ERROR) << "The store encryption key has not been initialized.";
    return false;
  }
  if (!GetNextID(handle)) {
    LOG(ERROR) << "Failed to generate blob identifier.";
    return false;
  }
  blob_type_map_[*handle] = blob.is_private ? kPrivate : kPublic;
  return UpdateObjectBlob(*handle, blob);
}

bool ObjectStoreImpl::DeleteObjectBlob(int handle) {
  leveldb::WriteOptions options;
  options.sync = true;
  string db_key = CreateBlobKey(GetBlobType(handle), handle);
  leveldb::Status status = db_->Delete(options, db_key);
  if (!status.ok()) {
    LOG(ERROR) << "Failed to delete blob: " << status.ToString();
    return false;
  }
  return true;
}

bool ObjectStoreImpl::DeleteAllObjectBlobs() {
  vector<string> blobs_to_delete;
  std::unique_ptr<leveldb::Iterator> it(
      db_->NewIterator(leveldb::ReadOptions()));
  for (it->SeekToFirst(); it->Valid(); it->Next()) {
    BlobType type;
    int id = 0;
    if (ParseBlobKey(it->key().ToString(), &type, &id) && type != kInternal)
      blobs_to_delete.push_back(it->key().ToString());
  }
  bool deleted_all = true;
  for (size_t i = 0; i < blobs_to_delete.size(); ++i) {
    leveldb::WriteOptions options;
    options.sync = true;
    leveldb::Status status = db_->Delete(options, blobs_to_delete[i]);
    if (!status.ok()) {
      LOG(ERROR) << "Failed to delete blob: " << status.ToString();
      deleted_all = false;
    }
  }
  return deleted_all;
}

bool ObjectStoreImpl::UpdateObjectBlob(int handle, const ObjectBlob& blob) {
  ObjectBlob encrypted_blob;
  BlobType type = GetBlobType(handle);
  if (blob.is_private != (type == kPrivate)) {
    LOG(ERROR) << "Object privacy mismatch.";
    return false;
  }
  if (!Encrypt(blob, &encrypted_blob)) {
    LOG(ERROR) << "Failed to encrypt object blob.";
    return false;
  }
  if (!WriteBlob(CreateBlobKey(type, handle), encrypted_blob.blob)) {
    LOG(ERROR) << "Failed to write object blob.";
  }
  return true;
}

bool ObjectStoreImpl::LoadPublicObjectBlobs(map<int, ObjectBlob>* blobs) {
  return LoadObjectBlobs(kPublic, blobs);
}

bool ObjectStoreImpl::LoadPrivateObjectBlobs(map<int, ObjectBlob>* blobs) {
  if (key_.empty()) {
    LOG(ERROR) << "The store encryption key has not been initialized.";
    return false;
  }
  return LoadObjectBlobs(kPrivate, blobs);
}

bool ObjectStoreImpl::LoadObjectBlobs(BlobType type,
                                      map<int, ObjectBlob>* blobs) {
  std::unique_ptr<leveldb::Iterator> it(
      db_->NewIterator(leveldb::ReadOptions()));
  for (it->SeekToFirst(); it->Valid(); it->Next()) {
    BlobType it_type;
    int id = 0;
    if (ParseBlobKey(it->key().ToString(), &it_type, &id) && type == it_type) {
      ObjectBlob encrypted_blob;
      encrypted_blob.is_private = (type == kPrivate);
      encrypted_blob.blob = it->value().ToString();
      ObjectBlob blob;
      if (!Decrypt(encrypted_blob, &blob)) {
        LOG(WARNING) << "Failed to decrypt object blob.";
        continue;
      }
      (*blobs)[id] = blob;
      blob_type_map_[id] = type;
    }
  }
  return true;
}

bool ObjectStoreImpl::Encrypt(const ObjectBlob& plain_text,
                              ObjectBlob* cipher_text) {
  if (plain_text.is_private && key_.empty()) {
    LOG(ERROR) << "The store encryption key has not been initialized.";
    return false;
  }
  cipher_text->is_private = plain_text.is_private;
  SecureBlob obfuscation_key(std::begin(kObfuscationKey),
                             std::end(kObfuscationKey));
  SecureBlob& key = plain_text.is_private ? key_ : obfuscation_key;
  string cipher_text_no_hmac;
  if (!RunCipher(true, key, string(), plain_text.blob, &cipher_text_no_hmac))
    return false;
  // Prepend a version header and include it in the MAC.
  string version_header(1, static_cast<char>(kBlobVersion));
  cipher_text->blob = AppendHMAC(version_header + cipher_text_no_hmac, key);
  return true;
}

bool ObjectStoreImpl::Decrypt(const ObjectBlob& cipher_text,
                              ObjectBlob* plain_text) {
  if (cipher_text.is_private && key_.empty()) {
    LOG(ERROR) << "The store encryption key has not been initialized.";
    return false;
  }
  plain_text->is_private = cipher_text.is_private;
  SecureBlob obfuscation_key(std::begin(kObfuscationKey),
                             std::end(kObfuscationKey));
  SecureBlob& key = cipher_text.is_private ? key_ : obfuscation_key;
  string cipher_text_no_hmac;
  if (!VerifyAndStripHMAC(cipher_text.blob, key, &cipher_text_no_hmac))
    return false;
  // Check and strip the version header.
  int version = static_cast<int>(cipher_text_no_hmac[0]);
  if (version != kBlobVersion) {
    LOG(ERROR) << "Blob found with unknown version.";
    return false;
  }
  cipher_text_no_hmac = cipher_text_no_hmac.substr(1);
  return RunCipher(false, key, string(), cipher_text_no_hmac,
                   &plain_text->blob);
}

string ObjectStoreImpl::AppendHMAC(const string& input, const SecureBlob& key) {
  return input + HmacSha512(input, key);
}

bool ObjectStoreImpl::VerifyAndStripHMAC(const string& input,
                                         const SecureBlob& key,
                                         string* stripped) {
  if (input.size() < static_cast<size_t>(kHMACSizeBytes)) {
    LOG(ERROR) << "Failed to verify blob integrity.";
    return false;
  }
  *stripped = input.substr(0, input.size() - kHMACSizeBytes);
  string hmac = input.substr(input.size() - kHMACSizeBytes);
  string computed_hmac = HmacSha512(*stripped, key);
  if ((hmac.size() != computed_hmac.size()) ||
      (0 !=
       brillo::SecureMemcmp(hmac.data(), computed_hmac.data(), hmac.size()))) {
    LOG(ERROR) << "Failed to verify blob integrity.";
    return false;
  }
  return true;
}

string ObjectStoreImpl::CreateBlobKey(BlobType type, int blob_id) {
  const char* prefix = NULL;
  switch (type) {
    case kInternal:
      prefix = kInternalBlobKeyPrefix;
      break;
    case kPublic:
      prefix = kPublicBlobKeyPrefix;
      break;
    case kPrivate:
      prefix = kPrivateBlobKeyPrefix;
      break;
    default:
      LOG(FATAL) << "Invalid enum value.";
  }
  return base::StringPrintf("%s%s%d", prefix, kBlobKeySeparator, blob_id);
}

bool ObjectStoreImpl::ParseBlobKey(const string& key,
                                   BlobType* type,
                                   int* blob_id) {
  size_t index = key.rfind(kBlobKeySeparator);
  if (index == string::npos) {
    // This isn't a blob.
    return false;
  }
  base::StringPiece key_piece(key.begin() + (index + 1), key.end());
  if (!base::StringToInt(key_piece, blob_id)) {
    LOG(ERROR) << "Invalid blob key id: " << key;
    return false;
  }
  string prefix = key.substr(0, index);
  if (prefix == kInternalBlobKeyPrefix) {
    *type = kInternal;
  } else if (prefix == kPublicBlobKeyPrefix) {
    *type = kPublic;
  } else if (prefix == kPrivateBlobKeyPrefix) {
    *type = kPrivate;
  } else {
    LOG(ERROR) << "Invalid blob key prefix: " << key;
    return false;
  }
  return true;
}

bool ObjectStoreImpl::GetNextID(int* next_id) {
  if (!ReadInt(kIDTrackerKey, next_id)) {
    LOG(ERROR) << "Failed to read ID tracker.";
    return false;
  }
  if (*next_id == std::numeric_limits<int>::max()) {
    LOG(ERROR) << "Object ID overflow.";
    return false;
  }
  if (!WriteInt(kIDTrackerKey, *next_id + 1)) {
    LOG(ERROR) << "Failed to write ID tracker.";
    return false;
  }
  return true;
}

bool ObjectStoreImpl::ReadBlob(const string& key, string* value) {
  leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, value);
  if (!status.ok()) {
    if (!status.IsNotFound())
      LOG(ERROR) << "Failed to read value from database: " << status.ToString();
    return false;
  }
  return true;
}

bool ObjectStoreImpl::ReadInt(const string& key, int* value) {
  string value_string;
  if (!ReadBlob(key, &value_string))
    return false;
  if (!base::StringToInt(value_string, value)) {
    LOG(ERROR) << "Invalid integer value.";
    return false;
  }
  return true;
}

bool ObjectStoreImpl::WriteBlob(const string& key, const string& value) {
  leveldb::WriteOptions options;
  options.sync = true;
  leveldb::Status status = db_->Put(options, key, value);
  if (!status.ok()) {
    LOG(ERROR) << "Failed to write value to database: " << status.ToString();
    return false;
  }
  return true;
}

bool ObjectStoreImpl::WriteInt(const string& key, int value) {
  return WriteBlob(key, base::NumberToString(value));
}

ObjectStoreImpl::BlobType ObjectStoreImpl::GetBlobType(int blob_id) {
  map<int, BlobType>::iterator it = blob_type_map_.find(blob_id);
  if (it == blob_type_map_.end())
    return kInternal;
  return it->second;
}

}  // namespace chaps
