/* 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.
 *
 * This tool will attempt to mount or create the encrypted stateful partition,
 * and the various bind mountable subdirectories.
 *
 */
#define _FILE_OFFSET_BITS 64
#define CHROMEOS_ENVIRONMENT

#include <fcntl.h>
#include <sys/time.h>

#include <memory>
#include <string>
#include <vector>

#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <brillo/secure_blob.h>
#include <cryptohome/cryptolib.h>
#include <cryptohome/mount_encrypted/encrypted_fs.h>
#include <cryptohome/mount_encrypted/encryption_key.h>
#include <cryptohome/mount_encrypted/mount_encrypted.h>
#include <cryptohome/mount_encrypted/tpm.h>
#include <cryptohome/platform.h>
#include <metrics/metrics_library.h>
#include <vboot/crossystem.h>
#include <vboot/tlcl.h>

#define PROP_SIZE 64

#if DEBUG_ENABLED
struct timeval tick = {};
struct timeval tick_start = {};
#endif

namespace {
constexpr char kBioCryptoInitPath[] = "/usr/bin/bio_crypto_init";
constexpr char kBioTpmSeedSalt[] = "biod";
constexpr char kBioTpmSeedTmpDir[] = "/run/bio_crypto_init";
constexpr char kBioTpmSeedFile[] = "seed";
static const uid_t kBiodUid = 282;
static const gid_t kBiodGid = 282;

constexpr char kNvramExport[] = "/tmp/lockbox.nvram";
constexpr char kMountEncryptedMetricsPath[] =
    "/run/mount_encrypted/metrics.mount-encrypted";
}  // namespace

namespace metrics {
const char kSystemKeyStatus[] = "Platform.MountEncrypted.SystemKeyStatus";
const char kEncryptionKeyStatus[] =
    "Platform.MountEncrypted.EncryptionKeyStatus";
}  // namespace metrics

static result_code get_system_property(const char* prop,
                                       char* buf,
                                       size_t length) {
  const char* rc;

  rc = VbGetSystemPropertyString(prop, buf, length);
  LOG(INFO) << "Got System Property '" << prop << "': " << (rc ? buf : "FAIL");

  return rc != NULL ? RESULT_SUCCESS : RESULT_FAIL_FATAL;
}

static int has_chromefw(void) {
  static int state = -1;
  char fw[PROP_SIZE];

  /* Cache the state so we don't have to perform the query again. */
  if (state != -1)
    return state;

  if (get_system_property("mainfw_type", fw, sizeof(fw)) != RESULT_SUCCESS)
    state = 0;
  else
    state = strcmp(fw, "nonchrome") != 0;
  return state;
}

// This triggers the live encryption key to be written to disk, encrypted by the
// system key. It is intended to be called by Cryptohome once the TPM is done
// being set up. If the system key is passed as an argument, use it, otherwise
// attempt to query the TPM again.
static result_code finalize_from_cmdline(
    const mount_encrypted::EncryptedFs& encrypted_fs,
    const base::FilePath& rootdir,
    char* key) {
  // Load the system key.
  brillo::SecureBlob system_key;
  if (!brillo::SecureBlob::HexStringToSecureBlob(std::string(key),
                                                 &system_key) ||
      system_key.size() != DIGEST_LENGTH) {
    LOG(ERROR) << "Failed to parse system key.";
    return RESULT_FAIL_FATAL;
  }

  mount_encrypted::FixedSystemKeyLoader loader(system_key);
  mount_encrypted::EncryptionKey key_manager(&loader, rootdir);
  result_code rc = key_manager.SetTpmSystemKey();
  if (rc != RESULT_SUCCESS) {
    return rc;
  }

  // If there already is an encrypted system key on disk, there is nothing to
  // do. This also covers cases where the system key is not derived from the
  // lockbox space contents (e.g. TPM 2.0 devices, TPM 1.2 devices with
  // encrypted stateful space, factory keys, etc.), for which it is not
  // appropriate to replace the system key. For cases where finalization is
  // unfinished, we clear any stale system keys from disk to make sure we pass
  // the check here.
  if (base::PathExists(key_manager.key_path())) {
    return RESULT_SUCCESS;
  }

  // Load the encryption key.
  brillo::SecureBlob encryption_key = encrypted_fs.GetKey();
  if (encryption_key.empty()) {
    LOG(ERROR) << "Could not get mount encryption key";
    return RESULT_FAIL_FATAL;
  }

  // Persist the encryption key to disk.
  key_manager.PersistEncryptionKey(encryption_key);

  return RESULT_SUCCESS;
}

