// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_COMPONENTS_KCER_KCER_IMPL_H_
#define CHROMEOS_COMPONENTS_KCER_KCER_IMPL_H_
#include <stdint.h>
#include <deque>
#include <string>
#include <vector>
#include "base/callback_list.h"
#include "base/containers/flat_set.h"
#include "base/functional/callback_forward.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/task_runner.h"
#include "chromeos/components/kcer/kcer.h"
#include "chromeos/components/kcer/kcer_notifier_net.h"
#include "chromeos/components/kcer/kcer_token.h"
#include "net/cert/x509_certificate.h"
namespace kcer::internal {
// Implementation of the Kcer interface, exported for KcerFactory.
class COMPONENT_EXPORT(KCER) KcerImpl : public Kcer {
public:
KcerImpl();
~KcerImpl() override;
// Completes the initialization. The object is usable right after creation,
// but it will queue requests in the internal queue until it's initialized.
void Initialize(scoped_refptr<base::TaskRunner> token_task_runner,
base::WeakPtr<KcerToken> user_token,
base::WeakPtr<KcerToken> device_token);
base::WeakPtr<KcerImpl> GetWeakPtr();
// Implements Kcer.
base::CallbackListSubscription AddObserver(
base::RepeatingClosure callback) override;
void GenerateRsaKey(Token token,
RsaModulusLength modulus_length_bits,
bool hardware_backed,
GenerateKeyCallback callback) override;
void GenerateEcKey(Token token,
EllipticCurve curve,
bool hardware_backed,
GenerateKeyCallback callback) override;
void ImportKey(Token token,
Pkcs8PrivateKeyInfoDer pkcs8_private_key_info_der,
ImportKeyCallback callback) override;
void ImportCertFromBytes(Token token,
CertDer cert_der,
StatusCallback callback) override;
void ImportX509Cert(Token token,
scoped_refptr<net::X509Certificate> cert,
StatusCallback callback) override;
void ImportPkcs12Cert(Token token,
Pkcs12Blob pkcs12_blob,
std::string password,
bool hardware_backed,
bool mark_as_migrated,
StatusCallback callback) override;
void ExportPkcs12Cert(scoped_refptr<const Cert> cert,
ExportPkcs12Callback callback) override;
void RemoveKeyAndCerts(PrivateKeyHandle key,
StatusCallback callback) override;
void RemoveCert(scoped_refptr<const Cert> cert,
StatusCallback callback) override;
void ListKeys(base::flat_set<Token> tokens,
ListKeysCallback callback) override;
void ListCerts(base::flat_set<Token> tokens,
ListCertsCallback callback) override;
void DoesPrivateKeyExist(PrivateKeyHandle key,
DoesKeyExistCallback callback) override;
void Sign(PrivateKeyHandle key,
SigningScheme signing_scheme,
DataToSign data,
SignCallback callback) override;
void SignRsaPkcs1Raw(PrivateKeyHandle key,
DigestWithPrefix digest_with_prefix,
SignCallback callback) override;
void GetAvailableTokens(GetAvailableTokensCallback callback) override;
void GetTokenInfo(Token token, GetTokenInfoCallback callback) override;
void GetKeyInfo(PrivateKeyHandle key, GetKeyInfoCallback callback) override;
void GetKeyPermissions(PrivateKeyHandle key,
GetKeyPermissionsCallback callback) override;
void GetCertProvisioningProfileId(
PrivateKeyHandle key,
GetCertProvisioningProfileIdCallback callback) override;
void SetKeyNickname(PrivateKeyHandle key,
std::string nickname,
StatusCallback callback) override;
void SetKeyPermissions(PrivateKeyHandle key,
chaps::KeyPermissions key_permissions,
StatusCallback callback) override;
void SetCertProvisioningProfileId(PrivateKeyHandle key,
std::string profile_id,
StatusCallback callback) override;
private:
base::WeakPtr<KcerToken>& GetToken(Token token);
// Finds the token where the `key` is stored. If `allow_guessing` is true, it
// can return a token where the key *might* be (and no other token can
// possibly have it), this is good enough for most methods that would just
// fail if the key is not on the returned token either. If `allow_guessing` is
// false, the result is precise and reliable. Returns a token on success, an
// nullopt if the key was not found, an error on failure.
void FindKeyToken(
bool allow_guessing,
PrivateKeyHandle key,
base::OnceCallback<void(base::expected<std::optional<Token>, Error>)>
callback);
// Attempts to find the token for the `key` (guessing is allowed). Returns a
// PrivateKeyHandle with the token populated on success, an error on failure.
void PopulateTokenForKey(
PrivateKeyHandle key,
base::OnceCallback<void(base::expected<PrivateKeyHandle, Error>)>
callback);
void PopulateTokenForKeyWithToken(
PrivateKeyHandle key,
base::OnceCallback<void(base::expected<PrivateKeyHandle, Error>)>
callback,
base::expected<std::optional<Token>, Error> find_key_result);
void RemoveKeyAndCertsWithToken(
StatusCallback callback,
base::expected<PrivateKeyHandle, Error> key_or_error);
void DoesPrivateKeyExistWithToken(
DoesKeyExistCallback callback,
base::expected<std::optional<Token>, Error> find_key_result);
void SignWithToken(SigningScheme signing_scheme,
DataToSign data,
SignCallback callback,
base::expected<PrivateKeyHandle, Error> key_or_error);
void SignRsaPkcs1RawWithToken(
DigestWithPrefix digest_with_prefix,
SignCallback callback,
base::expected<PrivateKeyHandle, Error> key_or_error);
base::flat_set<Token> GetCurrentTokens() const;
void GetKeyInfoWithToken(
GetKeyInfoCallback callback,
base::expected<PrivateKeyHandle, Error> key_or_error);
void GetKeyPermissionsWithToken(
GetKeyPermissionsCallback callback,
base::expected<PrivateKeyHandle, Error> key_or_error);
void GetCertProvisioningProfileIdWithToken(
GetCertProvisioningProfileIdCallback callback,
base::expected<PrivateKeyHandle, Error> key_or_error);
void SetKeyNicknameWithToken(
std::string nickname,
StatusCallback callback,
base::expected<PrivateKeyHandle, Error> key_or_error);
void SetKeyPermissionsWithToken(
chaps::KeyPermissions key_permissions,
StatusCallback callback,
base::expected<PrivateKeyHandle, Error> key_or_error);
void SetCertProvisioningProfileIdWithToken(
std::string profile_id,
StatusCallback callback,
base::expected<PrivateKeyHandle, Error> key_or_error);
// Task runner for the tokens. Can be nullptr if no tokens are available
// to the current Kcer instance.
scoped_refptr<base::TaskRunner> token_task_runner_;
// Pointers to kcer tokens. Can contain nullptr-s if a token is not available
// to the current instance of Kcer. All requests to the tokens must be posted
// on the `token_task_runner_`. The pointers themself also belong to the
// `token_task_runner_`'s sequence and can only be used within KcerImpl in a
// very limited way (consult documentation for WeakPtr for details).
base::WeakPtr<KcerToken> user_token_;
base::WeakPtr<KcerToken> device_token_;
KcerNotifierNet notifier_;
// A task queue for the initialization period until the tokens are assigned.
std::unique_ptr<std::deque<base::OnceClosure>> init_queue_;
base::WeakPtrFactory<KcerImpl> weak_factory_{this};
};
} // namespace kcer::internal
#endif // CHROMEOS_COMPONENTS_KCER_KCER_IMPL_H_