// Copyright 2021 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 "src/security/zxcrypt/client.h"

#include <errno.h>
#include <fcntl.h>
#include <fidl/fuchsia.device/cpp/wire.h>
#include <fuchsia/hardware/block/encrypted/c/fidl.h>
#include <inttypes.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fdio.h>
#include <lib/zircon-internal/debug.h>
#include <lib/zx/channel.h>
#include <unistd.h>
#include <zircon/status.h>

#include <memory>
#include <utility>

#include <fbl/string_buffer.h>
#include <fbl/vector.h>
#include <ramdevice-client/ramdisk.h>  // Why does wait_for_device_at() come from here?

#include "src/security/kms-stateless/kms-stateless.h"

#define ZXDEBUG 0

namespace zxcrypt {

// The zxcrypt driver
const char* kDriverLib = "zxcrypt.so";

namespace {

// Null key should be 32 bytes.
const size_t kKeyLength = 32;
const char kHardwareKeyInfo[] = "zxcrypt";

// How many bytes to read from /boot/config/zxcrypt?
const size_t kMaxKeySourcePolicyLength = 32;
const char kZxcryptConfigFile[] = "/pkg/config/zxcrypt";

// Reads /boot/config/zxcrypt to determine what key source policy was selected for this product at
// build time.
//
// Returns ZX_OK and sets |out| to the appropriate KeySourcePolicy value if the file contents
// exactly match a known configuration value.
// Returns ZX_ERR_NOT_FOUND if the config file was not present
// Returns ZX_ERR_IO if the config file could not be read
// Returns ZX_ERR_BAD_STATE if the config value was not recognized.
zx_status_t SelectKeySourcePolicy(KeySourcePolicy* out) {
  fbl::unique_fd fd(open(kZxcryptConfigFile, O_RDONLY));
  if (!fd) {
    xprintf("zxcrypt: couldn't open %s\n", kZxcryptConfigFile);
    return ZX_ERR_NOT_FOUND;
  }

  char key_source_buf[kMaxKeySourcePolicyLength + 1];
  ssize_t len = read(fd.get(), key_source_buf, sizeof(key_source_buf) - 1);
  if (len < 0) {
    xprintf("zxcrypt: couldn't read %s\n", kZxcryptConfigFile);
    return ZX_ERR_IO;
  } else {
    // add null terminator
    key_source_buf[len] = '\0';
    // Dispatch if recognized
    if (strcmp(key_source_buf, "null") == 0) {
      *out = NullSource;
      return ZX_OK;
    }
    if (strcmp(key_source_buf, "tee") == 0) {
      *out = TeeRequiredSource;
      return ZX_OK;
    }
    if (strcmp(key_source_buf, "tee-transitional") == 0) {
      *out = TeeTransitionalSource;
      return ZX_OK;
    }
    if (strcmp(key_source_buf, "tee-opportunistic") == 0) {
      *out = TeeOpportunisticSource;
      return ZX_OK;
    }
    return ZX_ERR_BAD_STATE;
  }
}

}  // namespace

// Returns a ordered vector of |KeySource|s, representing all key sources,
// ordered from most-preferred to least-preferred, that we should try for the
// purposes of creating a new volume
__EXPORT
fbl::Vector<KeySource> ComputeEffectiveCreatePolicy(KeySourcePolicy ksp) {
  fbl::Vector<KeySource> r;
  switch (ksp) {
    case NullSource:
      r = {kNullSource};
      break;
    case TeeRequiredSource:
    case TeeTransitionalSource:
      r = {kTeeSource};
      break;
    case TeeOpportunisticSource:
      r = {kTeeSource, kNullSource};
      break;
  }
  return r;
}

// Returns a ordered vector of |KeySource|s, representing all key sources,
// ordered from most-preferred to least-preferred, that we should try for the
// purposes of unsealing an existing volume
__EXPORT
fbl::Vector<KeySource> ComputeEffectiveUnsealPolicy(KeySourcePolicy ksp) {
  fbl::Vector<KeySource> r;
  switch (ksp) {
    case NullSource:
      r = {kNullSource};
      break;
    case TeeRequiredSource:
      r = {kTeeSource};
      break;
    case TeeTransitionalSource:
    case TeeOpportunisticSource:
      r = {kTeeSource, kNullSource};
      break;
  }
  return r;
}

__EXPORT
fbl::Vector<KeySource> ComputeEffectivePolicy(KeySourcePolicy ksp, Activity activity) {
  fbl::Vector<KeySource> r;
  switch (activity) {
    case Create:
      r = ComputeEffectiveCreatePolicy(ksp);
      break;
    case Unseal:
      r = ComputeEffectiveUnsealPolicy(ksp);
      break;
  }
  return r;
}

__EXPORT
zx_status_t TryWithImplicitKeys(
    Activity activity, fit::function<zx_status_t(std::unique_ptr<uint8_t[]>, size_t)> callback) {
  KeySourcePolicy source;
  zx_status_t rc;
  rc = SelectKeySourcePolicy(&source);
  if (rc != ZX_OK) {
    return rc;
  }

  rc = ZX_ERR_INTERNAL;
  auto ordered_key_sources = ComputeEffectivePolicy(source, activity);

  for (auto& key_source : ordered_key_sources) {
    switch (key_source) {
      case kNullSource: {
        auto key_buf = std::unique_ptr<uint8_t[]>(new uint8_t[kKeyLength]);
        memset(key_buf.get(), 0, kKeyLength);
        rc = callback(std::move(key_buf), kKeyLength);
      } break;
      case kTeeSource: {
        // key info is |kHardwareKeyInfo| padded with 0.
        uint8_t key_info[kms_stateless::kExpectedKeyInfoSize] = {0};
        memcpy(key_info, kHardwareKeyInfo, sizeof(kHardwareKeyInfo));
        // make names for these so the callback to kms_stateless can
        // copy them out later
        std::unique_ptr<uint8_t[]> key_buf;
        size_t key_size;
        zx_status_t kms_rc = kms_stateless::GetHardwareDerivedKey(
            [&](std::unique_ptr<uint8_t[]> cb_key_buffer, size_t cb_key_size) {
              key_size = cb_key_size;
              key_buf = std::unique_ptr<uint8_t[]>(new uint8_t[cb_key_size]);
              memcpy(key_buf.get(), cb_key_buffer.get(), cb_key_size);
              return ZX_OK;
            },
            key_info);

        if (kms_rc != ZX_OK) {
          rc = kms_rc;
          break;
        }

        rc = callback(std::move(key_buf), key_size);
      } break;
    }
    if (rc == ZX_OK) {
      return rc;
    }
  }

  xprintf("TryWithImplicitKeys (%s): none of the %lu key sources succeeded\n",
          activity == Activity::Create ? "create" : "unseal", ordered_key_sources.size());
  return rc;
}

EncryptedVolumeClient::EncryptedVolumeClient(zx::channel&& chan) : chan_(std::move(chan)) {}

zx_status_t EncryptedVolumeClient::Format(const uint8_t* key, size_t key_len, uint8_t slot) {
  zx_status_t rc;
  zx_status_t call_status;
  if ((rc = fuchsia_hardware_block_encrypted_DeviceManagerFormat(chan_.get(), key, key_len, slot,
                                                                 &call_status)) != ZX_OK) {
    xprintf("failed to call Format: %s\n", zx_status_get_string(rc));
    return rc;
  }

  if (call_status != ZX_OK) {
    xprintf("failed to Format: %s\n", zx_status_get_string(call_status));
  }
  return call_status;
}

zx_status_t EncryptedVolumeClient::FormatWithImplicitKey(uint8_t slot) {
  return TryWithImplicitKeys(Activity::Create,
                             [&](std::unique_ptr<uint8_t[]> key_buffer, size_t key_size) {
                               return Format(key_buffer.get(), key_size, slot);
                             });
}

zx_status_t EncryptedVolumeClient::Unseal(const uint8_t* key, size_t key_len, uint8_t slot) {
  zx_status_t rc;
  zx_status_t call_status;
  if ((rc = fuchsia_hardware_block_encrypted_DeviceManagerUnseal(chan_.get(), key, key_len, slot,
                                                                 &call_status)) != ZX_OK) {
    xprintf("failed to call Unseal: %s\n", zx_status_get_string(rc));
    return rc;
  }

  if (call_status != ZX_OK) {
    xprintf("failed to Unseal: %s\n", zx_status_get_string(call_status));
  }
  return call_status;
}

zx_status_t EncryptedVolumeClient::UnsealWithImplicitKey(uint8_t slot) {
  return TryWithImplicitKeys(Activity::Unseal,
                             [&](std::unique_ptr<uint8_t[]> key_buffer, size_t key_size) {
                               return Unseal(key_buffer.get(), key_size, slot);
                             });
}

zx_status_t EncryptedVolumeClient::Seal() {
  zx_status_t rc;
  zx_status_t call_status;
  if ((rc = fuchsia_hardware_block_encrypted_DeviceManagerSeal(chan_.get(), &call_status)) !=
      ZX_OK) {
    xprintf("failed to call Seal: %s\n", zx_status_get_string(rc));
    return rc;
  }
  if (call_status != ZX_OK) {
    xprintf("failed to Seal: %s\n", zx_status_get_string(call_status));
  }
  return call_status;
}

zx_status_t EncryptedVolumeClient::Shred() {
  zx_status_t rc;
  zx_status_t call_status;
  if ((rc = fuchsia_hardware_block_encrypted_DeviceManagerShred(chan_.get(), &call_status)) !=
      ZX_OK) {
    xprintf("failed to call Shred: %s\n", zx_status_get_string(rc));
    return rc;
  }
  if (call_status != ZX_OK) {
    xprintf("failed to Shred: %s\n", zx_status_get_string(call_status));
  }
  return call_status;
}

VolumeManager::VolumeManager(fbl::unique_fd&& block_dev_fd, fbl::unique_fd&& devfs_root_fd)
    : block_dev_fd_(std::move(block_dev_fd)), devfs_root_fd_(std::move(devfs_root_fd)) {}

zx_status_t VolumeManager::OpenInnerBlockDevice(const zx::duration& timeout, fbl::unique_fd* out) {
  zx_status_t rc;
  fbl::String path_base;

  fdio_cpp::UnownedFdioCaller caller(block_dev_fd_.get());
  if (!caller) {
    xprintf("could not convert fd to io\n");
    return ZX_ERR_BAD_STATE;
  }

  if ((rc = RelativeTopologicalPath(caller, &path_base)) != ZX_OK) {
    xprintf("could not get topological path: %s\n", zx_status_get_string(rc));
    return rc;
  }
  fbl::String path_block_exposed = fbl::String::Concat({path_base, "/zxcrypt/unsealed/block"});

  // Early return if path_block_exposed is already present in the device tree
  fbl::unique_fd fd(openat(devfs_root_fd_.get(), path_block_exposed.c_str(), O_RDWR));
  if (fd) {
    out->reset(fd.release());
    return ZX_OK;
  }

  // Wait for the unsealed and block devices to bind
  if ((rc = wait_for_device_at(devfs_root_fd_.get(), path_block_exposed.c_str(), timeout.get())) !=
      ZX_OK) {
    xprintf("timed out waiting for %s to exist: %s\n", path_block_exposed.c_str(),
            zx_status_get_string(rc));
    return rc;
  }
  fd.reset(openat(devfs_root_fd_.get(), path_block_exposed.c_str(), O_RDWR));
  if (!fd) {
    xprintf("failed to open zxcrypt volume\n");
    return ZX_ERR_NOT_FOUND;
  }

  out->reset(fd.release());
  return ZX_OK;
}

zx_status_t VolumeManager::OpenClient(const zx::duration& timeout, zx::channel& out) {
  fdio_cpp::UnownedFdioCaller caller(block_dev_fd_.get());
  if (!caller) {
    xprintf("could not convert fd to io\n");
    return ZX_ERR_BAD_STATE;
  }
  return OpenClientWithCaller(caller, timeout, out);
}

zx_status_t VolumeManager::OpenClientWithCaller(fdio_cpp::UnownedFdioCaller& caller,
                                                const zx::duration& timeout, zx::channel& out) {
  zx_status_t rc;
  fbl::String path_base;

  if ((rc = RelativeTopologicalPath(caller, &path_base)) != ZX_OK) {
    xprintf("could not get topological path: %s\n", zx_status_get_string(rc));
    return rc;
  }
  fbl::String path_manager = fbl::String::Concat({path_base, "/zxcrypt"});

  fbl::unique_fd fd(openat(devfs_root_fd_.get(), path_manager.c_str(), O_RDWR));
  if (!fd) {
    // No manager device in the /dev tree yet.  Try binding the zxcrypt
    // driver and waiting for it to appear.
    auto resp =
        fidl::WireCall<fuchsia_device::Controller>(zx::unowned_channel(caller.borrow_channel()))
            ->Bind(::fidl::StringView::FromExternal(kDriverLib));
    rc = resp.status();
    if (rc == ZX_OK) {
      if (resp->is_error()) {
        rc = resp->error_value();
      }
    }
    if (rc != ZX_OK) {
      xprintf("could not bind zxcrypt driver: %s\n", zx_status_get_string(rc));
      return rc;
    }

    // Await the appearance of the zxcrypt device.
    if ((rc = wait_for_device_at(devfs_root_fd_.get(), path_manager.c_str(), timeout.get())) !=
        ZX_OK) {
      xprintf("zxcrypt driver failed to bind: %s\n", zx_status_get_string(rc));
      return rc;
    }

    fd.reset(openat(devfs_root_fd_.get(), path_manager.c_str(), O_RDWR));
    if (!fd) {
      xprintf("failed to open zxcrypt manager\n");
      return ZX_ERR_NOT_FOUND;
    }
  }

  if ((rc = fdio_get_service_handle(fd.release(), out.reset_and_get_address())) != ZX_OK) {
    xprintf("failed to get service handle for zxcrypt manager: %s\n", zx_status_get_string(rc));
    return rc;
  }

  return ZX_OK;
}

zx_status_t VolumeManager::RelativeTopologicalPath(fdio_cpp::UnownedFdioCaller& caller,
                                                   fbl::String* out) {
  zx_status_t rc;

  // Get the full device path
  fbl::StringBuffer<PATH_MAX> path;
  path.Resize(path.capacity());
  size_t path_len;
  auto resp =
      fidl::WireCall<fuchsia_device::Controller>(zx::unowned_channel(caller.borrow_channel()))
          ->GetTopologicalPath();
  rc = resp.status();
  if (rc == ZX_OK) {
    if (resp->is_error()) {
      rc = resp->error_value();
    } else {
      auto& r = *resp->value();
      path_len = r.path.size();
      memcpy(path.data(), r.path.data(), r.path.size());
    }
  }

  if (rc != ZX_OK) {
    xprintf("could not find parent device: %s\n", zx_status_get_string(rc));
    return rc;
  }

  // Verify that the path returned starts with "/dev/"
  const char* kSlashDevSlash = "/dev/";
  if (path_len < strlen(kSlashDevSlash)) {
    xprintf("path_len way too short: %lu\n", path_len);
    return ZX_ERR_INTERNAL;
  }
  if (strncmp(path.c_str(), kSlashDevSlash, strlen(kSlashDevSlash)) != 0) {
    xprintf("Expected device path to start with '/dev/' but got %s\n", path.c_str());
    return ZX_ERR_INTERNAL;
  }

  // Strip the leading "/dev/" and return the rest
  size_t path_len_sans_dev = path_len - strlen(kSlashDevSlash);
  memmove(path.begin(), path.begin() + strlen(kSlashDevSlash), path_len_sans_dev);

  path.Resize(path_len_sans_dev);
  *out = path.ToString();
  return ZX_OK;
}

}  // namespace zxcrypt
