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

#include "platform_case_auth_delegate.h"

#include <fuchsia/weave/cpp/fidl.h>
#include <lib/fit/defer.h>

#include <Weave/Profiles/security/WeaveSig.h>
#include <sdk/lib/syslog/cpp/macros.h>

#include "src/connectivity/weave/adaptation/weave_device_platform_error.h"
#include "utils.h"

namespace nl {
namespace Weave {
namespace DeviceLayer {
namespace Internal {

namespace {
using namespace ::nl::Weave::TLV;
using namespace ::nl::Weave::Profiles;
using namespace ::nl::Weave::Profiles::Security;

// TODO(fxbug.dev/51130): Allow build-time configuration of these values.
constexpr size_t kMaxCerts = 10;
constexpr size_t kMaxServiceConfigSize = 10000;
constexpr size_t kCertDecodeBufferSize = 5000;

}  // namespace

PlatformCASEAuthDelegate gPlatformCASEAuthDelegate;

// Implementation of Internal::InitCASEAuthDelegate as defined in the
// openweave-core adaptation layer.
WEAVE_ERROR InitCASEAuthDelegate() {
  new (&gPlatformCASEAuthDelegate)
      PlatformCASEAuthDelegate(sys::ComponentContext::CreateAndServeOutgoingDirectory());
  SecurityMgr.SetCASEAuthDelegate(&gPlatformCASEAuthDelegate);
  return WEAVE_NO_ERROR;
}

PlatformCASEAuthDelegate::PlatformCASEAuthDelegate() : PlatformCASEAuthDelegate(nullptr) {}

PlatformCASEAuthDelegate::PlatformCASEAuthDelegate(std::unique_ptr<sys::ComponentContext> context)
    : context_(std::move(context)) {}

WEAVE_ERROR PlatformCASEAuthDelegate::EncodeNodePayload(const BeginSessionContext& msg_ctx,
                                                        uint8_t* payload_buf,
                                                        uint16_t payload_buf_size,
                                                        uint16_t& payload_len) {
  WEAVE_ERROR error = WEAVE_NO_ERROR;
  size_t device_desc_len;

  error = ConfigurationMgr().GetDeviceDescriptorTLV(payload_buf, (size_t)payload_buf_size,
                                                    device_desc_len);
  if (error != WEAVE_NO_ERROR) {
    return error;
  }

  payload_len = device_desc_len;
  return WEAVE_NO_ERROR;
}

WEAVE_ERROR PlatformCASEAuthDelegate::EncodeNodeCertInfo(const BeginSessionContext& msg_ctx,
                                                         TLVWriter& writer) {
  std::vector<uint8_t> device_cert;
  std::vector<uint8_t> device_ica_certs;
  size_t device_cert_size = 0;
  size_t device_ica_certs_size = 0;
  WEAVE_ERROR err = WEAVE_NO_ERROR;

  // Fetch the provided device certificate.
  err = ConfigurationMgr().GetDeviceCertificate(nullptr, 0, device_cert_size);
  if (err != WEAVE_NO_ERROR) {
    return err;
  }

  device_cert.resize(device_cert_size);
  err = ConfigurationMgr().GetDeviceCertificate(device_cert.data(), device_cert_size,
                                                device_cert_size);
  if (err != WEAVE_NO_ERROR) {
    return err;
  }

  // Fetch any intermediate CA certificates.
  err = ConfigurationMgr().GetDeviceIntermediateCACerts(nullptr, 0, device_ica_certs_size);
  if (err == WEAVE_NO_ERROR) {
    device_ica_certs.resize(device_ica_certs_size);
    err = ConfigurationMgr().GetDeviceIntermediateCACerts(
        device_ica_certs.data(), device_ica_certs_size, device_ica_certs_size);
    if (err != WEAVE_NO_ERROR) {
      return err;
    }
  } else if (err != WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND) {
    return err;
  }

  // Encode the certificate information into the provided TLVWriter.
  return Profiles::Security::CASE::EncodeCASECertInfo(
      writer, device_cert.data(), device_cert_size, device_ica_certs.data(), device_ica_certs_size);
}

WEAVE_ERROR PlatformCASEAuthDelegate::GenerateNodeSignature(const BeginSessionContext& msg_ctx,
                                                            const uint8_t* msg_hash,
                                                            uint8_t msg_hash_len, TLVWriter& writer,
                                                            uint64_t tag) {
  fuchsia::weave::Signer_SignHash_Result result;
  std::vector<uint8_t>* output;
  zx_status_t status;
  std::vector<uint8_t> signing_key;

  // Using a private key directly is intended only for test purposes.
  status = ConfigurationMgrImpl().GetPrivateKeyForSigning(&signing_key);
  if (status == ZX_OK) {
    status = GenerateAndEncodeWeaveECDSASignature(writer, tag, msg_hash, msg_hash_len,
                                                signing_key.data(), signing_key.size());
    secure_memset(signing_key.data(), 0, signing_key.size());
    signing_key.clear();
    return status;
  }

  // If private key is not present, continue with the signer, else return the error
  // encountered in reading the private key.
  if (status != ZX_ERR_NOT_FOUND) {
    FX_LOGS(ERROR) << "Failed reading private key:  " << zx_status_get_string(status);
    return status;
  }

  fuchsia::weave::SignerSyncPtr signer;
  if ((status = context_->svc()->Connect(signer.NewRequest())) != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to connect to signer: " << status;
    return status;
  }

  std::vector<uint8_t> hash(msg_hash, msg_hash + (msg_hash_len * sizeof(uint8_t)));
  if ((status = signer->SignHash(hash, &result)) != ZX_OK || !result.is_response()) {
    FX_LOGS(ERROR) << "Failed to sign hash: " << status;
    return status;
  }

  output = &result.response().signature;
  return ConvertECDSASignature_DERToWeave(output->data(), output->size(), writer, tag);
}

WEAVE_ERROR PlatformCASEAuthDelegate::BeginValidation(const BeginSessionContext& msg_ctx,
                                                      ValidationContext& valid_ctx,
                                                      WeaveCertificateSet& cert_set) {
  WEAVE_ERROR err = WEAVE_NO_ERROR;
  size_t service_config_len = 0;
  uint64_t now_ms;

  service_config_.clear();
  service_config_.resize(kMaxServiceConfigSize);

  err = cert_set.Init(kMaxCerts, kCertDecodeBufferSize);
  if (err != WEAVE_NO_ERROR) {
    return err;
  }

  auto release_cert_set = fit::defer([&] { cert_set.Release(); });

  // Read the service config data.
  err = ConfigurationMgr().GetServiceConfig(service_config_.data(), service_config_.size(),
                                            service_config_len);
  if (err != WEAVE_NO_ERROR) {
    return err;
  }

  // Load the list of trusted root certificates from the service config.
  err = LoadCertsFromServiceConfig(service_config_.data(), service_config_len, cert_set);
  if (err != WEAVE_NO_ERROR) {
    return err;
  }

  // Scan the list of trusted certs loaded from the service config. If the list
  // contains a general certificate with a CommonName subject, presume this is
  // the access token certificate.
  for (uint8_t cert_index = 0; cert_index < cert_set.CertCount; cert_index++) {
    WeaveCertificateData* cert = &cert_set.Certs[cert_index];
    if ((cert->CertFlags & kCertFlag_IsTrusted) != 0 && cert->CertType == kCertType_General &&
        cert->SubjectDN.AttrOID == ASN1::kOID_AttributeType_CommonName) {
      cert->CertType = kCertType_AccessToken;
    }
  }

  memset(&valid_ctx, 0, sizeof(valid_ctx));

  // Set the effective time for certificate validation. Use the current time if
  // the system's real time clock is synchronized, but otherwise use the
  // firmware build time and arrange to ignore the 'not before' date in the
  // peer's certificate.
  err = System::Layer::GetClock_RealTimeMS(now_ms);
  if (err == WEAVE_NO_ERROR) {
    // TODO(fxbug.dev/51890): The default implementation of GetClock_RealTimeMS only returns
    // not-synced if the value is before Jan 1, 2000. Use the UTC fidl instead
    // to confirm whether the clock source is from some external source.
    valid_ctx.EffectiveTime = SecondsSinceEpochToPackedCertTime((uint32_t)(now_ms / 1000));
  } else if (err == WEAVE_SYSTEM_ERROR_REAL_TIME_NOT_SYNCED) {
    // TODO(fxbug.dev/51890): Acquire the firmware build time, for now we set it to Jan 1, 2020
    // as sane default time.
    valid_ctx.EffectiveTime = SecondsSinceEpochToPackedCertTime(1577836800U);
    valid_ctx.ValidateFlags |= kValidateFlag_IgnoreNotBefore;
    FX_LOGS(WARNING) << "Real time clock not synchronized, using default time for cert validation.";
  }

  valid_ctx.RequiredKeyUsages = kKeyUsageFlag_DigitalSignature;
  valid_ctx.RequiredKeyPurposes =
      msg_ctx.IsInitiator() ? kKeyPurposeFlag_ServerAuth : kKeyPurposeFlag_ClientAuth;
  release_cert_set.cancel();
  return WEAVE_NO_ERROR;
}

WEAVE_ERROR PlatformCASEAuthDelegate::HandleValidationResult(const BeginSessionContext& msg_ctx,
                                                             ValidationContext& valid_ctx,
                                                             WeaveCertificateSet& cert_set,
                                                             WEAVE_ERROR& valid_res) {
  // If an error was already detected in a previous stage, return it as-is.
  if (valid_res != WEAVE_NO_ERROR) {
    return WEAVE_NO_ERROR;
  }

  uint64_t cert_id = valid_ctx.SigningCert->SubjectDN.AttrValue.WeaveId;
  switch (valid_ctx.SigningCert->CertType) {
    // If the peer authenticated with a device certificate:
    case kCertType_Device:
      // Reject the peer if the certificate node ID and peer node ID do not match.
      if (cert_id != msg_ctx.PeerNodeId) {
        valid_res = WEAVE_ERROR_WRONG_CERTIFICATE_SUBJECT;
      }
      break;
    // If the peer authenticated with a service endpoint certificate:
    case kCertType_ServiceEndpoint:
      // Reject the peer if the certificate node ID and peer node ID do not match.
      if (cert_id != msg_ctx.PeerNodeId) {
        valid_res = WEAVE_ERROR_WRONG_CERTIFICATE_SUBJECT;
      }
      // Reject the peer if they are initiating the session. Service endpoint
      // certificates cannot be used to initiate sessions to other nodes, only
      // to respond.
      if (!msg_ctx.IsInitiator()) {
        valid_res = WEAVE_ERROR_CERT_USAGE_NOT_ALLOWED;
      }
      break;
    // If the peer authenticated with an access token certificate:
    case kCertType_AccessToken:
      // Reject the peer if they are the session responder. Access token
      // certificates can only be used to initiate sessions.
      if (msg_ctx.IsInitiator()) {
        valid_res = WEAVE_ERROR_CERT_USAGE_NOT_ALLOWED;
      }
      break;
    default:
      valid_res = WEAVE_ERROR_CERT_USAGE_NOT_ALLOWED;
  }
  return WEAVE_NO_ERROR;
}

void PlatformCASEAuthDelegate::EndValidation(const BeginSessionContext& msg_ctx,
                                             ValidationContext& valid_ctx,
                                             WeaveCertificateSet& cert_set) {
  service_config_.clear();
}

WEAVE_ERROR PlatformCASEAuthDelegate::LoadCertsFromServiceConfig(const uint8_t* service_config,
                                                                 uint16_t service_config_len,
                                                                 WeaveCertificateSet& cert_set) {
  WEAVE_ERROR err = WEAVE_NO_ERROR;
  TLVReader reader;
  TLVType top_level_container;

  reader.Init(service_config, service_config_len);
  reader.ImplicitProfileId = kWeaveProfile_ServiceProvisioning;

  err = reader.Next(kTLVType_Structure, ProfileTag(kWeaveProfile_ServiceProvisioning,
                                                   ServiceProvisioning::kTag_ServiceConfig));
  if (err != WEAVE_NO_ERROR) {
    return err;
  }

  err = reader.EnterContainer(top_level_container);
  if (err != WEAVE_NO_ERROR) {
    return err;
  }

  err = reader.Next(kTLVType_Array, ContextTag(ServiceProvisioning::kTag_ServiceConfig_CACerts));
  if (err != WEAVE_NO_ERROR) {
    return err;
  }

  err = cert_set.LoadCerts(reader, kDecodeFlag_IsTrusted);
  if (err != WEAVE_NO_ERROR) {
    return err;
  }

  return WEAVE_NO_ERROR;
}

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