blob: 43f57e6c99e620b46853fffe9e1c4bda34a4f36f [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ASH_CERT_PROVISIONING_CERT_PROVISIONING_PLATFORM_KEYS_HELPERS_H_
#define CHROME_BROWSER_ASH_CERT_PROVISIONING_CERT_PROVISIONING_PLATFORM_KEYS_HELPERS_H_
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ash/cert_provisioning/cert_provisioning_common.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
// TODO(https://crbug.com/1164001): forward declare PlatformKeysService
// after //chrom/browser/chromeos/platform_keys is moved to ash.
#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h"
#include "net/cert/x509_certificate.h"
namespace ash {
namespace cert_provisioning {
// ========= CertIterator ======================================================
using CertIteratorForEachCallback =
base::RepeatingCallback<void(scoped_refptr<net::X509Certificate> cert,
const CertProfileId& cert_profile_id,
chromeos::platform_keys::Status status)>;
using CertIteratorOnFinishedCallback =
base::OnceCallback<void(chromeos::platform_keys::Status status)>;
// Iterates over all existing certificates of a given |cert_scope| and combines
// them with their certificate provisioning ids when possible. Runs |callback|
// on every (cert, cert_profile_id) pair that had a present and non-empty
// |cert_profile_id|. If |error_message| is not empty, then the pair is not
// valid.
class CertIterator {
public:
CertIterator(CertScope cert_scope,
platform_keys::PlatformKeysService* platform_keys_service);
CertIterator(const CertIterator&) = delete;
CertIterator& operator=(const CertIterator&) = delete;
~CertIterator();
// Can be called more than once. If previous iteration is not finished, it
// will be canceled.
void IterateAll(CertIteratorForEachCallback for_each_callback,
CertIteratorOnFinishedCallback on_finished_callback);
void Cancel();
private:
void OnGetCertificatesDone(
std::unique_ptr<net::CertificateList> existing_certs,
chromeos::platform_keys::Status status);
void OnGetAttributeForKeyDone(scoped_refptr<net::X509Certificate> cert,
const absl::optional<std::string>& attr_value,
chromeos::platform_keys::Status status);
void StopIteration(chromeos::platform_keys::Status status);
const CertScope cert_scope_ = CertScope::kDevice;
platform_keys::PlatformKeysService* const platform_keys_service_ = nullptr;
size_t wait_counter_ = 0;
CertIteratorForEachCallback for_each_callback_;
CertIteratorOnFinishedCallback on_finished_callback_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<CertIterator> weak_factory_{this};
};
// ========= LatestCertsWithIdsGetter ==========================================
using LatestCertsWithIdsGetterCallback = base::OnceCallback<void(
base::flat_map<CertProfileId, scoped_refptr<net::X509Certificate>>
certs_with_ids,
chromeos::platform_keys::Status status)>;
// Collects map of certificates with their certificate provisioning ids and
// returns it via |callback|. If there are several certificates for the same id,
// only the newest one will be stored in the map. Only one call to
// GetCertsWithIds() for one instance is allowed.
class LatestCertsWithIdsGetter {
public:
LatestCertsWithIdsGetter(
CertScope cert_scope,
platform_keys::PlatformKeysService* platform_keys_service);
LatestCertsWithIdsGetter(const LatestCertsWithIdsGetter&) = delete;
LatestCertsWithIdsGetter& operator=(const LatestCertsWithIdsGetter&) = delete;
~LatestCertsWithIdsGetter();
// Can be called more than once. If previous task is not finished, it will be
// canceled.
void GetCertsWithIds(LatestCertsWithIdsGetterCallback callback);
bool IsRunning() const;
void Cancel();
private:
void ProcessOneCert(scoped_refptr<net::X509Certificate> new_cert,
const CertProfileId& cert_profile_id,
chromeos::platform_keys::Status status);
void OnIterationFinished(chromeos::platform_keys::Status status);
CertIterator iterator_;
// Accumulates results that will be returned at the end via |callback_|.
base::flat_map<CertProfileId, scoped_refptr<net::X509Certificate>>
certs_with_ids_;
LatestCertsWithIdsGetterCallback callback_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<LatestCertsWithIdsGetter> weak_factory_{this};
};
// ========= CertDeleter =======================================================
using CertDeleterCallback =
base::OnceCallback<void(chromeos::platform_keys::Status status)>;
// Finds and deletes certificates that 1) have ids that are not in
// |cert_profile_ids_to_keep| set or 2) have another certificate for the same
// id with later expiration date. Only one call to DeleteCerts() for one
// instance is allowed.
class CertDeleter {
public:
CertDeleter(CertScope cert_scope,
platform_keys::PlatformKeysService* platform_keys_service);
CertDeleter(const CertDeleter&) = delete;
CertDeleter& operator=(const CertDeleter&) = delete;
~CertDeleter();
void Cancel();
// Can be called more than once. If previous task is not finished, it will be
// canceled.
void DeleteCerts(base::flat_set<CertProfileId> cert_profile_ids_to_keep,
CertDeleterCallback callback);
private:
void ProcessOneCert(scoped_refptr<net::X509Certificate> cert,
const CertProfileId& cert_profile_id,
chromeos::platform_keys::Status status);
void RememberOrDelete(scoped_refptr<net::X509Certificate> new_cert,
const CertProfileId& cert_profile_id);
void DeleteCert(scoped_refptr<net::X509Certificate> cert);
void OnDeleteCertDone(chromeos::platform_keys::Status status);
void OnIterationFinished(chromeos::platform_keys::Status status);
void CheckStateAndMaybeFinish();
void ReturnStatus(chromeos::platform_keys::Status status);
const CertScope cert_scope_ = CertScope::kDevice;
platform_keys::PlatformKeysService* const platform_keys_service_ = nullptr;
CertIterator iterator_;
bool iteration_finished_ = false;
size_t pending_delete_tasks_counter_ = 0;
CertDeleterCallback callback_;
// Contains list of currently existing certificate profile ids. Certificates
// with ids outside of this set can be deleted.
base::flat_set<CertProfileId> cert_profile_ids_to_keep_;
// Stores previously seen certificates that allows to find duplicates.
base::flat_map<CertProfileId, scoped_refptr<net::X509Certificate>>
certs_with_ids_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<CertDeleter> weak_factory_{this};
};
} // namespace cert_provisioning
} // namespace ash
#endif // CHROME_BROWSER_ASH_CERT_PROVISIONING_CERT_PROVISIONING_PLATFORM_KEYS_HELPERS_H_