// 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 "cryptohome/encrypted_reboot_vault/encrypted_reboot_vault.h"

#include <cryptohome/cryptolib.h>
#include <cryptohome/dircrypto_util.h>

#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <brillo/key_value_store.h>

namespace {
// Pstore-pmsg path.
const char kPmsgDevicePath[] = "/dev/pmsg0";
// There can be multiple pmsg ramoops entries.
const char kPmsgKeystoreRamoopsPathDesc[] = "pmsg-ramoops-*";
const char kExt4DircryptoSupportedPath[] = "/sys/fs/ext4/features/encryption";
const char kEncryptedRebootVaultPath[] = "/mnt/stateful_partition/reboot_vault";
// Pstore path.
const char kPstorePath[] = "/sys/fs/pstore";
// Key tag to retrieve the key from pstore-pmsg.
const char kEncryptionKeyTag[] = "pmsg-key";
// Encryption key size.
const size_t kEncryptionKeySize = 64;

bool IsSupported() {
  if (!base::PathExists(base::FilePath(kPmsgDevicePath))) {
    LOG(ERROR) << "pmsg0 not enabled.";
    return false;
  }

  // Check if we can create an encrypted vault.
  if (!base::PathExists(base::FilePath(kExt4DircryptoSupportedPath))) {
    LOG(ERROR) << "ext4 directory encryption not supported.";
    return false;
  }
  return true;
}

bool SaveKey(const brillo::SecureBlob& key) {
  // Do not use store.Save() since it uses WriteFileAtomically() which will
  // fail on /dev/pmsg0.
  brillo::KeyValueStore store;
  store.SetString(kEncryptionKeyTag,
                  cryptohome::CryptoLib::SecureBlobToHex(key));

  std::string store_contents = store.SaveToString();
  if (store_contents.empty() ||
      !base::WriteFile(base::FilePath(kPmsgDevicePath), store_contents.data(),
                       store_contents.size())) {
    return false;
  }
  return true;
}

brillo::SecureBlob RetrieveKey() {
  base::FileEnumerator pmsg_ramoops_enumerator(
      base::FilePath(kPstorePath), true /* recursive */,
      base::FileEnumerator::FILES, kPmsgKeystoreRamoopsPathDesc);

  for (base::FilePath ramoops_file = pmsg_ramoops_enumerator.Next();
       !ramoops_file.empty(); ramoops_file = pmsg_ramoops_enumerator.Next()) {
    brillo::KeyValueStore store;
    std::string val;
    if (store.Load(ramoops_file) && store.GetString(kEncryptionKeyTag, &val)) {
      auto encryption_key =
          brillo::SecureHexToSecureBlob(brillo::SecureBlob(val));
      base::DeleteFile(ramoops_file, false /* recursive */);
      // SaveKey stores the key again into pstore-pmsg on every boot since the
      // pstore object isn't persistent. Since the pstore object is always
      // stored in RAM on ChromiumOS, it is cleared the next time the device
      // shuts down or loses power.
      if (!SaveKey(encryption_key))
        LOG(WARNING) << "Failed to store key for next reboot.";
      return encryption_key;
    }
  }
  return brillo::SecureBlob();
}

}  // namespace

EncryptedRebootVault::EncryptedRebootVault()
    : vault_path_(base::FilePath(kEncryptedRebootVaultPath)) {
  if (dircrypto::CheckFscryptKeyIoctlSupport()) {
    key_reference_.policy_version = FSCRYPT_POLICY_V2;
  } else {
    key_reference_.reference = brillo::SecureBlob(kEncryptionKeyTag);
    key_reference_.policy_version = FSCRYPT_POLICY_V1;
  }
}

bool EncryptedRebootVault::CreateVault() {
  if (!IsSupported()) {
    LOG(ERROR) << "EncryptedRebootVault not supported";
    return false;
  }

  base::ScopedClosureRunner reset_vault(
      base::Bind(base::IgnoreResult(&EncryptedRebootVault::PurgeVault),
                 base::Unretained(this)));

  // Remove the existing vault.
  PurgeVault();

  // Generate encryption key.
  brillo::SecureBlob transient_encryption_key =
      cryptohome::CryptoLib::CreateSecureRandomBlob(kEncryptionKeySize);

  // The key descriptor needs to be exactly 8 bytes for v1 encryption policies.
  if (!dircrypto::AddDirectoryKey(transient_encryption_key, &key_reference_)) {
    LOG(ERROR) << "Failed to add pmsg-key";
    return false;
  }

  // Store key into pmsg. If it fails, we bail out.
  if (!SaveKey(transient_encryption_key)) {
    LOG(ERROR) << "Failed to store transient encryption key to pmsg.";
    return false;
  }

  // Set up the encrypted reboot vault.
  if (!base::CreateDirectory(vault_path_)) {
    LOG(ERROR) << "Failed to create directory";
    return false;
  }

  // Set the fscrypt context for the directory.
  if (!dircrypto::SetDirectoryKey(vault_path_, key_reference_)) {
    LOG(ERROR) << "Failed to set directory key";
    return false;
  }

  ignore_result(reset_vault.Release());
  return true;
}

bool EncryptedRebootVault::Validate() {
  return base::PathExists(vault_path_) &&
         dircrypto::GetDirectoryKeyState(vault_path_) ==
             dircrypto::KeyState::ENCRYPTED;
}

bool EncryptedRebootVault::PurgeVault() {
  if (!dircrypto::RemoveDirectoryKey(key_reference_, vault_path_)) {
    LOG(WARNING) << "Failed to unlink encryption key from keyring.";
  }
  return base::DeleteFile(vault_path_, true /* recursively */);
}

bool EncryptedRebootVault::UnlockVault() {
  if (!IsSupported()) {
    LOG(ERROR) << "EncryptedRebootVault depends on pstore-pmsg to pass the "
                  "encryption key. Enable CONFIG_PSTORE_PMSG";
    return false;
  }

  // We reset the vault if we fail to unlock it for any reason.
  base::ScopedClosureRunner reset_vault(
      base::Bind(base::IgnoreResult(&EncryptedRebootVault::PurgeVault),
                 base::Unretained(this)));

  if (!Validate()) {
    LOG(ERROR) << "Invalid vault; purging.";
    return false;
  }

  // If the vault exists, get the policy version from the directory.
  switch (dircrypto::GetDirectoryPolicyVersion(vault_path_)) {
    case FSCRYPT_POLICY_V1:
      key_reference_.policy_version = FSCRYPT_POLICY_V1;
      key_reference_.reference = brillo::SecureBlob(kEncryptionKeyTag);
      break;
    case FSCRYPT_POLICY_V2:
      key_reference_.policy_version = FSCRYPT_POLICY_V2;
      break;
    default:
      LOG(ERROR) << "Failed to get policy version for directory";
      return false;
  }

  // Retrieve key.
  brillo::SecureBlob transient_encryption_key = RetrieveKey();
  if (transient_encryption_key.empty()) {
    LOG(INFO) << "No valid key found: the device might have booted up from a "
                 "shutdown.";
    return false;
  }

  // Unlock vault.
  if (!dircrypto::AddDirectoryKey(transient_encryption_key, &key_reference_)) {
    LOG(ERROR) << "Failed to add key to keyring.";
    return false;
  }

  ignore_result(reset_vault.Release());
  return true;
}
