/* 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";
}

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()) {
    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;
}
