[go: nahoru, domu]

blob: b5fd3a124198dca12de4504197b1283a75356691 [file] [log] [blame]
Alex Ilin933326f02023-05-15 10:26:431// Copyright 2023 The Chromium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/unexportable_keys/unexportable_key_loader.h"
6
7#include "base/check.h"
8#include "base/test/bind.h"
9#include "base/test/task_environment.h"
10#include "base/test/test_future.h"
11#include "components/unexportable_keys/background_task_priority.h"
12#include "components/unexportable_keys/service_error.h"
13#include "components/unexportable_keys/unexportable_key_service_impl.h"
14#include "components/unexportable_keys/unexportable_key_task_manager.h"
15#include "crypto/scoped_mock_unexportable_key_provider.h"
16#include "crypto/signature_verifier.h"
17#include "testing/gtest/include/gtest/gtest.h"
18
19namespace unexportable_keys {
20
21namespace {
22
23constexpr crypto::SignatureVerifier::SignatureAlgorithm
24 kAcceptableAlgorithms[] = {crypto::SignatureVerifier::ECDSA_SHA256};
25constexpr BackgroundTaskPriority kTaskPriority =
26 BackgroundTaskPriority::kUserVisible;
27
28} // namespace
29
30class UnexportableKeyLoaderTest : public testing::Test {
31 public:
32 UnexportableKeyLoaderTest()
33 : task_manager_(std::make_unique<UnexportableKeyTaskManager>()),
34 service_(std::make_unique<UnexportableKeyServiceImpl>(*task_manager_)) {
35 }
36
37 UnexportableKeyServiceImpl& service() { return *service_; }
38
39 void RunBackgroundTasks() { task_environment_.RunUntilIdle(); }
40
41 void ResetService() {
42 task_manager_ = std::make_unique<UnexportableKeyTaskManager>();
43 service_ = std::make_unique<UnexportableKeyServiceImpl>(*task_manager_);
44 }
45
46 void DisableKeyProvider() {
47 // Using `emplace()` to destroy the existing scoped object before
48 // constructing a new one.
49 scoped_key_provider_.emplace<crypto::ScopedNullUnexportableKeyProvider>();
50 }
51
52 std::vector<uint8_t> GenerateNewKeyAndReturnWrappedKey() {
53 base::test::TestFuture<ServiceErrorOr<UnexportableKeyId>> generate_future;
54 service().GenerateSigningKeySlowlyAsync(
55 kAcceptableAlgorithms, kTaskPriority, generate_future.GetCallback());
56 RunBackgroundTasks();
57 ServiceErrorOr<UnexportableKeyId> key_id = generate_future.Get();
58 CHECK(key_id.has_value());
59
60 ServiceErrorOr<std::vector<uint8_t>> wrapped_key =
61 service().GetWrappedKey(*key_id);
62 CHECK(wrapped_key.has_value());
63 return *wrapped_key;
64 }
65
66 private:
67 base::test::TaskEnvironment task_environment_{
68 base::test::TaskEnvironment::ThreadPoolExecutionMode::
69 QUEUED}; // QUEUED - tasks don't run until `RunUntilIdle()` is
70 // called.
71 // Provides a mock key provider by default.
72 absl::variant<crypto::ScopedMockUnexportableKeyProvider,
73 crypto::ScopedNullUnexportableKeyProvider>
74 scoped_key_provider_;
75 std::unique_ptr<UnexportableKeyTaskManager> task_manager_;
76 std::unique_ptr<UnexportableKeyServiceImpl> service_;
77};
78
79TEST_F(UnexportableKeyLoaderTest, CreateFromWrappedKeySync) {
80 std::vector<uint8_t> wrapped_key = GenerateNewKeyAndReturnWrappedKey();
81
82 // `wrapped_key` is already registered in the service. The loader should
83 // return a key immediately.
84 auto key_loader = UnexportableKeyLoader::CreateFromWrappedKey(
85 service(), wrapped_key, kTaskPriority);
86 EXPECT_EQ(key_loader->GetStateForTesting(),
87 UnexportableKeyLoader::State::kReady);
88 EXPECT_TRUE(key_loader->GetKeyIdOrErrorForTesting().has_value());
89
90 base::test::TestFuture<ServiceErrorOr<UnexportableKeyId>> on_load_future;
91 key_loader->InvokeCallbackAfterKeyLoaded(on_load_future.GetCallback());
92 EXPECT_TRUE(on_load_future.IsReady());
93 EXPECT_EQ(key_loader->GetKeyIdOrErrorForTesting(), on_load_future.Get());
94}
95
96TEST_F(UnexportableKeyLoaderTest, CreateFromWrappedKeyAsync) {
97 std::vector<uint8_t> wrapped_key = GenerateNewKeyAndReturnWrappedKey();
98 // A new key is still registered inside the service. Reset the service to
99 // remove the key.
100 ResetService();
101
102 auto key_loader = UnexportableKeyLoader::CreateFromWrappedKey(
103 service(), wrapped_key, kTaskPriority);
104 EXPECT_EQ(key_loader->GetStateForTesting(),
105 UnexportableKeyLoader::State::kLoading);
106 EXPECT_EQ(key_loader->GetKeyIdOrErrorForTesting(),
107 base::unexpected(ServiceError::kKeyNotReady));
108
109 base::test::TestFuture<ServiceErrorOr<UnexportableKeyId>> on_load_future;
110 key_loader->InvokeCallbackAfterKeyLoaded(on_load_future.GetCallback());
111 EXPECT_FALSE(on_load_future.IsReady());
112
113 RunBackgroundTasks();
114 EXPECT_EQ(key_loader->GetStateForTesting(),
115 UnexportableKeyLoader::State::kReady);
116 EXPECT_TRUE(key_loader->GetKeyIdOrErrorForTesting().has_value());
117 EXPECT_TRUE(on_load_future.IsReady());
118 EXPECT_EQ(key_loader->GetKeyIdOrErrorForTesting(), on_load_future.Get());
119}
120
121TEST_F(UnexportableKeyLoaderTest, CreateFromWrappedKeyMultipleCallbacks) {
122 std::vector<uint8_t> wrapped_key = GenerateNewKeyAndReturnWrappedKey();
123 // A new key is still registered inside the service. Reset the service to
124 // remove the key.
125 ResetService();
126
127 auto key_loader = UnexportableKeyLoader::CreateFromWrappedKey(
128 service(), wrapped_key, kTaskPriority);
129
130 std::array<base::test::TestFuture<ServiceErrorOr<UnexportableKeyId>>, 5>
131 on_load_futures;
132 for (auto& future : on_load_futures) {
133 key_loader->InvokeCallbackAfterKeyLoaded(future.GetCallback());
134 EXPECT_FALSE(future.IsReady());
135 }
136
137 RunBackgroundTasks();
138 EXPECT_EQ(key_loader->GetStateForTesting(),
139 UnexportableKeyLoader::State::kReady);
140 EXPECT_TRUE(key_loader->GetKeyIdOrErrorForTesting().has_value());
141 for (auto& future : on_load_futures) {
142 EXPECT_TRUE(future.IsReady());
143 EXPECT_EQ(key_loader->GetKeyIdOrErrorForTesting(), future.Get());
144 }
145}
146
147TEST_F(UnexportableKeyLoaderTest, CreateWithNewKey) {
148 auto key_loader = UnexportableKeyLoader::CreateWithNewKey(
149 service(), kAcceptableAlgorithms, kTaskPriority);
150 EXPECT_EQ(key_loader->GetStateForTesting(),
151 UnexportableKeyLoader::State::kLoading);
152 EXPECT_EQ(key_loader->GetKeyIdOrErrorForTesting(),
153 base::unexpected(ServiceError::kKeyNotReady));
154
155 base::test::TestFuture<ServiceErrorOr<UnexportableKeyId>> on_load_future;
156 key_loader->InvokeCallbackAfterKeyLoaded(on_load_future.GetCallback());
157 EXPECT_FALSE(on_load_future.IsReady());
158
159 RunBackgroundTasks();
160 EXPECT_EQ(key_loader->GetStateForTesting(),
161 UnexportableKeyLoader::State::kReady);
162 EXPECT_TRUE(key_loader->GetKeyIdOrErrorForTesting().has_value());
163 EXPECT_TRUE(on_load_future.IsReady());
164 EXPECT_EQ(key_loader->GetKeyIdOrErrorForTesting(), on_load_future.Get());
165}
166
167TEST_F(UnexportableKeyLoaderTest, CreateWithNewKeyFailure) {
168 DisableKeyProvider();
169 auto key_loader = UnexportableKeyLoader::CreateWithNewKey(
170 service(), kAcceptableAlgorithms, kTaskPriority);
171 EXPECT_EQ(key_loader->GetStateForTesting(),
172 UnexportableKeyLoader::State::kReady);
173 EXPECT_EQ(key_loader->GetKeyIdOrErrorForTesting(),
174 base::unexpected(ServiceError::kNoKeyProvider));
175}
176
177TEST_F(UnexportableKeyLoaderTest, SignDataAfterLoading) {
178 auto key_loader = UnexportableKeyLoader::CreateWithNewKey(
179 service(), kAcceptableAlgorithms, kTaskPriority);
180
181 base::test::TestFuture<ServiceErrorOr<std::vector<uint8_t>>> sign_future;
182 key_loader->InvokeCallbackAfterKeyLoaded(base::BindLambdaForTesting(
183 [&](ServiceErrorOr<UnexportableKeyId> key_id_or_error) {
184 ASSERT_TRUE(key_id_or_error.has_value());
185 service().SignSlowlyAsync(*key_id_or_error,
186 std::vector<uint8_t>({1, 2, 3}),
187 kTaskPriority, sign_future.GetCallback());
188 }));
189 EXPECT_FALSE(sign_future.IsReady());
190 RunBackgroundTasks();
191 EXPECT_TRUE(sign_future.IsReady());
192 EXPECT_TRUE(sign_future.Get().has_value());
193}
194
195} // namespace unexportable_keys