// 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();
  SecurityMgr.SetCASEAuthDelegate(&gPlatformCASEAuthDelegate);
  return WEAVE_NO_ERROR;
}

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 = PlatformMgrImpl().GetComponentContextForProcess()->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) {
  cert_set.Release();
  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
