blob: d456ecd3cf663a5be3a7d605dc5adcc708540197 [file] [log] [blame]
// 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.
#include "components/unexportable_keys/unexportable_key_tasks.h"
#include <memory>
#include <optional>
#include "base/memory/scoped_refptr.h"
#include "base/trace_event/typed_macros.h"
#include "base/types/expected.h"
#include "base/types/optional_util.h"
#include "components/unexportable_keys/background_task_type.h"
#include "components/unexportable_keys/ref_counted_unexportable_signing_key.h"
#include "components/unexportable_keys/service_error.h"
#include "crypto/signature_verifier.h"
#include "crypto/unexportable_key.h"
namespace unexportable_keys {
namespace {
ServiceErrorOr<scoped_refptr<RefCountedUnexportableSigningKey>>
MakeSigningKeyRefCounted(std::unique_ptr<crypto::UnexportableSigningKey> key) {
if (!key) {
return base::unexpected(ServiceError::kCryptoApiFailed);
}
return base::MakeRefCounted<RefCountedUnexportableSigningKey>(
std::move(key), UnexportableKeyId());
}
ServiceErrorOr<scoped_refptr<RefCountedUnexportableSigningKey>>
GenerateSigningKeySlowly(
crypto::UnexportableKeyProvider* key_provider,
base::span<const crypto::SignatureVerifier::SignatureAlgorithm>
acceptable_algorithms,
void* task_ptr_for_tracing) {
TRACE_EVENT("browser", "unexportable_keys::GenerateSigningKeySlowly",
perfetto::Flow::FromPointer(task_ptr_for_tracing));
CHECK(key_provider);
return MakeSigningKeyRefCounted(
key_provider->GenerateSigningKeySlowly(acceptable_algorithms));
}
ServiceErrorOr<scoped_refptr<RefCountedUnexportableSigningKey>>
FromWrappedSigningKeySlowly(crypto::UnexportableKeyProvider* key_provider,
base::span<const uint8_t> wrapped_key,
void* task_ptr_for_tracing) {
TRACE_EVENT("browser", "unexportable_keys::FromWrappedSigningKeySlowly",
perfetto::Flow::FromPointer(task_ptr_for_tracing));
CHECK(key_provider);
return MakeSigningKeyRefCounted(
key_provider->FromWrappedSigningKeySlowly(wrapped_key));
}
ServiceErrorOr<std::vector<uint8_t>> SignSlowlyWithRefCountedKey(
scoped_refptr<RefCountedUnexportableSigningKey> signing_key,
base::span<const uint8_t> data,
void* task_ptr_for_tracing) {
TRACE_EVENT("browser", "unexportable_keys::SignSlowlyWithRefCountedKey",
perfetto::Flow::FromPointer(task_ptr_for_tracing));
CHECK(signing_key);
return base::OptionalToExpected(signing_key->key().SignSlowly(data),
ServiceError::kCryptoApiFailed);
}
} // namespace
GenerateKeyTask::GenerateKeyTask(
std::unique_ptr<crypto::UnexportableKeyProvider> key_provider,
base::span<const crypto::SignatureVerifier::SignatureAlgorithm>
acceptable_algorithms,
BackgroundTaskPriority priority,
base::OnceCallback<void(GenerateKeyTask::ReturnType, size_t)> callback)
: internal::BackgroundTaskImpl<GenerateKeyTask::ReturnType>(
base::BindRepeating(
&GenerateSigningKeySlowly,
base::Owned(std::move(key_provider)),
std::vector<crypto::SignatureVerifier::SignatureAlgorithm>(
acceptable_algorithms.begin(),
acceptable_algorithms.end()),
this),
std::move(callback),
priority,
BackgroundTaskType::kGenerateKey,
/*max_retries=*/0) {}
FromWrappedKeyTask::FromWrappedKeyTask(
std::unique_ptr<crypto::UnexportableKeyProvider> key_provider,
base::span<const uint8_t> wrapped_key,
BackgroundTaskPriority priority,
base::OnceCallback<void(FromWrappedKeyTask::ReturnType, size_t)> callback)
: internal::BackgroundTaskImpl<FromWrappedKeyTask::ReturnType>(
base::BindRepeating(
&FromWrappedSigningKeySlowly,
base::Owned(std::move(key_provider)),
std::vector<uint8_t>(wrapped_key.begin(), wrapped_key.end()),
this),
std::move(callback),
priority,
BackgroundTaskType::kFromWrappedKey,
/*max_retries=*/0) {}
SignTask::SignTask(
scoped_refptr<RefCountedUnexportableSigningKey> signing_key,
base::span<const uint8_t> data,
BackgroundTaskPriority priority,
size_t max_retries,
base::OnceCallback<void(SignTask::ReturnType, size_t)> callback)
: internal::BackgroundTaskImpl<SignTask::ReturnType>(
base::BindRepeating(&SignSlowlyWithRefCountedKey,
std::move(signing_key),
std::vector<uint8_t>(data.begin(), data.end()),
this),
std::move(callback),
priority,
BackgroundTaskType::kSign,
max_retries) {}
bool SignTask::ShouldRetryBasedOnResult(
const ServiceErrorOr<std::vector<uint8_t>>& result) const {
return !result.has_value();
}
} // namespace unexportable_keys