// Copyright 2020 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.

// clang-format off
#include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h>
#include <Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.ipp>

#include "src/connectivity/weave/adaptation/configuration_manager_delegate_impl.h"
#include "src/connectivity/weave/adaptation/group_key_store_impl.h"
// clang-format on

#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fit/defer.h>
#include <lib/syslog/cpp/macros.h>
#include <net/ethernet.h>
#include <sys/stat.h>
#include <unistd.h>
#include <zircon/status.h>

#include <filesystem>

#include "src/lib/files/file.h"
#include "src/lib/fsl/vmo/file.h"
#include "src/lib/fsl/vmo/strings.h"

namespace nl {
namespace Weave {
namespace DeviceLayer {

namespace {

using ::nl::Weave::DeviceLayer::Internal::EnvironmentConfig;
using ::nl::Weave::DeviceLayer::Internal::GenericConfigurationManagerImpl;
using ::nl::Weave::DeviceLayer::Internal::WeaveConfigManager;
using ::nl::Weave::Profiles::Security::AppKeys::GroupKeyStoreBase;

// Store path and keys for static device information.
constexpr char kDeviceInfoStorePath[] = "/config/data/device_info.json";
constexpr char kDeviceInfoConfigKey_BleDeviceNamePrefix[] = "ble-device-name-prefix";
constexpr char kDeviceInfoConfigKey_DeviceId[] = "device-id";
constexpr char kDeviceInfoConfigKey_DeviceIdPath[] = "device-id-path";
constexpr char kDeviceInfoConfigKey_EnableThread[] = "enable-thread";
constexpr char kDeviceInfoConfigKey_EnableWoBLE[] = "enable-woble";
constexpr char kDeviceInfoConfigKey_EnableWoBLEAdvertisement[] = "enable-woble-advertisement";
constexpr char kDeviceInfoConfigKey_FirmwareRevision[] = "firmware-revision";
constexpr char kDeviceInfoConfigKey_MfrDeviceCertPath[] = "mfr-device-cert-path";
constexpr char kDeviceInfoConfigKey_MfrDeviceCertAllowLocal[] = "mfr-device-cert-allow-local";
constexpr char kDeviceInfoConfigKey_PrivateKeyPath[] = "mfr-private-key-path";
constexpr char kDeviceInfoConfigKey_ProductId[] = "product-id";
constexpr char kDeviceInfoConfigKey_SerialNumber[] = "serial-number";
constexpr char kDeviceInfoConfigKey_VendorId[] = "vendor-id";
constexpr char kDeviceInfoConfigKey_AppletPaths[] = "applet-paths";

// Maximum number of chars in hex for a uint64_t.
constexpr int kWeaveDeviceIdMaxLength = 16;

// Maximum size of Weave certificate.
constexpr int kWeaveCertificateMaxLength = UINT16_MAX;

// Storage path for data files.
const std::string kDataPath = "/data/";

// The required size of a buffer supplied to GetPrimaryWiFiMACAddress.
constexpr size_t kWiFiMacAddressBufSize =
    sizeof(Profiles::DeviceDescription::WeaveDeviceDescriptor::PrimaryWiFiMACAddress);
// Fake MAC address returned by GetPrimaryWiFiMACAddress
constexpr uint8_t kFakeMacAddress[kWiFiMacAddressBufSize] = {0xFF};

}  // unnamed namespace

ConfigurationManagerDelegateImpl::ConfigurationManagerDelegateImpl()
    : device_info_(WeaveConfigManager::CreateReadOnlyInstance(kDeviceInfoStorePath)) {}

WEAVE_ERROR ConfigurationManagerDelegateImpl::Init() {
  WEAVE_ERROR err = WEAVE_NO_ERROR;
  auto context = PlatformMgrImpl().GetComponentContextForProcess();

  FX_CHECK(context->svc()->Connect(hwinfo_device_.NewRequest()) == ZX_OK)
      << "Failed to connect to hwinfo device service.";
  FX_CHECK(context->svc()->Connect(weave_factory_data_manager_.NewRequest()) == ZX_OK)
      << "Failed to connect to weave factory data manager service.";
  FX_CHECK(context->svc()->Connect(factory_store_provider_.NewRequest()) == ZX_OK)
      << "Failed to connect to factory store";

  err = EnvironmentConfig::Init();
  if (err != WEAVE_NO_ERROR) {
    return err;
  }

  err = static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_)->_Init();
  if (err != WEAVE_NO_ERROR) {
    return err;
  }

