1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16
17 #include "tink/internal/configuration_impl.h"
18
19 #include <memory>
20 #include <string>
21
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "absl/status/status.h"
25 #include "tink/cleartext_keyset_handle.h"
26 #include "tink/configuration.h"
27 #include "tink/internal/keyset_wrapper_store.h"
28 #include "tink/subtle/random.h"
29 #include "tink/util/test_matchers.h"
30 #include "tink/util/test_util.h"
31 #include "proto/aes_gcm.pb.h"
32 #include "proto/rsa_ssa_pss.pb.h"
33
34 namespace crypto {
35 namespace tink {
36 namespace internal {
37 namespace {
38
39 using ::crypto::tink::test::IsOk;
40 using ::crypto::tink::test::StatusIs;
41 using ::google::crypto::tink::AesGcmKey;
42 using ::google::crypto::tink::AesGcmKeyFormat;
43 using ::google::crypto::tink::KeyData;
44 using ::google::crypto::tink::Keyset;
45 using ::google::crypto::tink::KeyStatusType;
46 using ::google::crypto::tink::OutputPrefixType;
47 using ::google::crypto::tink::RsaSsaPssKeyFormat;
48 using ::google::crypto::tink::RsaSsaPssParams;
49 using ::google::crypto::tink::RsaSsaPssPrivateKey;
50 using ::google::crypto::tink::RsaSsaPssPublicKey;
51
52 class FakePrimitive {
53 public:
FakePrimitive(std::string s)54 explicit FakePrimitive(std::string s) : s_(s) {}
get()55 std::string get() { return s_; }
56
57 private:
58 std::string s_;
59 };
60
61 class FakePrimitive2 {
62 public:
FakePrimitive2(std::string s)63 explicit FakePrimitive2(std::string s) : s_(s) {}
get()64 std::string get() { return s_ + "2"; }
65
66 private:
67 std::string s_;
68 };
69
70 // Transforms AesGcmKey into FakePrimitive.
71 class FakeKeyTypeManager
72 : public KeyTypeManager<AesGcmKey, AesGcmKeyFormat, List<FakePrimitive>> {
73 public:
74 class FakePrimitiveFactory : public PrimitiveFactory<FakePrimitive> {
75 public:
Create(const AesGcmKey & key) const76 util::StatusOr<std::unique_ptr<FakePrimitive>> Create(
77 const AesGcmKey& key) const override {
78 return absl::make_unique<FakePrimitive>(key.key_value());
79 }
80 };
81
FakeKeyTypeManager()82 FakeKeyTypeManager()
83 : KeyTypeManager(absl::make_unique<FakePrimitiveFactory>()) {}
84
key_material_type() const85 KeyData::KeyMaterialType key_material_type() const override {
86 return KeyData::SYMMETRIC;
87 }
88
get_version() const89 uint32_t get_version() const override { return 0; }
90
get_key_type() const91 const std::string& get_key_type() const override { return key_type_; }
92
ValidateKey(const AesGcmKey & key) const93 util::Status ValidateKey(const AesGcmKey& key) const override {
94 return util::OkStatus();
95 }
96
ValidateKeyFormat(const AesGcmKeyFormat & key_format) const97 util::Status ValidateKeyFormat(
98 const AesGcmKeyFormat& key_format) const override {
99 return util::OkStatus();
100 }
101
CreateKey(const AesGcmKeyFormat & key_format) const102 util::StatusOr<AesGcmKey> CreateKey(
103 const AesGcmKeyFormat& key_format) const override {
104 return AesGcmKey();
105 }
106
DeriveKey(const AesGcmKeyFormat & key_format,InputStream * input_stream) const107 util::StatusOr<AesGcmKey> DeriveKey(
108 const AesGcmKeyFormat& key_format,
109 InputStream* input_stream) const override {
110 return AesGcmKey();
111 }
112
113 private:
114 const std::string key_type_ =
115 "type.googleapis.com/google.crypto.tink.AesGcmKey";
116 };
117
118 // Transforms FakePrimitive into FakePrimitive.
119 class FakePrimitiveWrapper
120 : public PrimitiveWrapper<FakePrimitive, FakePrimitive> {
121 public:
Wrap(std::unique_ptr<PrimitiveSet<FakePrimitive>> primitive_set) const122 util::StatusOr<std::unique_ptr<FakePrimitive>> Wrap(
123 std::unique_ptr<PrimitiveSet<FakePrimitive>> primitive_set)
124 const override {
125 return absl::make_unique<FakePrimitive>(
126 primitive_set->get_primary()->get_primitive().get());
127 }
128 };
129
130 // Transforms FakePrimitive2 into FakePrimitive.
131 class FakePrimitiveWrapper2
132 : public PrimitiveWrapper<FakePrimitive2, FakePrimitive> {
133 public:
Wrap(std::unique_ptr<PrimitiveSet<FakePrimitive2>> primitive_set) const134 util::StatusOr<std::unique_ptr<FakePrimitive>> Wrap(
135 std::unique_ptr<PrimitiveSet<FakePrimitive2>> primitive_set)
136 const override {
137 return absl::make_unique<FakePrimitive>(
138 primitive_set->get_primary()->get_primitive().get());
139 }
140 };
141
AddAesGcmKeyToKeyset(Keyset & keyset,uint32_t key_id,OutputPrefixType output_prefix_type,KeyStatusType key_status_type)142 std::string AddAesGcmKeyToKeyset(Keyset& keyset, uint32_t key_id,
143 OutputPrefixType output_prefix_type,
144 KeyStatusType key_status_type) {
145 AesGcmKey key;
146 key.set_version(0);
147 key.set_key_value(subtle::Random::GetRandomBytes(16));
148 KeyData key_data;
149 key_data.set_value(key.SerializeAsString());
150 key_data.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey");
151 test::AddKeyData(key_data, key_id, output_prefix_type, key_status_type,
152 &keyset);
153 return key.key_value();
154 }
155
TEST(ConfigurationImplTest,AddPrimitiveWrapper)156 TEST(ConfigurationImplTest, AddPrimitiveWrapper) {
157 Configuration config;
158 EXPECT_THAT((ConfigurationImpl::AddPrimitiveWrapper(
159 absl::make_unique<FakePrimitiveWrapper>(), config)),
160 IsOk());
161 }
162
TEST(ConfigurationImplTest,AddKeyTypeManager)163 TEST(ConfigurationImplTest, AddKeyTypeManager) {
164 Configuration config;
165 EXPECT_THAT(ConfigurationImpl::AddKeyTypeManager(
166 absl::make_unique<FakeKeyTypeManager>(), config),
167 IsOk());
168 }
169
TEST(ConfigurationImplTest,GetKeyTypeInfoStore)170 TEST(ConfigurationImplTest, GetKeyTypeInfoStore) {
171 Configuration config;
172 ASSERT_THAT(ConfigurationImpl::AddKeyTypeManager(
173 absl::make_unique<FakeKeyTypeManager>(), config),
174 IsOk());
175
176 std::string type_url = FakeKeyTypeManager().get_key_type();
177 util::StatusOr<const KeyTypeInfoStore*> store =
178 ConfigurationImpl::GetKeyTypeInfoStore(config);
179 ASSERT_THAT(store, IsOk());
180 util::StatusOr<const KeyTypeInfoStore::Info*> info = (*store)->Get(type_url);
181 ASSERT_THAT(info, IsOk());
182
183 util::StatusOr<const KeyManager<FakePrimitive>*> key_manager =
184 (*info)->get_key_manager<FakePrimitive>(type_url);
185 ASSERT_THAT(key_manager, IsOk());
186 EXPECT_EQ((*key_manager)->get_key_type(), type_url);
187 }
188
TEST(ConfigurationImplTest,GetKeyTypeInfoStoreMissingInfoFails)189 TEST(ConfigurationImplTest, GetKeyTypeInfoStoreMissingInfoFails) {
190 Configuration config;
191 util::StatusOr<const KeyTypeInfoStore*> store =
192 ConfigurationImpl::GetKeyTypeInfoStore(config);
193 ASSERT_THAT(store, IsOk());
194 EXPECT_THAT((*store)->Get("i.do.not.exist").status(),
195 StatusIs(absl::StatusCode::kNotFound));
196 }
197
TEST(ConfigurationImplTest,GetKeysetWrapperStoreAndWrap)198 TEST(ConfigurationImplTest, GetKeysetWrapperStoreAndWrap) {
199 Configuration config;
200 ASSERT_THAT((ConfigurationImpl::AddPrimitiveWrapper(
201 absl::make_unique<FakePrimitiveWrapper>(), config)),
202 IsOk());
203 ASSERT_THAT(ConfigurationImpl::AddKeyTypeManager(
204 absl::make_unique<FakeKeyTypeManager>(), config),
205 IsOk());
206
207 util::StatusOr<const KeysetWrapperStore*> store =
208 ConfigurationImpl::GetKeysetWrapperStore(config);
209 ASSERT_THAT(store, IsOk());
210 util::StatusOr<const KeysetWrapper<FakePrimitive>*> wrapper =
211 (*store)->Get<FakePrimitive>();
212 ASSERT_THAT(wrapper, IsOk());
213
214 Keyset keyset;
215 std::string raw_key = AddAesGcmKeyToKeyset(
216 keyset, /*key_id=*/13, OutputPrefixType::TINK, KeyStatusType::ENABLED);
217 keyset.set_primary_key_id(13);
218
219 util::StatusOr<std::unique_ptr<FakePrimitive>> aead =
220 (*wrapper)->Wrap(keyset, /*annotations=*/{});
221 ASSERT_THAT(aead, IsOk());
222 EXPECT_EQ((*aead)->get(), raw_key);
223 }
224
TEST(ConfigurationImplTest,KeysetWrapperWrapMissingKeyTypeInfoFails)225 TEST(ConfigurationImplTest, KeysetWrapperWrapMissingKeyTypeInfoFails) {
226 Configuration config;
227 ASSERT_THAT(ConfigurationImpl::AddPrimitiveWrapper(
228 absl::make_unique<FakePrimitiveWrapper>(), config),
229 IsOk());
230
231 util::StatusOr<const KeysetWrapperStore*> store =
232 ConfigurationImpl::GetKeysetWrapperStore(config);
233 ASSERT_THAT(store, IsOk());
234 util::StatusOr<const KeysetWrapper<FakePrimitive>*> wrapper =
235 (*store)->Get<FakePrimitive>();
236 ASSERT_THAT(wrapper, IsOk());
237
238 Keyset keyset;
239 std::string raw_key = AddAesGcmKeyToKeyset(
240 keyset, /*key_id=*/13, OutputPrefixType::TINK, KeyStatusType::ENABLED);
241 keyset.set_primary_key_id(13);
242
243 EXPECT_THAT((*wrapper)->Wrap(keyset, /*annotations=*/{}).status(),
244 StatusIs(absl::StatusCode::kNotFound));
245 }
246
TEST(ConfigurationImplTest,KeysetWrapperWrapMissingKeyManagerFails)247 TEST(ConfigurationImplTest, KeysetWrapperWrapMissingKeyManagerFails) {
248 Configuration config;
249 // Transforms FakePrimitive2 to FakePrimitive.
250 ASSERT_THAT((ConfigurationImpl::AddPrimitiveWrapper(
251 absl::make_unique<FakePrimitiveWrapper2>(), config)),
252 IsOk());
253 // Transforms KeyData to FakePrimitive.
254 ASSERT_THAT(ConfigurationImpl::AddKeyTypeManager(
255 absl::make_unique<FakeKeyTypeManager>(), config),
256 IsOk());
257
258 // AesGcmKey KeyData -> FakePrimitive2 -> FakePrimitive is the success path,
259 // but the AesGcmKey KeyData -> FakePrimitive2 transformation is not
260 // registered.
261 util::StatusOr<const KeysetWrapperStore*> store =
262 ConfigurationImpl::GetKeysetWrapperStore(config);
263 ASSERT_THAT(store, IsOk());
264 util::StatusOr<const KeysetWrapper<FakePrimitive>*> wrapper =
265 (*store)->Get<FakePrimitive>();
266 ASSERT_THAT(wrapper, IsOk());
267
268 Keyset keyset;
269 std::string raw_key = AddAesGcmKeyToKeyset(
270 keyset, /*key_id=*/13, OutputPrefixType::TINK, KeyStatusType::ENABLED);
271 keyset.set_primary_key_id(13);
272
273 // FakeKeyTypeManager cannot transform AesGcmKey KeyData -> FakePrimitive2.
274 EXPECT_THAT((*wrapper)->Wrap(keyset, /*annotations=*/{}).status(),
275 StatusIs(absl::StatusCode::kInvalidArgument));
276 }
277
278 class FakeSignKeyManager
279 : public PrivateKeyTypeManager<RsaSsaPssPrivateKey, RsaSsaPssKeyFormat,
280 RsaSsaPssPublicKey, List<PublicKeySign>> {
281 public:
282 class PublicKeySignFactory : public PrimitiveFactory<PublicKeySign> {
283 public:
Create(const RsaSsaPssPrivateKey & key) const284 util::StatusOr<std::unique_ptr<PublicKeySign>> Create(
285 const RsaSsaPssPrivateKey& key) const override {
286 return {absl::make_unique<test::DummyPublicKeySign>("a public key sign")};
287 }
288 };
289
FakeSignKeyManager()290 explicit FakeSignKeyManager()
291 : PrivateKeyTypeManager(absl::make_unique<PublicKeySignFactory>()) {}
292
key_material_type() const293 KeyData::KeyMaterialType key_material_type() const override {
294 return KeyData::ASYMMETRIC_PRIVATE;
295 }
296
get_version() const297 uint32_t get_version() const override { return 0; }
298
get_key_type() const299 const std::string& get_key_type() const override { return key_type_; }
300
ValidateKey(const RsaSsaPssPrivateKey & key) const301 util::Status ValidateKey(const RsaSsaPssPrivateKey& key) const override {
302 return util::OkStatus();
303 }
304
ValidateKeyFormat(const RsaSsaPssKeyFormat & key_format) const305 util::Status ValidateKeyFormat(
306 const RsaSsaPssKeyFormat& key_format) const override {
307 return util::OkStatus();
308 }
309
CreateKey(const RsaSsaPssKeyFormat & key_format) const310 util::StatusOr<RsaSsaPssPrivateKey> CreateKey(
311 const RsaSsaPssKeyFormat& key_format) const override {
312 return RsaSsaPssPrivateKey();
313 }
314
DeriveKey(const RsaSsaPssKeyFormat & key_format,InputStream * input_stream) const315 util::StatusOr<RsaSsaPssPrivateKey> DeriveKey(
316 const RsaSsaPssKeyFormat& key_format,
317 InputStream* input_stream) const override {
318 return RsaSsaPssPrivateKey();
319 }
320
GetPublicKey(const RsaSsaPssPrivateKey & private_key) const321 util::StatusOr<RsaSsaPssPublicKey> GetPublicKey(
322 const RsaSsaPssPrivateKey& private_key) const override {
323 return private_key.public_key();
324 }
325
326 private:
327 const std::string key_type_ = "some.sign.key.type";
328 };
329
330 class FakeVerifyKeyManager
331 : public KeyTypeManager<RsaSsaPssPublicKey, void, List<PublicKeyVerify>> {
332 public:
333 class PublicKeyVerifyFactory : public PrimitiveFactory<PublicKeyVerify> {
334 public:
Create(const RsaSsaPssPublicKey & key) const335 util::StatusOr<std::unique_ptr<PublicKeyVerify>> Create(
336 const RsaSsaPssPublicKey& key) const override {
337 return {
338 absl::make_unique<test::DummyPublicKeyVerify>("a public key verify")};
339 }
340 };
341
FakeVerifyKeyManager()342 explicit FakeVerifyKeyManager()
343 : KeyTypeManager(absl::make_unique<PublicKeyVerifyFactory>()) {}
344
key_material_type() const345 KeyData::KeyMaterialType key_material_type() const override {
346 return KeyData::ASYMMETRIC_PUBLIC;
347 }
348
get_version() const349 uint32_t get_version() const override { return 0; }
350
get_key_type() const351 const std::string& get_key_type() const override { return key_type_; }
352
ValidateKey(const RsaSsaPssPublicKey & key) const353 util::Status ValidateKey(const RsaSsaPssPublicKey& key) const override {
354 return util::OkStatus();
355 }
356
ValidateParams(const RsaSsaPssParams & params) const357 util::Status ValidateParams(const RsaSsaPssParams& params) const {
358 return util::OkStatus();
359 }
360
361 private:
362 const std::string key_type_ = "some.verify.key.type";
363 };
364
TEST(ConfigurationImplTest,AddAsymmetricKeyManagers)365 TEST(ConfigurationImplTest, AddAsymmetricKeyManagers) {
366 Configuration config;
367 EXPECT_THAT(ConfigurationImpl::AddAsymmetricKeyManagers(
368 absl::make_unique<FakeSignKeyManager>(),
369 absl::make_unique<FakeVerifyKeyManager>(), config),
370 IsOk());
371 }
372
TEST(ConfigurationImplTest,GetKeyTypeInfoStoreAsymmetric)373 TEST(ConfigurationImplTest, GetKeyTypeInfoStoreAsymmetric) {
374 Configuration config;
375 ASSERT_THAT(ConfigurationImpl::AddAsymmetricKeyManagers(
376 absl::make_unique<FakeSignKeyManager>(),
377 absl::make_unique<FakeVerifyKeyManager>(), config),
378 IsOk());
379
380 {
381 std::string type_url = FakeSignKeyManager().get_key_type();
382 util::StatusOr<const KeyTypeInfoStore*> store =
383 ConfigurationImpl::GetKeyTypeInfoStore(config);
384 ASSERT_THAT(store, IsOk());
385 util::StatusOr<const KeyTypeInfoStore::Info*> info =
386 (*store)->Get(type_url);
387 ASSERT_THAT(info, IsOk());
388
389 util::StatusOr<const KeyManager<PublicKeySign>*> key_manager =
390 (*info)->get_key_manager<PublicKeySign>(type_url);
391 ASSERT_THAT(key_manager, IsOk());
392 EXPECT_EQ((*key_manager)->get_key_type(), type_url);
393 }
394 {
395 std::string type_url = FakeVerifyKeyManager().get_key_type();
396 util::StatusOr<const KeyTypeInfoStore*> store =
397 ConfigurationImpl::GetKeyTypeInfoStore(config);
398 ASSERT_THAT(store, IsOk());
399 util::StatusOr<const KeyTypeInfoStore::Info*> info =
400 (*store)->Get(type_url);
401 ASSERT_THAT(info, IsOk());
402
403 util::StatusOr<const KeyManager<PublicKeyVerify>*> key_manager =
404 (*info)->get_key_manager<PublicKeyVerify>(type_url);
405 ASSERT_THAT(key_manager, IsOk());
406 EXPECT_EQ((*key_manager)->get_key_type(), type_url);
407 }
408 }
409
TEST(ConfigurationImplTest,GlobalRegistryMode)410 TEST(ConfigurationImplTest, GlobalRegistryMode) {
411 Registry::Reset();
412 Configuration config;
413 ASSERT_THAT(ConfigurationImpl::SetGlobalRegistryMode(config), IsOk());
414 EXPECT_TRUE(ConfigurationImpl::IsInGlobalRegistryMode(config));
415
416 // Check that ConfigurationImpl functions return kFailedPrecondition.
417 EXPECT_THAT(ConfigurationImpl::AddPrimitiveWrapper(
418 absl::make_unique<FakePrimitiveWrapper>(), config),
419 StatusIs(absl::StatusCode::kFailedPrecondition));
420 EXPECT_THAT(ConfigurationImpl::AddKeyTypeManager(
421 absl::make_unique<FakeKeyTypeManager>(), config),
422 StatusIs(absl::StatusCode::kFailedPrecondition));
423 EXPECT_THAT(ConfigurationImpl::AddAsymmetricKeyManagers(
424 absl::make_unique<FakeSignKeyManager>(),
425 absl::make_unique<FakeVerifyKeyManager>(), config),
426 StatusIs(absl::StatusCode::kFailedPrecondition));
427 EXPECT_THAT(ConfigurationImpl::GetKeyTypeInfoStore(config).status(),
428 StatusIs(absl::StatusCode::kFailedPrecondition));
429 EXPECT_THAT(ConfigurationImpl::GetKeysetWrapperStore(config).status(),
430 StatusIs(absl::StatusCode::kFailedPrecondition));
431
432 Keyset keyset;
433 std::string raw_key = AddAesGcmKeyToKeyset(
434 keyset, /*key_id=*/13, OutputPrefixType::TINK, KeyStatusType::ENABLED);
435 keyset.set_primary_key_id(13);
436 std::unique_ptr<KeysetHandle> handle =
437 CleartextKeysetHandle::GetKeysetHandle(keyset);
438 // TODO(b/265705174): Replace with GetPrimitive(config) once implemented.
439 EXPECT_THAT(handle->GetPrimitive<FakePrimitive>().status(),
440 StatusIs(absl::StatusCode::kNotFound));
441
442 ASSERT_THAT(Registry::RegisterPrimitiveWrapper(
443 absl::make_unique<FakePrimitiveWrapper>()),
444 IsOk());
445 ASSERT_THAT(
446 Registry::RegisterKeyTypeManager(absl::make_unique<FakeKeyTypeManager>(),
447 /*new_key_allowed=*/true),
448 IsOk());
449 // TODO(b/265705174): Replace with GetPrimitive(config) once implemented.
450 EXPECT_THAT(handle->GetPrimitive<FakePrimitive>(), IsOk());
451 }
452
TEST(ConfigurationImplTest,GlobalRegistryModeWithNonEmptyConfigFails)453 TEST(ConfigurationImplTest, GlobalRegistryModeWithNonEmptyConfigFails) {
454 Configuration config;
455 ASSERT_THAT(ConfigurationImpl::AddPrimitiveWrapper(
456 absl::make_unique<FakePrimitiveWrapper>(), config),
457 IsOk());
458 EXPECT_THAT(ConfigurationImpl::SetGlobalRegistryMode(config),
459 StatusIs(absl::StatusCode::kFailedPrecondition));
460 EXPECT_FALSE(ConfigurationImpl::IsInGlobalRegistryMode(config));
461 }
462
463 } // namespace
464 } // namespace internal
465 } // namespace tink
466 } // namespace crypto
467