chromium/chrome/browser/certificate_provider/certificate_provider_service.h

// Copyright 2015 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_CERTIFICATE_PROVIDER_CERTIFICATE_PROVIDER_SERVICE_H_
#define CHROME_BROWSER_CERTIFICATE_PROVIDER_CERTIFICATE_PROVIDER_SERVICE_H_

#include <stdint.h>

#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/containers/span.h"
#include "base/functional/callback_forward.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "chrome/browser/certificate_provider/certificate_requests.h"
#include "chrome/browser/certificate_provider/pin_dialog_manager.h"
#include "chrome/browser/certificate_provider/sign_requests.h"
#include "chrome/browser/certificate_provider/thread_safe_certificate_map.h"
#include "chromeos/components/certificate_provider/certificate_info.h"
#include "components/account_id/account_id.h"
#include "components/keyed_service/core/keyed_service.h"
#include "net/cert/x509_certificate.h"
#include "net/ssl/client_cert_identity.h"
#include "net/ssl/ssl_private_key.h"

namespace chromeos {

class CertificateProvider;

// A keyed service that manages registrations of extensions as certificate
// providers. It exposes all certificates that are provided by extensions
// through a |CertificateProvider| object that can be created using
// |CreateCertificateProvider()|. Private key handles are exposed through
// net::ClientKeyStore. Sign operations are routed to the extension that exposed
// the certificate.
//
// The typical order of execution is as follows:
//  1. HTTPS server requests client certs or
//     chrome.platformKeys.selectClientCertificates is called.
//  2. This starts the certificate request with ID x.
//  3. All extensions registered for the event onClientCertificatesRequested are
//     notified, the exposed callback is bound to request ID x.
//  4. Wait for all extensions to reply to request with ID x
//     or time out.
//  5. Filter all certificates from extensions that replied to request with ID x
//     and from the platform.
//  6. Show the selection dialog, user will select one.
//  7. Create private key handle. As this call is not associated with a specific
//     certificate request it looks at the certificate list obtained by the most
//     recent certificate request (execution of 3-5), which may or may not have
//     had ID x.
//  8. Sign() function of the key handle is called.
//  9. Forward the sign request to the extension that registered the
//     certificate. This request has a new sign request ID y.
// 10. Wait until the extension replies with the signature or fails the sign
//     request with ID y.
// 11. Forward the signature or failure as result of the key handle's Sign()
//     function.
class CertificateProviderService : public KeyedService {
 public:
  using CertificateInfo = certificate_provider::CertificateInfo;
  using CertificateInfoList = certificate_provider::CertificateInfoList;

  class Delegate {
   public:
    Delegate() {}

    Delegate(const Delegate&) = delete;
    Delegate& operator=(const Delegate&) = delete;

    virtual ~Delegate() {}

    // Returns the ids of the extensions that want to provide certificates and
    // therefore want to be notified about certificate requests. This is called
    // once per client certificate request by the net layer.
    virtual std::vector<std::string> CertificateProviderExtensions() = 0;

    // Broadcasts a certificate request with |cert_request_id| to all
    // certificate provider extensions.
    virtual void BroadcastCertificateRequest(int cert_request_id) = 0;

    // Dispatches a sign request with the given arguments to the extension with
    // id |extension_id|. |algorithm| is a TLS 1.3 SignatureScheme value. See
    // net::SSLPrivateKey for details. Returns whether that extension is
    // actually a listener for that event.
    virtual bool DispatchSignRequestToExtension(
        const std::string& extension_id,
        int sign_request_id,
        uint16_t algorithm,
        const scoped_refptr<net::X509Certificate>& certificate,
        base::span<const uint8_t> input) = 0;
  };

  class Observer : public base::CheckedObserver {
   public:
    // Called when an extension updates the certificates it provides.
    virtual void OnCertificatesUpdated(
        const std::string& extension_id,
        const CertificateInfoList& certificate_infos) {}

    // Called when a sign request gets successfully completed.
    virtual void OnSignCompleted(
        const scoped_refptr<net::X509Certificate>& certificate,
        const std::string& extension_id) {}
  };

  // |SetDelegate| must be called exactly once directly after construction.
  CertificateProviderService();
  CertificateProviderService(const CertificateProviderService&) = delete;
  CertificateProviderService& operator=(const CertificateProviderService&) =
      delete;
  ~CertificateProviderService() override;

  // Must be called exactly once after construction and before other methods are
  // called. The delegate will be destroyed in the destructor of the service and
  // not before, which allows to unregister observers (e.g. for
  // OnExtensionUnloaded) in the delegate's destructor on behalf of the service.
  void SetDelegate(std::unique_ptr<Delegate> delegate);

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

  // Updates the certificates provided by the extension with |extension_id| to
  // be |certificates_infos|.
  void SetCertificatesProvidedByExtension(
      const std::string& extension_id,
      const CertificateInfoList& certificate_infos);

  // Must be called when an extension replied to a previous certificate
  // request, after the new certificates were registered with
  // SetCertificatesProvidedByExtension(). For each request, it is expected that
  // every registered extension replies exactly once. |cert_request_id| must
  // refer to a previously broadcast certificate request. Returns false if the
  // request id is unknown or it was called before with the same combination of
  // request id and extension id. E.g. the request could have timed out before
  // an extension replies.
  bool SetExtensionCertificateReplyReceived(const std::string& extension_id,
                                            int cert_request_id);