  err = GetAndStoreHWInfo();
  if (err != WEAVE_NO_ERROR && err != WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND) {
    return err;
  }

  err = GetAndStorePairingCode();
  if (err != WEAVE_NO_ERROR && err != WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND) {
    return err;
  }

  return WEAVE_NO_ERROR;
}

WEAVE_ERROR ConfigurationManagerDelegateImpl::GetDeviceId(uint64_t& device_id) {
  WEAVE_ERROR err =
      EnvironmentConfig::ReadConfigValue(EnvironmentConfig::kConfigKey_MfrDeviceId, device_id);
  if (err == WEAVE_NO_ERROR) {
    return WEAVE_NO_ERROR;
  }

  err = device_info_->ReadConfigValue(kDeviceInfoConfigKey_DeviceId, &device_id);
  if (err != WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND) {
    return err;
  }

  char path[PATH_MAX] = {'\0'};
  size_t out_size;
  err = device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_DeviceIdPath, path, sizeof(path),
                                         &out_size);
  if (err == WEAVE_NO_ERROR) {
    err = GetDeviceIdFromFactory(path, &device_id);
    FX_CHECK(err == WEAVE_NO_ERROR) << "Failed getting device id from factory at path: " << path;
    impl_->StoreManufacturerDeviceId(device_id);
    return err;
  }

  err = GetDeviceIdFromFactory(path, &device_id);
  if (err != WEAVE_NO_ERROR) {
    return err;
  }

  return impl_->StoreManufacturerDeviceId(device_id);
}

WEAVE_ERROR ConfigurationManagerDelegateImpl::GetManufacturerDeviceCertificate(uint8_t* buf,
                                                                               size_t buf_size,
                                                                               size_t& out_len) {
  WEAVE_ERROR err = EnvironmentConfig::ReadConfigValueBin(
      EnvironmentConfig::kConfigKey_MfrDeviceCert, buf, buf_size, out_len);
  if (err == WEAVE_NO_ERROR) {
    return err;
  }

  err = GetAndStoreMfrDeviceCert();
  if (err != WEAVE_NO_ERROR) {
    return err;
  }

  return EnvironmentConfig::ReadConfigValueBin(EnvironmentConfig::kConfigKey_MfrDeviceCert, buf,
                                               buf_size, out_len);
}

bool ConfigurationManagerDelegateImpl::IsFullyProvisioned() {
  return ConnectivityMgr().IsWiFiStationProvisioned() &&
         // TODO(fxbug.dev/58252) Due to incomplete implementation of ThreadStackManager, this
         // predicate does not yet include the line `ConnectivityMgr().IsThreadProvisioned() &&`,
         // but should once complete.
         ConfigurationMgr().IsPairedToAccount() && ConfigurationMgr().IsMemberOfFabric();
}

bool ConfigurationManagerDelegateImpl::IsPairedToAccount() {
  // By default, just use the generic implementation in Weave Device Layer.
  return static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_)
      ->_IsPairedToAccount();
}

bool ConfigurationManagerDelegateImpl::IsMemberOfFabric() {
  // By default, just use the generic implementation in Weave Device Layer.
  return static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_)
      ->_IsMemberOfFabric();
}

GroupKeyStoreBase* ConfigurationManagerDelegateImpl::GetGroupKeyStore() {
  return &group_key_store_;
}

bool ConfigurationManagerDelegateImpl::CanFactoryReset() { return true; }

void ConfigurationManagerDelegateImpl::InitiateFactoryReset() {
  EnvironmentConfig::FactoryResetConfig();
}

