|  | // 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 |