  // Must be called with the reply of an extension to a previous sign request.
  // |sign_request_id| is provided in the reply of the extension and must refer
  // to a previous sign request. The extension id must be provided, because
  // not the sign request id alone but only the pair (extension id, sign request
  // id) is unambiguous.
  // If the signature could be calculated by the extension, |signature| is
  // provided in the reply and should be the signature of the data sent in the
  // sign request. Otherwise, in case of a failure, |signature| must be empty.
  // Returns false if |sign_request_id| is not referring to a pending request.
  bool ReplyToSignRequest(const std::string& extension_id,
                          int sign_request_id,
                          const std::vector<uint8_t>& signature);

  // Returns whether this certificate was provided by any extension during the
  // lifetime of this service. If this certificate is currently provided by an
  // extension, sets |is_currently_provided| to true and |extension_id| to that
  // extension's id. If this certificate was provided before but not anymore,
  // |is_currently_provided| will be set to false and |extension_id| will not be
  // modified.
  bool LookUpCertificate(const net::X509Certificate& cert,
                         bool* is_currently_provided,
                         std::string* extension_id);

  // Returns a CertificateProvider that always returns the latest list of
  // certificates that are provided by all registered extensions. Therefore, it
  // is sufficient to create the CertificateProvider once and then repeatedly
  // call its |GetCertificates()|. The returned provider is valid even after the
  // destruction of this service.
  std::unique_ptr<CertificateProvider> CreateCertificateProvider();

  // Called whenever the extension with id |extension_id| unregisters from
  // receiving future certificate requests. This will clear certificates
  // currently provided by the extension.
  void OnExtensionUnregistered(const std::string& extension_id);

  // Must be called if extension with id |extension_id| is unloaded and cannot
  // serve certificates anymore. This should be called everytime the
  // corresponding notification of the ExtensionRegistry is triggered.
  void OnExtensionUnloaded(const std::string& extension_id);

  // Requests the extension which provided the certificate identified by
  // |subject_public_key_info| to sign the unhashed |input| with the
  // corresponding private key. |algorithm| is a TLS 1.3 SignatureScheme value.
  // See net::SSLPrivateKey for details. |callback| will be run with the reply
  // of the extension or an error.
  void RequestSignatureBySpki(
      const std::string& subject_public_key_info,
      uint16_t algorithm,
      base::span<const uint8_t> input,
      const std::optional<AccountId>& authenticating_user_account_id,
      net::SSLPrivateKey::SignCallback callback);

  // Looks up the certificate identified by |subject_public_key_info|. If any
  // extension is currently providing such a certificate, fills |extension_id|,
  // fills *|supported_algorithms| with the algorithms supported for that
  // certificate, and returns true. Values used for |supported_algorithms| are
  // TLS 1.3 SignatureSchemes. See net::SSLPrivateKey for details. If no
  // extension is currently providing such a certificate, returns false.
  bool LookUpSpki(const std::string& subject_public_key_info,
                  std::vector<uint16_t>* supported_algorithms,
                  std::string* extension_id);

  // Aborts all signature requests and related PIN dialogs that are associated
  // with the authentication of the given user.
  void AbortSignatureRequestsForAuthenticatingUser(
      const AccountId& authenticating_user_account_id);

  PinDialogManager* pin_dialog_manager() { return &pin_dialog_manager_; }

 private:
  class ClientCertIdentity;
  class CertificateProviderImpl;
  class SSLPrivateKey;

  // Requests the current list of certificates from every registered extension.
  // Once all extensions replied or a timeout was reached, the internal
  // |extension_to_certificates_| is updated and |callback| is run with the
  // retrieved list of certificates.
  void GetCertificatesFromExtensions(
      base::OnceCallback<void(net::ClientCertIdentityList)> callback);

  // Collects all currently available certificates and passes them to
  // |callback|.
  void CollectCertificatesAndRun(
      base::OnceCallback<void(net::ClientCertIdentityList)> callback);

  // Terminates the certificate request with id |cert_request_id| by ignoring
  // pending replies from extensions. Certificates that were already reported
  // are processed.
  void TerminateCertificateRequest(int cert_request_id);

  // Requests extension with |extension_id| to sign the unhashed |input| with
  // the private key certified by |certificate|. |algorithm| is a TLS 1.3
  // SignatureScheme value. See net::SSLPrivateKey for details. |callback| will
  // be run with the reply of the extension or an error.
  void RequestSignatureFromExtension(
      const std::string& extension_id,
      const scoped_refptr<net::X509Certificate>& certificate,
      uint16_t algorithm,
      base::span<const uint8_t> input,
      const std::optional<AccountId>& authenticating_user_account_id,
      net::SSLPrivateKey::SignCallback callback);

  std::unique_ptr<Delegate> delegate_;

  base::ObserverList<Observer> observers_;

  // The object to manage the dialog displayed when requestPin is called by the
  // extension.
  PinDialogManager pin_dialog_manager_;

  // State about all pending sign requests.
  certificate_provider::SignRequests sign_requests_;

  // Contains all pending certificate requests.
  certificate_provider::CertificateRequests certificate_requests_;

  // Contains all certificates that the extensions returned during the lifetime
  // of this service. Each certificate is associated with the extension that
  // reported the certificate in response to the most recent certificate
  // request. If a certificate was reported previously but in the most recent
  // responses, it is still cached but not loses it's association with any
  // extension. This ensures that a certificate can't magically appear as
  // platform certificate (e.g. in the client certificate selection dialog)
  // after an extension doesn't report it anymore.
  certificate_provider::ThreadSafeCertificateMap certificate_map_;

  SEQUENCE_CHECKER(sequence_checker_);
  base::WeakPtrFactory<CertificateProviderService> weak_factory_{this};
};

}  // namespace chromeos

#endif  // CHROME_BROWSER_CERTIFICATE_PROVIDER_CERTIFICATE_PROVIDER_SERVICE_H_