WEAVE_ERROR ConfigurationManagerDelegateImpl::ReadPersistedStorageValue(Key key, uint32_t& value) {
  WEAVE_ERROR err = EnvironmentConfig::ReadConfigValue(key, value);
  return (err == WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND)
             ? WEAVE_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND
             : err;
}

WEAVE_ERROR ConfigurationManagerDelegateImpl::WritePersistedStorageValue(Key key, uint32_t value) {
  WEAVE_ERROR err = EnvironmentConfig::WriteConfigValue(key, value);
  return (err != WEAVE_NO_ERROR) ? WEAVE_ERROR_PERSISTED_STORAGE_FAIL : err;
}

WEAVE_ERROR ConfigurationManagerDelegateImpl::GetVendorId(uint16_t& vendor_id) {
  return device_info_->ReadConfigValue(kDeviceInfoConfigKey_VendorId, &vendor_id);
}

WEAVE_ERROR ConfigurationManagerDelegateImpl::GetProductId(uint16_t& product_id) {
  return device_info_->ReadConfigValue(kDeviceInfoConfigKey_ProductId, &product_id);
}

WEAVE_ERROR ConfigurationManagerDelegateImpl::GetFirmwareRevision(char* buf, size_t buf_size,
                                                                  size_t& out_len) {
  return device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_FirmwareRevision, buf, buf_size,
                                          &out_len);
}

WEAVE_ERROR ConfigurationManagerDelegateImpl::GetBleDeviceNamePrefix(char* device_name_prefix,
                                                                     size_t device_name_prefix_size,
                                                                     size_t* out_len) {
  return device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_BleDeviceNamePrefix,
                                          device_name_prefix, device_name_prefix_size, out_len);
}

bool ConfigurationManagerDelegateImpl::IsThreadEnabled() {
  bool is_enabled = false;
  device_info_->ReadConfigValue(kDeviceInfoConfigKey_EnableThread, &is_enabled);
  return is_enabled;
}

bool ConfigurationManagerDelegateImpl::IsWoBLEEnabled() {
  bool is_enabled = false;
  device_info_->ReadConfigValue(kDeviceInfoConfigKey_EnableWoBLE, &is_enabled);
  return is_enabled;
}

bool ConfigurationManagerDelegateImpl::IsWoBLEAdvertisementEnabled() {
  bool is_enabled = IsWoBLEEnabled();
  if (is_enabled) {
    device_info_->ReadConfigValue(kDeviceInfoConfigKey_EnableWoBLEAdvertisement, &is_enabled);
  }
  return is_enabled;
}

WEAVE_ERROR ConfigurationManagerDelegateImpl::GetDeviceDescriptorTLV(uint8_t* buf, size_t buf_size,
                                                                     size_t& encoded_len) {
  return static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_)
      ->_GetDeviceDescriptorTLV(buf, buf_size, encoded_len);
}

WEAVE_ERROR ConfigurationManagerDelegateImpl::GetAndStoreHWInfo() {
  fuchsia::hwinfo::DeviceInfo device_info;
  WEAVE_ERROR err;
  char serial[ConfigurationManager::kMaxSerialNumberLength + 1];
  size_t serial_size = 0;
  if (ZX_OK == hwinfo_device_->GetInfo(&device_info) && device_info.has_serial_number()) {
    return impl_->StoreSerialNumber(device_info.serial_number().c_str(),
                                    device_info.serial_number().length());
  } else if ((err =
                  device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_SerialNumber, serial,
                                                   ConfigurationManager::kMaxSerialNumberLength + 1,
                                                   &serial_size)) == WEAVE_NO_ERROR) {
    return impl_->StoreSerialNumber(serial, serial_size);
  }
  return WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND;
}