static result_code report_info(const mount_encrypted::EncryptedFs& encrypted_fs,
                               const base::FilePath& rootdir) {
  mount_encrypted::Tpm tpm;

  printf("TPM: %s\n", tpm.available() ? "yes" : "no");
  if (tpm.available()) {
    bool owned = false;
    printf("TPM Owned: %s\n", tpm.IsOwned(&owned) == RESULT_SUCCESS
                                  ? (owned ? "yes" : "no")
                                  : "fail");
  }
  printf("ChromeOS: %s\n", has_chromefw() ? "yes" : "no");
  printf("TPM2: %s\n", tpm.is_tpm2() ? "yes" : "no");
  if (has_chromefw()) {
    brillo::SecureBlob system_key;
    auto loader = mount_encrypted::SystemKeyLoader::Create(&tpm, rootdir);
    result_code rc = loader->Load(&system_key);
    if (rc != RESULT_SUCCESS) {
      printf("NVRAM: missing.\n");
    } else {
      printf("NVRAM: available.\n");
    }
  } else {
    printf("NVRAM: not present\n");
  }
  // Report info from the encrypted mount.
  encrypted_fs.ReportInfo();

  return RESULT_SUCCESS;
}

// Reads key material from the file |key_material_file|, creates a system key
// using the material, and persists the system key in NVRAM.
//
// This function only supports TPM 2.0 and should be called ONLY for testing
// purposes.
//
// Doesn't take ownership of |platform|.
// Return code indicates if every thing is successful.
static result_code set_system_key(const base::FilePath& rootdir,
                                  const char* key_material_file,
                                  cryptohome::Platform* platform) {
  if (!key_material_file) {
    LOG(ERROR) << "Key material file not provided.";
    return RESULT_FAIL_FATAL;
  }

  mount_encrypted::Tpm tpm;
  if (!tpm.is_tpm2()) {
    LOG(WARNING) << "Custom system key is not supported in TPM 1.2.";
    return RESULT_FAIL_FATAL;
  }

  brillo::SecureBlob key_material;
  if (!platform->ReadFileToSecureBlob(base::FilePath(key_material_file),
                                      &key_material)) {
    LOG(ERROR) << "Failed to read custom system key material from file "
               << key_material_file;
    return RESULT_FAIL_FATAL;
  }

  auto loader = mount_encrypted::SystemKeyLoader::Create(&tpm, rootdir);

  result_code rc = loader->Initialize(key_material, nullptr);
  if (rc != RESULT_SUCCESS) {
    LOG(ERROR) << "Failed to initialize system key NV space contents.";
    return rc;
  }

  rc = loader->Persist();
  if (rc != RESULT_SUCCESS) {
    LOG(ERROR) << "Failed to persist custom system key material in NVRAM.";
    return rc;
  }

  return RESULT_SUCCESS;
}

