// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_CERT_INTERNAL_SYSTEM_TRUST_STORE_H_
#define NET_CERT_INTERNAL_SYSTEM_TRUST_STORE_H_

#include <optional>

#include "base/containers/span.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "net/base/net_export.h"
#include "net/cert/internal/platform_trust_store.h"
#include "net/net_buildflags.h"
#include "third_party/boringssl/src/pki/parsed_certificate.h"
#include "third_party/boringssl/src/pki/path_builder.h"
#include "third_party/boringssl/src/pki/trust_store.h"

#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
#include "net/cert/internal/trust_store_chrome.h"
#endif  // CHROME_ROOT_STORE_SUPPORTED

namespace net {

struct ChromeRootCertConstraints;
class NetLogWithSource;

// The SystemTrustStore interface is used to encapsulate a bssl::TrustStore for
// the current platform, with some extra bells and whistles. Implementations
// must be thread-safe.
//
// This is primarily used to abstract out the platform-specific bits that
// relate to configuring the bssl::TrustStore needed for path building.
class SystemTrustStore {
 public:
  virtual ~SystemTrustStore() = default;

  // Returns an aggregate bssl::TrustStore that can be used by the path builder.
  // The store composes the system trust store (if implemented) with manually
  // added trust anchors added via AddTrustAnchor(). This pointer is non-owned,
  // and valid only for the lifetime of |this|. Any bssl::TrustStore objects
  // returned from this method must be thread-safe.
  virtual bssl::TrustStore* GetTrustStore() = 0;

  // IsKnownRoot() returns true if the given certificate originated from the
  // system trust store and is a "standard" one. The meaning of "standard" is
  // that it is one of default trust anchors for the system, as opposed to a
  // user-installed one. (It may *also* be trusted as a user-installed root.)
  virtual bool IsKnownRoot(const bssl::ParsedCertificate* cert) const = 0;
  virtual bool IsKnownMtcAnchor(const bssl::MTCAnchor* anchor) const = 0;

#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
  // Returns the PlatformTrustStore that can be used to look for
  // platform-specific user-added trust settings. This pointer is non-owned,
  // and valid only for the lifetime of |this|. Any net::PlatformTrustStore
  // objects returned from this method must be thread-safe.
  //
  // May return null if there is no PlatformTrustStore.
  virtual net::PlatformTrustStore* GetPlatformTrustStore() = 0;

  // IsLocallyTrustedRoot returns true if the given certificate is trusted in
  // the user-installed root store. (It may *also* be trusted in the Chrome
  // Root Store.)
  virtual bool IsLocallyTrustedRoot(
      const bssl::ParsedCertificate* trust_anchor) = 0;

  // Returns the current version of the Chrome Root Store being used. If
  // Chrome Root Store is not in use, returns 0.
  virtual int64_t chrome_root_store_version() const = 0;

  // Returns the timestamp of the current SignerSet being used. If Chrome Root
  // Store or MTCs are not enabled, returns nullopt.
  virtual std::optional<base::Time> signer_set_timestamp() const = 0;

  // Returns the update timestamp for the Chrome Root Store MTC Metadata
  // component, or nullopt if MTC Metadata is not available.
  virtual std::optional<base::Time> mtc_metadata_update_time() const = 0;

  // Returns the Chrome Root Store constraints for `path`, or returns an empty
  // span if the certificate is not constrained.
  // (If the bssl::TrustAnchor is changed to also contain the root certificate,
  // this could be updated to take a TrustAnchor object instead. See this TODO:
  // https://source.chromium.org/chromium/chromium/src/+/main:third_party/boringssl/src/pki/trust_store.h;l=207;drc=f359b2876732d31100187ef4ad0d462864b168c2)
  virtual base::span<const ChromeRootCertConstraints> GetChromeRootConstraints(
      const bssl::CertPathBuilderResultPath* path) const = 0;

  virtual const TrustStoreChrome::MtcAnchorExtraData* GetMTCAnchorData(
      base::span<const uint8_t> ca_id) const = 0;

  virtual std::optional<bssl::VerifyCertificateChainDelegate::MTCCosigner>
  GetMtcMirrorKey(base::span<const uint8_t> cosigner_id) const = 0;

  virtual bool IsMtcCosignerPolicySatisfied(
      const bssl::ParsedCertificate& target_cert,
      base::Time current_time,
      const bssl::MTCAnchor* mtc_anchor,
      base::span<const std::vector<uint8_t>> valid_additional_cosigners,
      const NetLogWithSource& net_log) const = 0;

  // Returns the crs_root_id for `path`, or nullopt if unknown.
  virtual std::optional<int32_t> GetCrsRootIdForCert(
      const bssl::CertPathBuilderResultPath* path) const = 0;

  virtual bssl::TrustStore* eutl_trust_store() = 0;
#endif
};

#if BUILDFLAG(IS_FUCHSIA)
// Creates an instance of SystemTrustStore that wraps the current platform's SSL
// trust store. This cannot return nullptr.
NET_EXPORT std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore();
#endif

#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
// Creates an instance of SystemTrustStore that wraps the current platform's SSL
// trust store for user added roots, but uses the Chrome Root Store trust
// anchors. This cannot return nullptr.
NET_EXPORT std::unique_ptr<SystemTrustStore>
CreateSslSystemTrustStoreChromeRoot(
    std::unique_ptr<TrustStoreChrome> chrome_root);

// Creates an instance of SystemTrustStore that only uses the Chrome Root Store
// trust anchors.
// This cannot return nullptr.
NET_EXPORT std::unique_ptr<SystemTrustStore> CreateChromeOnlySystemTrustStore(
    std::unique_ptr<TrustStoreChrome> chrome_root);

NET_EXPORT_PRIVATE std::unique_ptr<SystemTrustStore>
CreateSystemTrustStoreChromeForTesting(
    std::unique_ptr<TrustStoreChrome> trust_store_chrome,
    std::unique_ptr<net::PlatformTrustStore> trust_store_system);
#endif  // BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)

#if BUILDFLAG(IS_MAC)
// Initializes trust cache on a worker thread, if the builtin verifier is
// enabled.
NET_EXPORT void InitializeTrustStoreMacCache();
#endif

#if BUILDFLAG(IS_WIN)
// Initializes windows system trust store on a worker thread, if the builtin
// verifier is enabled.
NET_EXPORT void InitializeTrustStoreWinSystem();
#endif

#if BUILDFLAG(IS_ANDROID)
// Initializes Android system trust store on a worker thread, if the builtin
// verifier is enabled.
NET_EXPORT void InitializeTrustStoreAndroid();
#endif

}  // namespace net

#endif  // NET_CERT_INTERNAL_SYSTEM_TRUST_STORE_H_