WEAVE_ERROR ConfigurationManagerDelegateImpl::GetAndStorePairingCode() {
  fuchsia::weave::FactoryDataManager_GetPairingCode_Result pairing_code_result;
  fuchsia::weave::FactoryDataManager_GetPairingCode_Response pairing_code_response;
  std::string pairing_code;
  char read_value[ConfigurationManager::kMaxPairingCodeLength + 1];
  size_t read_value_size = 0;
  WEAVE_ERROR err;

  // If a pairing code is provided in config-data, it takes precedent over the
  // value provided by the factory data manager.
  err = device_info_->ReadConfigValueStr(EnvironmentConfig::kConfigKey_PairingCode, read_value,
                                         ConfigurationManager::kMaxPairingCodeLength + 1,
                                         &read_value_size);
  if (err == WEAVE_NO_ERROR) {
    return impl_->StorePairingCode(read_value, read_value_size);
  }

  // Otherwise, use the factory data manager as the source of truth.
  zx_status_t status = weave_factory_data_manager_->GetPairingCode(&pairing_code_result);
  if (ZX_OK != status || !pairing_code_result.is_response()) {
    return WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND;
  }

  pairing_code_response = pairing_code_result.response();
  if (pairing_code_response.pairing_code.size() > ConfigurationManager::kMaxPairingCodeLength) {
    return WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND;
  }

  return impl_->StorePairingCode((const char*)pairing_code_response.pairing_code.data(),
                                 pairing_code_response.pairing_code.size());
}

WEAVE_ERROR ConfigurationManagerDelegateImpl::GetAndStoreMfrDeviceCert() {
  char path[PATH_MAX] = {'\0'};
  char mfr_cert[kWeaveCertificateMaxLength];
  std::string cert;
  size_t out_size;
  zx_status_t status;
  WEAVE_ERROR err;
  bool allow_local = false;
  std::filesystem::path full_path(kDataPath);

  // Check if a test cert was provided and read the same.
  err = EnvironmentConfig::ReadConfigValue(EnvironmentConfig::kConfigKey_MfrDeviceCertAllowLocal,
                                           allow_local);
  if (err != WEAVE_NO_ERROR) {
    device_info_->ReadConfigValue(kDeviceInfoConfigKey_MfrDeviceCertAllowLocal, &allow_local);
  }
  if (allow_local) {
    err = device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_MfrDeviceCertPath, path,
                                           sizeof(path), &out_size);
    if (err != WEAVE_NO_ERROR) {
      FX_LOGS(ERROR) << "Local manufacturer cert path not found";
      return err;
    }

    full_path.append(path);
    if (!files::ReadFileToString(full_path.string(), &cert)) {
      FX_LOGS(ERROR) << "failed reading " << path;
      return ZX_ERR_INTERNAL;
    }

    return impl_->StoreManufacturerDeviceCertificate(reinterpret_cast<uint8_t*>(cert.data()),
                                                     cert.size());
  }

  // Read file from factory.
  err = device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_MfrDeviceCertPath, path, sizeof(path),
                                         &out_size);

  if (err != WEAVE_NO_ERROR) {
    FX_LOGS(ERROR) << "No manufacturer device certificate was found";
    return err;
  }

  status = ReadFactoryFile(path, mfr_cert, sizeof(mfr_cert), &out_size);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed getting manufacturer certificate from factory with status "
                   << zx_status_get_string(status) << " for path: " << path;
    return WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND;
  }

  return impl_->StoreManufacturerDeviceCertificate(reinterpret_cast<uint8_t*>(mfr_cert), out_size);
}

zx_status_t ConfigurationManagerDelegateImpl::GetPrivateKeyForSigning(
    std::vector<uint8_t>* signing_key) {
  char path[PATH_MAX] = {'\0'};
  std::filesystem::path full_path(kDataPath);
  WEAVE_ERROR err;
  size_t out_len;

  err = device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_PrivateKeyPath, path, sizeof(path),
                                         &out_len);
  if (err != WEAVE_NO_ERROR) {
    FX_LOGS(INFO) << "No private key found";
    return ZX_ERR_NOT_FOUND;
  }
  full_path.append(path);
  if (!files::ReadFileToVector(full_path.string(), signing_key)) {
    return ZX_ERR_INTERNAL;
  }
  return ZX_OK;
}

