chromium/chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager.h

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

#ifndef CHROME_BROWSER_NEARBY_SHARING_CERTIFICATES_NEARBY_SHARE_CERTIFICATE_MANAGER_H_
#define CHROME_BROWSER_NEARBY_SHARING_CERTIFICATES_NEARBY_SHARE_CERTIFICATE_MANAGER_H_

#include <optional>
#include <vector>

#include "base/containers/span.h"
#include "base/functional/callback.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.h"
#include "chrome/browser/nearby_sharing/certificates/nearby_share_encrypted_metadata_key.h"
#include "chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.h"
#include "chromeos/ash/services/nearby/public/mojom/nearby_share_settings.mojom.h"
#include "third_party/nearby/sharing/proto/rpc_resources.pb.h"

// The Nearby Share certificate manager maintains the local device's private
// certificates and contacts' public certificates. The manager communicates with
// the Nearby server to 1) download contacts' public certificates and 2) upload
// local device public certificates to be distributed to contacts.
//
// The class contatins methods for performing crypto operations with the
// currently valid private certificate of a given visibility, such as signing a
// payload or generating an encrypted metadata key for an advertisement. For
// crypto operations related to public certificates, such as verifying a
// payload, find and decrypt the relevant certificate with
// DecryptPublicCertificate(), then use the
// NearbyShareDecryptedPublicCertificate class to perform the crypto operations.
// NOTE: The NearbySharePrivateCertificate class is not directly returned
// because storage needs to be update whenever salts are consumed for metadata
// key encryption.
//
// Observers are notified of any changes to private/public certificates.
class NearbyShareCertificateManager {
 public:
  class Observer : public base::CheckedObserver {
   public:
    virtual void OnPublicCertificatesDownloaded() = 0;
    virtual void OnPrivateCertificatesChanged() = 0;
  };

  using CertDecryptedCallback = base::OnceCallback<void(
      std::optional<NearbyShareDecryptedPublicCertificate>)>;

  NearbyShareCertificateManager();
  virtual ~NearbyShareCertificateManager();

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // Starts/Stops certificate task scheduling.
  void Start();
  void Stop();
  bool is_running() { return is_running_; }

  // Encrypts the metadata encryption key of the currently valid private
  // certificate with |visibility|. Returns std::nullopt if there is no valid
  // private certificate with |visibility|, if the encryption failed, or if
  // there are no remaining salts.
  std::optional<NearbyShareEncryptedMetadataKey>
  EncryptPrivateCertificateMetadataKey(
      nearby_share::mojom::Visibility visibility);

  // Signs the input |payload| using the currently valid private certificate
  // with |visibility|. Returns std::nullopt if there is no valid private
  // certificate with |visibility| or if the signing was unsuccessful.
  std::optional<std::vector<uint8_t>> SignWithPrivateCertificate(
      nearby_share::mojom::Visibility visibility,
      base::span<const uint8_t> payload) const;

  // Creates a hash of the |authentication_token| using the currently valid
  // private certificate. Returns std::nullopt if there is no valid private
  // certificate with |visibility|.
  std::optional<std::vector<uint8_t>>
  HashAuthenticationTokenWithPrivateCertificate(
      nearby_share::mojom::Visibility visibility,
      base::span<const uint8_t> authentication_token) const;

  // Returns all local device private certificates of |visibility| converted to
  // public certificates. The public certificates' for_selected_contacts fields
  // will be set to reflect the |visibility|. NOTE: Only certificates with the
  // requested visibility will be returned; if selected-contacts visibility is
  // passed in, the all-contacts visibility certificates will *not* be returned
  // as well.
  virtual std::vector<nearby::sharing::proto::PublicCertificate>
  GetPrivateCertificatesAsPublicCertificates(
      nearby_share::mojom::Visibility visibility) = 0;

  // Returns in |callback| the public certificate that is able to be decrypted
  // using |encrypted_metadata_key|, and returns std::nullopt if no such public
  // certificate exists.
  virtual void GetDecryptedPublicCertificate(
      NearbyShareEncryptedMetadataKey encrypted_metadata_key,
      CertDecryptedCallback callback) = 0;

  // Makes an RPC call to the Nearby server to retrieve all public certificates
  // available to the local device. These are also downloaded periodically.
  // Observers are notified when all public certificate downloads succeed via
  // OnPublicCertificatesDownloaded().
  virtual void DownloadPublicCertificates() = 0;

 protected:
  virtual void OnStart() = 0;
  virtual void OnStop() = 0;

  // Returns the currently valid private certificate with |visibility|, or
  // returns std::nullopt if one does not exist.
  virtual std::optional<NearbySharePrivateCertificate>
  GetValidPrivateCertificate(
      nearby_share::mojom::Visibility visibility) const = 0;

  // Updates the existing record for |private_certificate|. If no such record
  // exists, this function does nothing.
  virtual void UpdatePrivateCertificateInStorage(
      const NearbySharePrivateCertificate& private_certificate) = 0;

  void NotifyPublicCertificatesDownloaded();
  void NotifyPrivateCertificatesChanged();

 private:
  bool is_running_ = false;
  base::ObserverList<Observer> observers_;
};

#endif  // CHROME_BROWSER_NEARBY_SHARING_CERTIFICATES_NEARBY_SHARE_CERTIFICATE_MANAGER_H_