// Copyright 2018 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 "oobe_config/load_oobe_config_usb.h"

#include <pwd.h>
#include <sys/mount.h>
#include <unistd.h>

#include <map>
#include <utility>
#include <vector>

#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/strings/string_number_conversions.h>
#include <brillo/file_utils.h>
#include <libtpmcrypto/tpm.h>
#include <openssl/evp.h>
#include <openssl/pem.h>

#include "oobe_config/usb_utils.h"

using base::FilePath;
using base::ScopedTempDir;
using std::map;
using std::string;
using std::unique_ptr;
using std::vector;

namespace oobe_config {

namespace {
#if USE_TPM2
// TPMA_NV_PPWRITE | TPMA_NV_AUTHREAD | TPMA_NV_NO_DA | TPMA_NV_WRITTEN |
// TPMA_NV_PLATFORMCREATE
constexpr uint32_t kTpmPermissions = 0x62040001;
#else
// TPM_NV_PER_PPWRITE
constexpr uint32_t kTpmPermissions =  0x1;
#endif

constexpr uint32_t kHashIndexInTpmNvram = 0x100c;

// Copied from rollback_helper.cc.
// TODO(ahassani): Find a way to use the one in rollback_helper.cc
bool GetUidGid(const string& user, uid_t* uid, gid_t* gid) {
  // Load the passwd entry.
  constexpr int kDefaultPwnameLength = 1024;
  int user_name_length = sysconf(_SC_GETPW_R_SIZE_MAX);
  if (user_name_length == -1) {
    user_name_length = kDefaultPwnameLength;
  }
  if (user_name_length < 0) {
    return false;
  }
  passwd user_info{}, *user_infop;
  vector<char> user_name_buf(static_cast<size_t>(user_name_length));
  getpwnam_r(user.c_str(), &user_info, user_name_buf.data(),
             static_cast<size_t>(user_name_length), &user_infop);
  // NOTE: the return value can be ambiguous in the case that the user does
  // not exist. See "man getpwnam_r" for details.
  if (user_infop == nullptr) {
    return false;
  }

  *uid = user_info.pw_uid;
  *gid = user_info.pw_gid;
  return true;
}

}  // namespace

unique_ptr<LoadOobeConfigUsb> LoadOobeConfigUsb::CreateInstance() {
  return std::make_unique<LoadOobeConfigUsb>(
      FilePath(kStatefulDir), FilePath(kDevDiskById), FilePath(kStoreDir));
}

LoadOobeConfigUsb::LoadOobeConfigUsb(const FilePath& stateful_dir,
                                     const FilePath& device_ids_dir,
                                     const FilePath& store_dir)
    : stateful_(stateful_dir),
      device_ids_dir_(device_ids_dir),
      store_dir_(store_dir),
      public_key_(nullptr) {
  unencrypted_oobe_config_dir_ = stateful_.Append(kUnencryptedOobeConfigDir);
  pub_key_file_ = unencrypted_oobe_config_dir_.Append(kKeyFile);
  config_signature_file_ =
      unencrypted_oobe_config_dir_.Append(kConfigFile).AddExtension("sig");
  enrollment_domain_signature_file_ =
      unencrypted_oobe_config_dir_.Append(kDomainFile).AddExtension("sig");
  usb_device_path_signature_file_ =
      unencrypted_oobe_config_dir_.Append(kUsbDevicePathSigFile);
}

bool LoadOobeConfigUsb::ReadFiles() {
  if (!base::PathExists(stateful_)) {
    LOG(ERROR) << "Stateful partition's path " << stateful_.value()
               << " does not exist.";
    return false;
  }
  if (!base::PathExists(unencrypted_oobe_config_dir_)) {
    LOG(WARNING) << "oobe_config directory on stateful partition "
                 << unencrypted_oobe_config_dir_.value()
                 << " does not exist. This is not an error if the system is not"
                 << " configured for auto oobe.";
    return false;
  }

  if (!base::PathExists(pub_key_file_)) {
    LOG(WARNING) << "Public key file " << pub_key_file_.value()
                 << " does not exist. ";
    return false;
  }

  if (!ReadPublicKey(pub_key_file_, &public_key_)) {
    return false;
  }

  map<FilePath, string*> signature_files = {
      {config_signature_file_, &config_signature_},
      {enrollment_domain_signature_file_, &enrollment_domain_signature_},
      {usb_device_path_signature_file_, &usb_device_path_signature_}};

  for (auto& file : signature_files) {
    if (!base::PathExists(file.first)) {
      LOG(WARNING) << "File " << file.first.value() << " does not exist. ";
      return false;
    }
    if (!base::ReadFileToString(file.first, file.second)) {
      PLOG(ERROR) << "Failed to read file: " << file.first.value();
      return false;
    }
  }

  return true;
}

bool LoadOobeConfigUsb::VerifyPublicKey() {
  std::unique_ptr<tpmcrypto::Tpm> tpm_crypto = tpmcrypto::CreateTpmInstance();

  uint32_t attributes = 0;
  if (!tpm_crypto->GetNVAttributes(kHashIndexInTpmNvram, &attributes)) {
    LOG(ERROR) << "Failed to get NV attributes.";
    return false;
  }
  if (attributes != kTpmPermissions) {
    LOG(ERROR) << "Attributes given (" << attributes
               << ") does not match the expected (" << kTpmPermissions << ").";
    return false;
  }

  string hash_from_tpm;
  if (!tpm_crypto->NVReadNoAuth(kHashIndexInTpmNvram, 0 /* offset */,
                                SHA256_DIGEST_LENGTH, &hash_from_tpm)) {
    LOG(ERROR) << "Failed to read the hash value from TPM.";
    return false;
  }
  if (hash_from_tpm.size() != SHA256_DIGEST_LENGTH) {
    LOG(ERROR) << "NVReadNoAuth() returned data with size "
               << hash_from_tpm.size() << " != " << SHA256_DIGEST_LENGTH;
    return false;
  }

  string public_key_content;
  if (!base::ReadFileToString(pub_key_file_, &public_key_content)) {
    PLOG(ERROR) << "Failed to read the public key: " << pub_key_file_.value();
    return false;
  }

  // Calculating the hash of the public key.
  char hash_from_public_key[SHA256_DIGEST_LENGTH];
  auto address = reinterpret_cast<unsigned char*>(hash_from_public_key);
  if (SHA256(reinterpret_cast<const unsigned char*>(public_key_content.c_str()),
             public_key_content.length(), address) != address) {
    LOG(ERROR) << "openssl returned an invalid hash pointer!";
    return false;
  }

  // Finally, compare the two hashes to see if they are equal.
  if (string(hash_from_public_key, SHA256_DIGEST_LENGTH) != hash_from_tpm) {
    LOG(ERROR) << "Public key hash ("
               << base::HexEncode(hash_from_public_key, SHA256_DIGEST_LENGTH)
               << ") does not match the hash in the TPM ("
               << base::HexEncode(hash_from_tpm.data(), SHA256_DIGEST_LENGTH)
               << ")";
    return false;
  }
  return true;
}

bool LoadOobeConfigUsb::LocateUsbDevice(FilePath* device_id) {
  // /stateful/unencrypted/oobe_auto_config/usb_device_path.sig is the signature
  // of a /dev/disk/by-id path for the root USB device (e.g. /dev/sda). So to
  // obtain which USB we were on pre-reboot:
  // for dev in /dev/disk/by-id/ *:
  //     if dev verifies with usb_device_path.sig with validation_key.pub:
  //       USB block device is at readlink(dev)
  base::FileEnumerator iter(device_ids_dir_, false,
                            base::FileEnumerator::FILES);
  for (auto link = iter.Next(); !link.empty(); link = iter.Next()) {
    if (VerifySignature(link.value(), usb_device_path_signature_,
                        public_key_) &&
        base::NormalizeFilePath(link, device_id)) {
      LOG(INFO) << "Found USB device " << device_id->value();
      return true;
    }
  }

  LOG(ERROR) << "Did not find the USB device. Probably it was taken out?";
  return false;
}

bool LoadOobeConfigUsb::MountUsbDevice(const FilePath& device_path,
                                       const FilePath& mount_point) {
  LOG(INFO) << "Mounting " << device_path.value() << " on "
            << mount_point.value();
  auto kMountFlags = MS_RDONLY | MS_NOEXEC | MS_NOSUID | MS_NODEV;
  if (mount(device_path.value().c_str(), mount_point.value().c_str(), "ext4",
            kMountFlags, nullptr) != 0) {
    PLOG(ERROR) << "Failed to mount " << device_path.value() << "on "
                << mount_point.value();
    return false;
  }

  return true;
}

bool LoadOobeConfigUsb::UnmountUsbDevice(const FilePath& mount_point) {
  LOG(INFO) << "Unmounting " << mount_point.value();
  if (umount(mount_point.value().c_str()) != 0) {
    PLOG(WARNING) << "Failed to unmount " << mount_point.value();
    return false;
  }
  return true;
}

bool LoadOobeConfigUsb::Load() {
  if (!ReadFiles()) {
    return false;
  }

  if (!VerifyPublicKey()) {
    return false;
  }

  // By now we have all the files necessary on the stateful partition. Now we
  // have to look into the USB drives.
  FilePath device_path;
  if (!LocateUsbDevice(&device_path)) {
    return false;
  }

  ScopedTempDir usb_mount_path;
  if (!usb_mount_path.CreateUniqueTempDir() ||
      !MountUsbDevice(device_path, usb_mount_path.GetPath())) {
    return false;
  }

  // /stateful/unencrypted/oobe_auto_config/config.json.sig is the signature of
  // the config.json file on the USB stateful.
  FilePath unencrypted_oobe_config_dir_on_usb =
      usb_mount_path.GetPath().Append(kUnencryptedOobeConfigDir);
  FilePath config_file_on_usb =
      unencrypted_oobe_config_dir_on_usb.Append(kConfigFile);
  if (!base::ReadFileToString(config_file_on_usb, &config_)) {
    LOG(ERROR) << "Failed to read oobe config file: "
               << config_file_on_usb.value();
    return false;
  }
  if (!VerifySignature(config_, config_signature_, public_key_)) {
    return false;
  }

  // /stateful/unencrypted/oobe_auto_config/enrollment_domain.sig is the
  // signature of the enrollment_domain file on the USB stateful.
  FilePath enrollment_domain_file_on_usb =
      unencrypted_oobe_config_dir_on_usb.Append(kDomainFile);
  if (!base::ReadFileToString(enrollment_domain_file_on_usb,
                              &enrollment_domain_)) {
    LOG(ERROR) << "Failed to read enrollment domain file: "
               << enrollment_domain_file_on_usb.value();
    return false;
  }
  if (!VerifySignature(enrollment_domain_, enrollment_domain_signature_,
                       public_key_)) {
    return false;
  }

  // Ignore the failure.
  UnmountUsbDevice(usb_mount_path.GetPath());
  return true;
}

bool LoadOobeConfigUsb::Store() {
  if (!Load()) {
    return false;
  }

  // Find the GID/UID of oobe_config_restore.
  uid_t uid;
  gid_t gid;
  if (!GetUidGid(kOobeConfigRestoreUser, &uid, &gid)) {
    PLOG(ERROR) << "Failed to get the UID/GID for " << kOobeConfigRestoreUser;
    return false;
  }

  map<FilePath, string*> files = {
      {store_dir_.Append(kConfigFile), &config_},
      {store_dir_.Append(kDomainFile), &enrollment_domain_}};

  for (const auto& file : files) {
    if (!brillo::WriteStringToFile(file.first, *file.second)) {
      PLOG(ERROR) << "Failed to write the config to " << file.first.value();
      return false;
    }
    // Change owners to oobe_config_restore.
    if (lchown(file.first.value().c_str(), uid, gid) != 0) {
      PLOG(ERROR) << "Couldn't change ownership of " << file.first.value()
                  << " to " << kOobeConfigRestoreUser;
      return false;
    }
  }

  return true;
}

bool LoadOobeConfigUsb::GetOobeConfigJson(string* config,
                                          string* enrollment_domain) {
  CHECK(config);
  CHECK(enrollment_domain);

  auto config_file = store_dir_.Append(kConfigFile);
  if (!base::ReadFileToString(config_file, config)) {
    PLOG(ERROR) << "Failed to read in the config file: " << config_file.value();
    return false;
  }

  auto enrollment_domain_file = store_dir_.Append(kDomainFile);
  if (!base::ReadFileToString(enrollment_domain_file, enrollment_domain)) {
    PLOG(ERROR) << "Failed to read in the enrollment_domain file: "
                << enrollment_domain_file.value();
    return false;
  }

  return true;
}

void LoadOobeConfigUsb::CleanupFilesOnDevice() {
  if (!base::DirectoryExists(unencrypted_oobe_config_dir_)) {
    return;
  }

  if (!base::DeleteFile(unencrypted_oobe_config_dir_, true)) {
    LOG(ERROR) << "Failed to delete directory "
               << unencrypted_oobe_config_dir_.value();
  }
}

}  // namespace oobe_config