/* Exports NVRAM contents to tmpfs for use by install attributes */
void nvram_export(const brillo::SecureBlob& contents) {
  int fd;
  LOG(INFO) << "Export NVRAM contents";
  fd = open(kNvramExport, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
  if (fd < 0) {
    PLOG(ERROR) << "open(nvram_export)";
    return;
  }
  if (write(fd, contents.data(), contents.size()) != contents.size()) {
    // Don't leave broken files around
    unlink(kNvramExport);
  }
  close(fd);
}

template <typename Enum>
void RecordEnumeratedHistogram(MetricsLibrary* metrics,
                               const char* name,
                               Enum val) {
  metrics->SendEnumToUMA(name, static_cast<int>(val),
                         static_cast<int>(Enum::kCount));
}

// Send a secret derived from the system key to the biometric managers, if
// available, via a tmpfs file which will be read by bio_crypto_init.
bool SendSecretToBiodTmpFile(const mount_encrypted::EncryptionKey& key) {
  // If there isn't a bio-sensor, don't bother.
  if (!base::PathExists(base::FilePath(kBioCryptoInitPath))) {
    LOG(INFO) << "There is no biod, so skip sending TPM seed.";
    return true;
  }

  brillo::SecureBlob tpm_seed =
      key.GetDerivedSystemKey(std::string(kBioTpmSeedSalt));
  if (tpm_seed.empty()) {
    LOG(ERROR) << "TPM Seed provided is empty, not writing to tmpfs.";
    return false;
  }

  auto dirname = base::FilePath(kBioTpmSeedTmpDir);
  if (!base::CreateDirectory(dirname)) {
    LOG(ERROR) << "Failed to create dir for TPM seed.";
    return false;
  }

  if (chown(kBioTpmSeedTmpDir, kBiodUid, kBiodGid) == -1) {
    PLOG(ERROR) << "Failed to change ownership of biod tmpfs dir.";
    return false;
  }

  auto filename = dirname.Append(kBioTpmSeedFile);
  if (base::WriteFile(filename, tpm_seed.char_data(), tpm_seed.size()) !=
      tpm_seed.size()) {
    LOG(ERROR) << "Failed to write TPM seed to tmpfs file.";
    return false;
  }

  if (chown(filename.value().c_str(), kBiodUid, kBiodGid) == -1) {
    PLOG(ERROR) << "Failed to change ownership of biod tmpfs file.";
    return false;
  }

  return true;
}

int main(int argc, char* argv[]) {
  result_code rc;
  char* rootdir_env = getenv("MOUNT_ENCRYPTED_ROOT");
  base::FilePath rootdir = base::FilePath(rootdir_env ? rootdir_env : "/");
  cryptohome::Platform platform;
  brillo::LoopDeviceManager loopdev_manager;
  brillo::DeviceMapper device_mapper;
  mount_encrypted::EncryptedFs encrypted_fs(rootdir, &platform,
                                            &loopdev_manager, &device_mapper);

  MetricsLibrary metrics;
  metrics.SetOutputFile(kMountEncryptedMetricsPath);

  LOG(INFO) << "Starting.";

  if (argc > 1) {
    if (!strcmp(argv[1], "umount")) {
      return encrypted_fs.Teardown();
    } else if (!strcmp(argv[1], "info")) {
      // Report info from the encrypted mount.
      return report_info(encrypted_fs, rootdir);
    } else if (!strcmp(argv[1], "finalize")) {
      return finalize_from_cmdline(encrypted_fs, rootdir,
                                   argc > 2 ? argv[2] : NULL);
    } else if (!strcmp(argv[1], "set")) {
      return set_system_key(rootdir, argc > 2 ? argv[2] : NULL, &platform);
    } else {
      fprintf(stderr, "Usage: %s [info|finalize|umount|set]\n", argv[0]);
      return RESULT_FAIL_FATAL;
    }
  }

  // For the mount operation at boot, return RESULT_FAIL_FATAL to trigger
  // chromeos_startup do the stateful wipe.
  rc = encrypted_fs.CheckStates();
  if (rc != RESULT_SUCCESS)
    return rc;

  mount_encrypted::Tpm tpm;
  auto loader = mount_encrypted::SystemKeyLoader::Create(&tpm, rootdir);
  mount_encrypted::EncryptionKey key(loader.get(), rootdir);
  if (has_chromefw()) {
    if (!tpm.available()) {
      // The TPM should be available before we load the system_key.
      LOG(ERROR) << "TPM not available.";
      // We shouldn't continue to load the system_key.
      return RESULT_FAIL_FATAL;
    }
    rc = key.LoadChromeOSSystemKey();
  } else {
    rc = key.SetInsecureFallbackSystemKey();
  }
  RecordEnumeratedHistogram(&metrics, metrics::kSystemKeyStatus,
                            key.system_key_status());
  if (rc != RESULT_SUCCESS) {
    return rc;
  }

  rc = key.LoadEncryptionKey();
  RecordEnumeratedHistogram(&metrics, metrics::kEncryptionKeyStatus,
                            key.encryption_key_status());
  if (rc != RESULT_SUCCESS) {
    return rc;
  }

  /* Log errors during sending seed to biod, but don't stop execution. */
  if (has_chromefw()) {
    if (!SendSecretToBiodTmpFile(key)) {
      LOG(ERROR) << "Failed to send TPM secret to biod.";
    }
  } else {
    LOG(ERROR) << "Failed to load system key, biod won't get a TPM seed.";
  }

  rc = encrypted_fs.Setup(key.encryption_key(), key.is_fresh());
  if (rc == RESULT_SUCCESS) {
    bool lockbox_valid = false;
    if (loader->CheckLockbox(&lockbox_valid) == RESULT_SUCCESS) {
      mount_encrypted::NvramSpace* lockbox_space = tpm.GetLockboxSpace();
      if (lockbox_valid && lockbox_space->is_valid()) {
        LOG(INFO) << "Lockbox is valid, exporting.";
        nvram_export(lockbox_space->contents());
      }
    } else {
      LOG(ERROR) << "Lockbox validity check error.";
    }
  }

  LOG(INFO) << "Done.";

  // Continue boot.
  return rc;
}