zx_status_t ConfigurationManagerDelegateImpl::ReadFactoryFile(const char* path, char* buf,
                                                              size_t buf_size, size_t* out_len) {
  fuchsia::io::DirectorySyncPtr factory_directory;
  zx_status_t status;
  struct stat statbuf;
  int dir_fd;

  // Open the factory store directory as a file descriptor.
  status = factory_store_provider_->GetFactoryStore(factory_directory.NewRequest());
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to get factory store: " << zx_status_get_string(status);
    return status;
  }
  status = fdio_fd_create(factory_directory.Unbind().TakeChannel().release(), &dir_fd);
  if (status != ZX_OK || dir_fd < 0) {
    FX_LOGS(ERROR) << "Failed to open factory store: " << zx_status_get_string(status);
    return status;
  }

  auto close_dir_defer = fit::defer([&] { close(dir_fd); });

  // Grab the fd of the corresponding file path and validate.
  int fd = openat(dir_fd, path, O_RDONLY);
  if (fd < 0) {
    FX_LOGS(ERROR) << "Failed to open " << path << ": " << strerror(errno);
    return ZX_ERR_IO;
  }

  auto close_fd_defer = fit::defer([&] { close(fd); });

  // Check the size of the file.
  if (fstat(fd, &statbuf) < 0) {
    FX_LOGS(ERROR) << "Could not stat file: " << path << ": " << strerror(errno);
    return ZX_ERR_IO;
  }
  size_t file_size = static_cast<size_t>(statbuf.st_size);
  if (file_size > buf_size) {
    FX_LOGS(ERROR) << "File too large for buffer: File size = " << file_size
                   << ", buffer size = " << buf_size;
    return ZX_ERR_BUFFER_TOO_SMALL;
  }

  // Read up to buf_size bytes into buf.
  size_t total_read = 0;
  ssize_t current_read = 0;
  while ((current_read = read(fd, buf + total_read, buf_size - total_read)) > 0) {
    total_read += current_read;
  }

  // Store the total size read.
  if (out_len) {
    *out_len = total_read;
  }

  // Confirm that the last read was successful.
  if (current_read < 0) {
    FX_LOGS(ERROR) << "Failed to read from file: " << strerror(errno);
    status = ZX_ERR_IO;
  }

  return status;
}

zx_status_t ConfigurationManagerDelegateImpl::GetDeviceIdFromFactory(const char* path,
                                                                     uint64_t* factory_device_id) {
  zx_status_t status;
  char output[kWeaveDeviceIdMaxLength + 1] = {'\0'};

  status = ReadFactoryFile(path, output, kWeaveDeviceIdMaxLength, nullptr);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to read " << path << ": " << zx_status_get_string(status);
    return status;
  }

  if (output[0] == '\0') {
    FX_LOGS(ERROR) << "File containing device ID was empty.";
    return ZX_ERR_IO;
  }

  *factory_device_id = strtoull(output, NULL, 16);
  if (errno == ERANGE) {
    FX_LOGS(ERROR) << "Failed to strtoull device ID: " << strerror(errno);
    return ZX_ERR_IO;
  }

  return ZX_OK;
}

zx_status_t ConfigurationManagerDelegateImpl::GetAppletPathList(std::vector<std::string>& out) {
  return device_info_->ReadConfigValueArray(kDeviceInfoConfigKey_AppletPaths, out);
}

WEAVE_ERROR ConfigurationManagerDelegateImpl::GetPrimaryWiFiMACAddress(uint8_t* mac_address) {
  // This is setting the MAC address to FF:0:0:0:0:0; this is for a few reasons:
  //   1. The actual value of the MAC address in the descriptor is not currently used.
  //   2. The MAC address is PII, so it should not be transmitted unless necessary.
  //   3. Some value should still be transmitted as some tools or other devices use the presence of
  //      an WiFi MAC address to determine if WiFi is supported.
  // The best way to meet these requirements is to provide a faked-out MAC address instead.
  std::memcpy(mac_address, kFakeMacAddress, kWiFiMacAddressBufSize);
  return WEAVE_NO_ERROR;
}

}  // namespace DeviceLayer
}  // namespace Weave
}  // namespace nl
