// Copyright 2019 The Fuchsia 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 "factory_reset.h"

#include <dirent.h>
#include <fcntl.h>
#include <fidl/fuchsia.fshost/cpp/wire.h>
#include <fidl/fuchsia.hardware.block/cpp/wire.h>
#include <lib/component/incoming/cpp/clone.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/fdio.h>
#include <lib/fit/defer.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/channel.h>
#include <zircon/errors.h>
#include <zircon/status.h>

#include "src/recovery/factory_reset/factory_reset_config.h"
#include "src/security/lib/kms-stateless/kms-stateless.h"
#include "src/security/lib/zxcrypt/client.h"
#include "src/storage/lib/block_client/cpp/remote_block_device.h"
#include "src/storage/lib/fs_management/cpp/format.h"
namespace factory_reset {

const char* kBlockPath = "class/block";

zx_status_t ShredZxcryptDevice(fidl::ClientEnd<fuchsia_device::Controller> device,
                               fbl::unique_fd devfs_root_fd) {
  zxcrypt::VolumeManager volume(std::move(device), std::move(devfs_root_fd));

  // Note: the access to /dev/sys/platform from the manifest is load-bearing
  // here, because we can only find the related zxcrypt device for a particular
  // block device via appending "/zxcrypt" to its topological path, and the
  // canonical topological path sits under sys/platform.
  zx::channel driver_chan;
  if (zx_status_t status = volume.OpenClient(zx::sec(5), driver_chan); status != ZX_OK) {
    FX_PLOGS(ERROR, status) << "Couldn't open channel to zxcrypt volume manager";
    return status;
  }

  zxcrypt::EncryptedVolumeClient zxc_manager(std::move(driver_chan));
  if (zx_status_t status = zxc_manager.Shred(); status != ZX_OK) {
    FX_PLOGS(ERROR, status) << "Couldn't shred volume";
    return status;
  }

  return ZX_OK;
}

FactoryReset::FactoryReset(async_dispatcher_t* dispatcher,
                           fidl::ClientEnd<fuchsia_io::Directory> dev,
                           fidl::ClientEnd<fuchsia_hardware_power_statecontrol::Admin> admin,
                           fidl::ClientEnd<fuchsia_fshost::Admin> fshost_admin,
                           factory_reset_config::Config config)
    : dev_(std::move(dev)),
      admin_(std::move(admin), dispatcher),
      fshost_admin_(std::move(fshost_admin), dispatcher),
      config_(config) {}

void FactoryReset::Shred(fit::callback<void(zx_status_t)> callback) const {
  // First try and shred the data volume using fshost.
  auto cb = [this, callback = std::move(callback)](const auto& result) mutable {
    callback([this, &result]() {
      zx_status_t status;
      if (result.ok()) {
        const fit::result response = result.value();
        if (response.is_ok()) {
          FX_LOGS(INFO) << "fshost ShredDataVolume succeeded";
          return ZX_OK;
        }
        if (response.is_error()) {
          if (response.error_value() != ZX_ERR_NOT_SUPPORTED) {
            FX_PLOGS(ERROR, response.error_value()) << "fshost ShredDataVolume failed";
          }
        }
        status = response.error_value();
      } else {
        FX_LOGS(ERROR) << "Failed to call ShredDataVolume: " << result.FormatDescription();
        status = result.status();
      }
      if (config_.use_fxblob()) {
        // We can't fall back to shredding manually for Fxblob, so fail now.
        return status;
      }
      // Fall back to shredding all zxcrypt devices...
      FX_LOGS(INFO) << "Falling back to manually shredding zxcrypt...";
      zx::result block_dir = component::ConnectAt<fuchsia_io::Directory>(dev_, kBlockPath);
      if (block_dir.is_error()) {
        FX_PLOGS(ERROR, block_dir.error_value()) << "Failed to open '" << kBlockPath << "'";
        return block_dir.error_value();
      }
      int fd;
      if (zx_status_t status = fdio_fd_create(block_dir.value().TakeChannel().release(), &fd);
          status != ZX_OK) {
        FX_PLOGS(ERROR, status) << "Failed to create fd from '" << kBlockPath << "'";
        return status;
      }
      DIR* const dir = fdopendir(fd);
      auto cleanup = fit::defer([dir]() { closedir(dir); });
      fdio_cpp::UnownedFdioCaller caller(dirfd(dir));
      // Attempts to shred every zxcrypt volume found.
      while (true) {
        dirent* de = readdir(dir);
        if (de == nullptr) {
          return ZX_OK;
        }
        if (std::string_view(de->d_name) == ".") {
          continue;
        }
        zx::result block =
            component::ConnectAt<fuchsia_hardware_block::Block>(caller.directory(), de->d_name);
        if (block.is_error()) {
          FX_PLOGS(ERROR, block.status_value()) << "Error opening " << de->d_name;
          continue;
        }

        std::string controller_path = std::string(de->d_name) + "/device_controller";
        zx::result block_controller =
            component::ConnectAt<fuchsia_device::Controller>(caller.directory(), controller_path);
        if (block_controller.is_error()) {
          FX_PLOGS(ERROR, block_controller.status_value()) << "Error opening " << controller_path;
          continue;
        }
        if (fs_management::DetectDiskFormat(block.value()) == fs_management::kDiskFormatZxcrypt) {
          fbl::unique_fd dev_fd;
          {
            zx::result dev = component::Clone(dev_);
            if (dev.is_error()) {
              FX_PLOGS(ERROR, dev.error_value()) << "Error cloning connection to /dev";
              continue;
            }
            if (zx_status_t status = fdio_fd_create(dev.value().TakeChannel().release(),
                                                    dev_fd.reset_and_get_address());
                status != ZX_OK) {
              FX_PLOGS(ERROR, status) << "Error creating file descriptor from /dev";
              continue;
            }
          }

          zx_status_t status =
              ShredZxcryptDevice(std::move(block_controller.value()), std::move(dev_fd));
          if (status != ZX_OK) {
            FX_PLOGS(ERROR, status) << "Error shredding " << de->d_name;
            return status;
          }
          FX_LOGS(INFO) << "Successfully shredded " << de->d_name;
        }
      }
    }());
  };
  fshost_admin_->ShredDataVolume().ThenExactlyOnce(std::move(cb));
}

void FactoryReset::Reset(fit::callback<void(zx_status_t)> callback) {
  FX_LOGS(INFO) << "Reset called. Starting shred";
  Shred([this, callback = std::move(callback)](zx_status_t status) mutable {
    if (status != ZX_OK) {
      FX_PLOGS(ERROR, status) << "Shred failed";
      callback(status);
      return;
    }
    FX_LOGS(INFO) << "Finished shred";

    uint8_t key_info[kms_stateless::kExpectedKeyInfoSize] = "zxcrypt";
    switch (zx_status_t status = kms_stateless::RotateHardwareDerivedKeyFromService(key_info);
            status) {
      case ZX_OK:
        break;
      case ZX_ERR_NOT_SUPPORTED:
        FX_LOGS(WARNING)
            << "FactoryReset: The device does not support rotatable hardware keys. Ignoring";
        break;
      default:
        FX_PLOGS(ERROR, status) << "FactoryReset: RotateHardwareDerivedKey() failed";
        callback(status);
        return;
    }
    // Reboot to initiate the recovery.
    FX_LOGS(INFO) << "Requesting reboot...";
    auto cb = [callback = std::move(callback)](const auto& result) mutable {
      if (!result.ok()) {
        FX_PLOGS(ERROR, result.status()) << "Reboot call failed";
        callback(result.status());
        return;
      }
      const auto& response = result.value();
      if (response.is_error()) {
        FX_PLOGS(ERROR, response.error_value()) << "Reboot returned error";
        callback(response.error_value());
        return;
      }
      callback(ZX_OK);
    };
    admin_->Reboot(fuchsia_hardware_power_statecontrol::wire::RebootReason::kFactoryDataReset)
        .ThenExactlyOnce(std::move(cb));
  });
}

void FactoryReset::Reset(ResetCompleter::Sync& completer) {
  Reset([completer = completer.ToAsync()](zx_status_t status) mutable { completer.Reply(status); });
}

}  // namespace factory_reset
