// Copyright 2022 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/storage/fs_test/crypt_service.h"

#include <fidl/fuchsia.fxfs/cpp/wire.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/fdio/directory.h>
#include <lib/fidl/cpp/wire/channel.h>
#include <lib/fidl/cpp/wire/connect_service.h>

#include "sdk/lib/syslog/cpp/macros.h"

namespace fs_test {

zx::result<> SetUpCryptWithRandomKeys(
    fidl::UnownedClientEnd<fuchsia_io::Directory> service_directory) {
  fidl::WireSyncClient<fuchsia_fxfs::CryptManagement> client;
  if (auto management_service_or =
          component::ConnectAt<fuchsia_fxfs::CryptManagement>(service_directory);
      management_service_or.is_error()) {
    FX_LOGS(ERROR) << "Unable to connect to crypt management service: "
                   << management_service_or.status_string();
    return management_service_or.take_error();
  } else {
    client = fidl::WireSyncClient(*std::move(management_service_or));
  }
  unsigned char key[32];
  zx_cprng_draw(key, sizeof(key));
  if (auto result = client->AddWrappingKey(0, fidl::VectorView<unsigned char>::FromExternal(key));
      !result.ok()) {
    FX_LOGS(ERROR) << "Failed to add wrapping key: " << result.status_string();
    return zx::error(result.status());
  }
  zx_cprng_draw(key, sizeof(key));
  if (auto result = client->AddWrappingKey(1, fidl::VectorView<unsigned char>::FromExternal(key));
      !result.ok()) {
    FX_LOGS(ERROR) << "Failed to add wrapping key: " << result.status_string();
    return zx::error(result.status());
  }
  if (auto result = client->SetActiveKey(fuchsia_fxfs::wire::KeyPurpose::kData, 0); !result.ok()) {
    FX_LOGS(ERROR) << "Failed to set active data key: " << result.status_string();
    return zx::error(result.status());
  }
  if (auto result = client->SetActiveKey(fuchsia_fxfs::wire::KeyPurpose::kMetadata, 1);
      !result.ok()) {
    FX_LOGS(ERROR) << "Failed to set active data key: " << result.status_string();
    return zx::error(result.status());
  }
  return zx::ok();
}

zx::result<zx::channel> GetCryptService() {
  static bool initialized = false;
  if (!initialized) {
    auto service_endpoints_or = fidl::CreateEndpoints<fuchsia_io::Directory>();
    if (service_endpoints_or.is_error()) {
      FX_LOGS(ERROR) << "Unable to create endpoints: " << service_endpoints_or.status_string();
      return service_endpoints_or.take_error();
    }

    if (zx_status_t status =
            fdio_service_connect("/svc", service_endpoints_or->server.TakeChannel().release());
        status != ZX_OK) {
      FX_LOGS(ERROR) << "Unable to open /svc: " << zx_status_get_string(status);
      return zx::error(status);
    }

    if (auto status = SetUpCryptWithRandomKeys(service_endpoints_or->client); status.is_error()) {
      return status.take_error();
    }

    initialized = true;
  }

  if (auto crypt_service_or = component::Connect<fuchsia_fxfs::Crypt>();
      crypt_service_or.is_error()) {
    FX_LOGS(ERROR) << "Unable to connect to the crypt service: "
                   << crypt_service_or.status_string();
    return crypt_service_or.take_error();
  } else {
    return zx::ok(crypt_service_or->TakeChannel());
  }
}

}  // namespace fs_test

extern "C" {

// Exported for Rust
zx_status_t get_crypt_service(zx_handle_t* handle) {
  if (auto channel = fs_test::GetCryptService(); channel.is_error()) {
    return channel.error_value();
  } else {
    *handle = channel->release();
    return ZX_OK;
  }
}

}  // extern
