1 // Copyright 2022 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/keyset_handle_builder.h"
18
19 #include <memory>
20 #include <ostream>
21 #include <set>
22 #include <sstream>
23 #include <string>
24 #include <utility>
25
26 #include "gmock/gmock.h"
27 #include "gtest/gtest.h"
28 #include "absl/status/status.h"
29 #include "absl/strings/string_view.h"
30 #include "tink/config/tink_config.h"
31 #include "tink/insecure_secret_key_access.h"
32 #include "tink/internal/legacy_proto_key.h"
33 #include "tink/internal/legacy_proto_parameters.h"
34 #include "tink/internal/proto_key_serialization.h"
35 #include "tink/internal/proto_parameters_serialization.h"
36 #include "tink/key_status.h"
37 #include "tink/mac/aes_cmac_key.h"
38 #include "tink/mac/aes_cmac_parameters.h"
39 #include "tink/mac/mac_key_templates.h"
40 #include "tink/partial_key_access.h"
41 #include "tink/subtle/random.h"
42 #include "tink/util/status.h"
43 #include "tink/util/test_matchers.h"
44 #include "tink/util/test_util.h"
45 #include "proto/aes_cmac.pb.h"
46 #include "proto/tink.pb.h"
47
48 namespace crypto {
49 namespace tink {
50 namespace {
51
52 using ::crypto::tink::test::AddTinkKey;
53 using ::crypto::tink::test::IsOk;
54 using ::crypto::tink::test::IsOkAndHolds;
55 using ::crypto::tink::test::StatusIs;
56 using ::google::crypto::tink::AesCmacParams;
57 using ::google::crypto::tink::KeyData;
58 using ::google::crypto::tink::Keyset;
59 using ::google::crypto::tink::KeyStatusType;
60 using ::google::crypto::tink::KeyTemplate;
61 using ::google::crypto::tink::OutputPrefixType;
62 using ::testing::Eq;
63 using ::testing::IsFalse;
64 using ::testing::IsTrue;
65 using ::testing::SizeIs;
66 using ::testing::Test;
67
68 class KeysetHandleBuilderTest : public Test {
69 protected:
SetUp()70 void SetUp() override {
71 util::Status status = TinkConfig::Register();
72 ASSERT_TRUE(status.ok()) << status;
73 }
74 };
75
76 using KeysetHandleBuilderDeathTest = KeysetHandleBuilderTest;
77
CreateLegacyProtoParameters(KeyTemplate key_template)78 util::StatusOr<internal::LegacyProtoParameters> CreateLegacyProtoParameters(
79 KeyTemplate key_template) {
80 util::StatusOr<internal::ProtoParametersSerialization> serialization =
81 internal::ProtoParametersSerialization::Create(key_template);
82 if (!serialization.ok()) return serialization.status();
83
84 return internal::LegacyProtoParameters(*serialization);
85 }
86
TEST_F(KeysetHandleBuilderTest,BuildWithSingleKey)87 TEST_F(KeysetHandleBuilderTest, BuildWithSingleKey) {
88 util::StatusOr<internal::LegacyProtoParameters> parameters =
89 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
90 ASSERT_THAT(parameters.status(), IsOk());
91
92 KeysetHandleBuilder::Entry entry =
93 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
94 *parameters, KeyStatus::kEnabled, /*is_primary=*/true,
95 /*id=*/123);
96
97 util::StatusOr<KeysetHandle> handle =
98 KeysetHandleBuilder().AddEntry(std::move(entry)).Build();
99 ASSERT_THAT(handle.status(), IsOk());
100 EXPECT_THAT(*handle, SizeIs(1));
101
102 EXPECT_THAT((*handle)[0].GetStatus(), Eq(KeyStatus::kEnabled));
103 EXPECT_THAT((*handle)[0].GetId(), Eq(123));
104 EXPECT_THAT((*handle)[0].IsPrimary(), IsTrue());
105 EXPECT_THAT((*handle)[0].GetKey()->GetParameters().HasIdRequirement(),
106 IsTrue());
107 }
108
TEST_F(KeysetHandleBuilderTest,BuildWithMultipleKeys)109 TEST_F(KeysetHandleBuilderTest, BuildWithMultipleKeys) {
110 util::StatusOr<internal::LegacyProtoParameters> parameters =
111 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
112 ASSERT_THAT(parameters.status(), IsOk());
113
114 KeysetHandleBuilder::Entry entry0 =
115 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
116 *parameters, KeyStatus::kDestroyed,
117 /*is_primary=*/false,
118 /*id=*/123);
119
120 KeysetHandleBuilder::Entry entry1 =
121 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
122 *parameters, KeyStatus::kEnabled, /*is_primary=*/true,
123 /*id=*/456);
124
125 KeysetHandleBuilder::Entry entry2 =
126 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
127 *parameters, KeyStatus::kDisabled,
128 /*is_primary=*/false, /*id=*/789);
129
130 util::StatusOr<KeysetHandle> handle = KeysetHandleBuilder()
131 .AddEntry(std::move(entry0))
132 .AddEntry(std::move(entry1))
133 .AddEntry(std::move(entry2))
134 .Build();
135 ASSERT_THAT(handle.status(), IsOk());
136 EXPECT_THAT(*handle, SizeIs(3));
137
138 EXPECT_THAT((*handle)[0].GetStatus(), Eq(KeyStatus::kDestroyed));
139 EXPECT_THAT((*handle)[0].GetId(), Eq(123));
140 EXPECT_THAT((*handle)[0].IsPrimary(), IsFalse());
141 EXPECT_THAT((*handle)[0].GetKey()->GetParameters().HasIdRequirement(),
142 IsTrue());
143
144 EXPECT_THAT((*handle)[1].GetStatus(), Eq(KeyStatus::kEnabled));
145 EXPECT_THAT((*handle)[1].GetId(), Eq(456));
146 EXPECT_THAT((*handle)[1].IsPrimary(), IsTrue());
147 EXPECT_THAT((*handle)[1].GetKey()->GetParameters().HasIdRequirement(),
148 IsTrue());
149
150 EXPECT_THAT((*handle)[2].GetStatus(), Eq(KeyStatus::kDisabled));
151 EXPECT_THAT((*handle)[2].GetId(), Eq(789));
152 EXPECT_THAT((*handle)[2].IsPrimary(), IsFalse());
153 EXPECT_THAT((*handle)[2].GetKey()->GetParameters().HasIdRequirement(),
154 IsTrue());
155 }
156
TEST_F(KeysetHandleBuilderTest,BuildCopy)157 TEST_F(KeysetHandleBuilderTest, BuildCopy) {
158 util::StatusOr<internal::LegacyProtoParameters> parameters =
159 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
160 ASSERT_THAT(parameters.status(), IsOk());
161
162 KeysetHandleBuilder::Entry entry0 =
163 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
164 *parameters, KeyStatus::kDestroyed,
165 /*is_primary=*/false,
166 /*id=*/123);
167
168 KeysetHandleBuilder::Entry entry1 =
169 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
170 *parameters, KeyStatus::kEnabled, /*is_primary=*/true,
171 /*id=*/456);
172
173 KeysetHandleBuilder::Entry entry2 =
174 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
175 *parameters, KeyStatus::kDisabled,
176 /*is_primary=*/false, /*id=*/789);
177
178 util::StatusOr<KeysetHandle> handle = KeysetHandleBuilder()
179 .AddEntry(std::move(entry0))
180 .AddEntry(std::move(entry1))
181 .AddEntry(std::move(entry2))
182 .Build();
183 ASSERT_THAT(handle.status(), IsOk());
184
185 util::StatusOr<KeysetHandle> copy = KeysetHandleBuilder(*handle).Build();
186 ASSERT_THAT(copy.status(), IsOk());
187 EXPECT_THAT(copy->size(), Eq(3));
188
189 EXPECT_THAT((*copy)[0].GetStatus(), Eq(KeyStatus::kDestroyed));
190 EXPECT_THAT((*copy)[0].GetId(), Eq(123));
191 EXPECT_THAT((*copy)[0].IsPrimary(), IsFalse());
192 EXPECT_THAT((*copy)[0].GetKey()->GetParameters().HasIdRequirement(),
193 IsTrue());
194
195 EXPECT_THAT((*copy)[1].GetStatus(), Eq(KeyStatus::kEnabled));
196 EXPECT_THAT((*copy)[1].GetId(), Eq(456));
197 EXPECT_THAT((*copy)[1].IsPrimary(), IsTrue());
198 EXPECT_THAT((*copy)[1].GetKey()->GetParameters().HasIdRequirement(),
199 IsTrue());
200
201 EXPECT_THAT((*copy)[2].GetStatus(), Eq(KeyStatus::kDisabled));
202 EXPECT_THAT((*copy)[2].GetId(), Eq(789));
203 EXPECT_THAT((*copy)[2].IsPrimary(), IsFalse());
204 EXPECT_THAT((*copy)[2].GetKey()->GetParameters().HasIdRequirement(),
205 IsTrue());
206 }
207
TEST_F(KeysetHandleBuilderTest,IsPrimary)208 TEST_F(KeysetHandleBuilderTest, IsPrimary) {
209 util::StatusOr<internal::LegacyProtoParameters> parameters =
210 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
211 ASSERT_THAT(parameters.status(), IsOk());
212
213 KeysetHandleBuilder::Entry entry =
214 KeysetHandleBuilder::Entry::CreateFromCopyableParams(*parameters,
215 KeyStatus::kEnabled,
216 /*is_primary=*/false,
217 /*id=*/123);
218 EXPECT_THAT(entry.IsPrimary(), IsFalse());
219
220 entry.SetPrimary();
221 EXPECT_THAT(entry.IsPrimary(), IsTrue());
222 }
223
TEST_F(KeysetHandleBuilderTest,SetAndGetStatus)224 TEST_F(KeysetHandleBuilderTest, SetAndGetStatus) {
225 util::StatusOr<internal::LegacyProtoParameters> parameters =
226 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
227 ASSERT_THAT(parameters.status(), IsOk());
228
229 KeysetHandleBuilder::Entry entry =
230 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
231 *parameters, KeyStatus::kEnabled, /*is_primary=*/false,
232 /*id=*/123);
233
234 entry.SetStatus(KeyStatus::kDisabled);
235 EXPECT_THAT(entry.GetStatus(), Eq(KeyStatus::kDisabled));
236 entry.SetStatus(KeyStatus::kEnabled);
237 EXPECT_THAT(entry.GetStatus(), Eq(KeyStatus::kEnabled));
238 entry.SetStatus(KeyStatus::kDestroyed);
239 EXPECT_THAT(entry.GetStatus(), Eq(KeyStatus::kDestroyed));
240 }
241
TEST_F(KeysetHandleBuilderTest,BuildWithRandomId)242 TEST_F(KeysetHandleBuilderTest, BuildWithRandomId) {
243 util::StatusOr<internal::LegacyProtoParameters> parameters =
244 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
245 ASSERT_THAT(parameters.status(), IsOk());
246
247 KeysetHandleBuilder::Entry primary =
248 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
249 *parameters, KeyStatus::kEnabled, /*is_primary=*/true);
250
251 KeysetHandleBuilder builder;
252 builder.AddEntry(std::move(primary));
253
254 int num_non_primary_entries = 1 << 16;
255 for (int i = 0; i < num_non_primary_entries; ++i) {
256 KeysetHandleBuilder::Entry non_primary =
257 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
258 *parameters, KeyStatus::kEnabled, /*is_primary=*/false);
259 builder.AddEntry(std::move(non_primary));
260 }
261
262 util::StatusOr<KeysetHandle> handle = builder.Build();
263 ASSERT_THAT(handle.status(), IsOk());
264
265 std::set<int> ids;
266 for (int i = 0; i < handle->size(); ++i) {
267 ids.insert((*handle)[i].GetId());
268 }
269 EXPECT_THAT(ids, SizeIs(num_non_primary_entries + 1));
270 }
271
TEST_F(KeysetHandleBuilderTest,BuildWithRandomIdAfterFixedId)272 TEST_F(KeysetHandleBuilderTest, BuildWithRandomIdAfterFixedId) {
273 util::StatusOr<internal::LegacyProtoParameters> parameters =
274 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
275 ASSERT_THAT(parameters.status(), IsOk());
276
277 KeysetHandleBuilder::Entry fixed =
278 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
279 *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123);
280
281 KeysetHandleBuilder::Entry random =
282 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
283 *parameters, KeyStatus::kEnabled, /*is_primary=*/false);
284
285 util::StatusOr<KeysetHandle> handle = KeysetHandleBuilder()
286 .AddEntry(std::move(fixed))
287 .AddEntry(std::move(random))
288 .Build();
289 ASSERT_THAT(handle.status(), IsOk());
290
291 EXPECT_THAT(*handle, SizeIs(2));
292 EXPECT_THAT((*handle)[0].GetId(), Eq(123));
293 }
294
TEST_F(KeysetHandleBuilderTest,BuildWithFixedIdAfterRandomIdFails)295 TEST_F(KeysetHandleBuilderTest, BuildWithFixedIdAfterRandomIdFails) {
296 util::StatusOr<internal::LegacyProtoParameters> parameters =
297 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
298 ASSERT_THAT(parameters.status(), IsOk());
299
300 KeysetHandleBuilder::Entry random =
301 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
302 *parameters, KeyStatus::kEnabled, /*is_primary=*/false);
303
304 KeysetHandleBuilder::Entry fixed =
305 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
306 *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123);
307
308 util::StatusOr<KeysetHandle> handle = KeysetHandleBuilder()
309 .AddEntry(std::move(random))
310 .AddEntry(std::move(fixed))
311 .Build();
312 ASSERT_THAT(handle.status(), StatusIs(absl::StatusCode::kFailedPrecondition));
313 }
314
TEST_F(KeysetHandleBuilderDeathTest,AddEntryToAnotherBuilderCrashes)315 TEST_F(KeysetHandleBuilderDeathTest, AddEntryToAnotherBuilderCrashes) {
316 util::StatusOr<internal::LegacyProtoParameters> parameters =
317 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
318 ASSERT_THAT(parameters.status(), IsOk());
319
320 KeysetHandleBuilder::Entry entry =
321 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
322 *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123);
323
324 KeysetHandleBuilder builder0;
325 builder0.AddEntry(std::move(entry));
326 KeysetHandleBuilder builder1;
327 EXPECT_DEATH_IF_SUPPORTED(
328 builder1.AddEntry(std::move(builder0[0])),
329 "Keyset handle builder entry already added to a builder.");
330 }
331
TEST_F(KeysetHandleBuilderDeathTest,ReAddEntryToSameBuilderCrashes)332 TEST_F(KeysetHandleBuilderDeathTest, ReAddEntryToSameBuilderCrashes) {
333 util::StatusOr<internal::LegacyProtoParameters> parameters =
334 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
335 ASSERT_THAT(parameters.status(), IsOk());
336
337 KeysetHandleBuilder::Entry entry =
338 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
339 *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123);
340
341 KeysetHandleBuilder builder;
342 builder.AddEntry(std::move(entry));
343 EXPECT_DEATH_IF_SUPPORTED(
344 builder.AddEntry(std::move(builder[0])),
345 "Keyset handle builder entry already added to a builder.");
346 }
347
TEST_F(KeysetHandleBuilderDeathTest,AddDereferencedEntryToAnotherBuilderCrashes)348 TEST_F(KeysetHandleBuilderDeathTest,
349 AddDereferencedEntryToAnotherBuilderCrashes) {
350 util::StatusOr<internal::LegacyProtoParameters> parameters =
351 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
352 ASSERT_THAT(parameters.status(), IsOk());
353
354 KeysetHandleBuilder::Entry entry =
355 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
356 *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123);
357
358 KeysetHandleBuilder builder0;
359 builder0.AddEntry(std::move(entry));
360 KeysetHandleBuilder builder1;
361 EXPECT_DEATH_IF_SUPPORTED(
362 builder1.AddEntry(std::move(*&(builder0[0]))),
363 "Keyset handle builder entry already added to a builder.");
364 }
365
TEST_F(KeysetHandleBuilderTest,RemoveEntry)366 TEST_F(KeysetHandleBuilderTest, RemoveEntry) {
367 util::StatusOr<internal::LegacyProtoParameters> parameters =
368 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
369 ASSERT_THAT(parameters.status(), IsOk());
370
371 KeysetHandleBuilder::Entry entry0 =
372 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
373 *parameters, KeyStatus::kEnabled, /*is_primary=*/false, /*id=*/123);
374
375 KeysetHandleBuilder::Entry entry1 =
376 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
377 *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/456);
378
379 util::StatusOr<KeysetHandle> handle0 = KeysetHandleBuilder()
380 .AddEntry(std::move(entry0))
381 .AddEntry(std::move(entry1))
382 .Build();
383 ASSERT_THAT(handle0.status(), IsOk());
384 ASSERT_THAT(*handle0, SizeIs(2));
385
386 util::StatusOr<KeysetHandle> handle1 =
387 KeysetHandleBuilder(*handle0).RemoveEntry(0).Build();
388 ASSERT_THAT(handle1.status(), IsOk());
389 ASSERT_THAT(*handle1, SizeIs(1));
390
391 EXPECT_THAT((*handle1)[0].GetStatus(), Eq(KeyStatus::kEnabled));
392 EXPECT_THAT((*handle1)[0].GetId(), Eq(456));
393 EXPECT_THAT((*handle1)[0].IsPrimary(), IsTrue());
394 EXPECT_THAT((*handle1)[0].GetKey()->GetParameters().HasIdRequirement(),
395 IsTrue());
396 }
397
TEST_F(KeysetHandleBuilderDeathTest,RemoveOutofRangeIndexEntryCrashes)398 TEST_F(KeysetHandleBuilderDeathTest, RemoveOutofRangeIndexEntryCrashes) {
399 util::StatusOr<internal::LegacyProtoParameters> parameters =
400 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
401 ASSERT_THAT(parameters.status(), IsOk());
402
403 KeysetHandleBuilder::Entry entry =
404 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
405 *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123);
406
407 util::StatusOr<KeysetHandle> handle =
408 KeysetHandleBuilder().AddEntry(std::move(entry)).Build();
409 ASSERT_THAT(handle.status(), IsOk());
410 ASSERT_THAT(*handle, SizeIs(1));
411
412 EXPECT_DEATH_IF_SUPPORTED(
413 KeysetHandleBuilder(*handle).RemoveEntry(1),
414 "Keyset handle builder entry removal index out of range.");
415 }
416
TEST_F(KeysetHandleBuilderTest,Size)417 TEST_F(KeysetHandleBuilderTest, Size) {
418 util::StatusOr<internal::LegacyProtoParameters> parameters =
419 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
420 ASSERT_THAT(parameters.status(), IsOk());
421
422 KeysetHandleBuilder::Entry entry0 =
423 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
424 *parameters, KeyStatus::kDestroyed,
425 /*is_primary=*/false,
426 /*id=*/123);
427
428 KeysetHandleBuilder::Entry entry1 =
429 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
430 *parameters, KeyStatus::kEnabled, /*is_primary=*/true,
431 /*id=*/456);
432
433 KeysetHandleBuilder builder;
434 ASSERT_THAT(builder, SizeIs(0));
435 builder.AddEntry(std::move(entry0));
436 ASSERT_THAT(builder, SizeIs(1));
437 builder.AddEntry(std::move(entry1));
438 EXPECT_THAT(builder, SizeIs(2));
439 }
440
TEST_F(KeysetHandleBuilderTest,NoPrimaryFails)441 TEST_F(KeysetHandleBuilderTest, NoPrimaryFails) {
442 util::StatusOr<internal::LegacyProtoParameters> parameters =
443 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
444 ASSERT_THAT(parameters.status(), IsOk());
445
446 KeysetHandleBuilder::Entry entry0 =
447 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
448 *parameters, KeyStatus::kEnabled, /*is_primary=*/false,
449 /*id=*/123);
450
451 KeysetHandleBuilder::Entry entry1 =
452 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
453 *parameters, KeyStatus::kEnabled, /*is_primary=*/false,
454 /*id=*/456);
455
456 util::StatusOr<KeysetHandle> handle = KeysetHandleBuilder()
457 .AddEntry(std::move(entry0))
458 .AddEntry(std::move(entry1))
459 .Build();
460 ASSERT_THAT(handle.status(), StatusIs(absl::StatusCode::kFailedPrecondition));
461 }
462
TEST_F(KeysetHandleBuilderTest,RemovePrimaryFails)463 TEST_F(KeysetHandleBuilderTest, RemovePrimaryFails) {
464 util::StatusOr<internal::LegacyProtoParameters> parameters =
465 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
466 ASSERT_THAT(parameters.status(), IsOk());
467
468 KeysetHandleBuilder::Entry entry0 =
469 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
470 *parameters, KeyStatus::kEnabled, /*is_primary=*/true,
471 /*id=*/123);
472
473 KeysetHandleBuilder::Entry entry1 =
474 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
475 *parameters, KeyStatus::kEnabled, /*is_primary=*/false,
476 /*id=*/456);
477
478 util::StatusOr<KeysetHandle> handle = KeysetHandleBuilder()
479 .AddEntry(std::move(entry0))
480 .AddEntry(std::move(entry1))
481 .RemoveEntry(0)
482 .Build();
483 ASSERT_THAT(handle.status(), StatusIs(absl::StatusCode::kFailedPrecondition));
484 }
485
TEST_F(KeysetHandleBuilderTest,AddPrimaryClearsOtherPrimary)486 TEST_F(KeysetHandleBuilderTest, AddPrimaryClearsOtherPrimary) {
487 util::StatusOr<internal::LegacyProtoParameters> parameters =
488 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
489 ASSERT_THAT(parameters.status(), IsOk());
490
491 KeysetHandleBuilder builder;
492 builder.AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
493 *parameters, KeyStatus::kEnabled,
494 /*is_primary=*/true,
495 /*id=*/123));
496 builder.AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
497 *parameters, KeyStatus::kEnabled,
498 /*is_primary=*/true,
499 /*id=*/456));
500
501 ASSERT_THAT(builder[0].IsPrimary(), IsFalse());
502 ASSERT_THAT(builder[1].IsPrimary(), IsTrue());
503 }
504
TEST_F(KeysetHandleBuilderTest,NoIdStrategySucceeds)505 TEST_F(KeysetHandleBuilderTest, NoIdStrategySucceeds) {
506 util::StatusOr<internal::LegacyProtoParameters> parameters =
507 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
508 ASSERT_THAT(parameters.status(), IsOk());
509
510 KeysetHandleBuilder::Entry entry =
511 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
512 *parameters, KeyStatus::kEnabled, /*is_primary=*/true);
513
514 util::StatusOr<KeysetHandle> handle =
515 KeysetHandleBuilder().AddEntry(std::move(entry)).Build();
516 ASSERT_THAT(handle, IsOk());
517 }
518
TEST_F(KeysetHandleBuilderTest,DuplicateId)519 TEST_F(KeysetHandleBuilderTest, DuplicateId) {
520 util::StatusOr<internal::LegacyProtoParameters> parameters =
521 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
522 ASSERT_THAT(parameters.status(), IsOk());
523
524 util::StatusOr<KeysetHandle> handle =
525 KeysetHandleBuilder()
526 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
527 *parameters, KeyStatus::kEnabled,
528 /*is_primary=*/true,
529 /*id=*/123))
530 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
531 *parameters, KeyStatus::kEnabled,
532 /*is_primary=*/false,
533 /*id=*/123))
534 .Build();
535 ASSERT_THAT(handle.status(), StatusIs(absl::StatusCode::kAlreadyExists));
536 }
537
TEST_F(KeysetHandleBuilderTest,CreateBuilderEntryFromParams)538 TEST_F(KeysetHandleBuilderTest, CreateBuilderEntryFromParams) {
539 util::StatusOr<AesCmacParameters> params = AesCmacParameters::Create(
540 /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
541 AesCmacParameters::Variant::kTink);
542 ASSERT_THAT(params, IsOk());
543
544 KeysetHandleBuilder::Entry entry =
545 KeysetHandleBuilder::Entry::CreateFromParams(
546 absl::make_unique<AesCmacParameters>(std::move(*params)),
547 KeyStatus::kEnabled, /*is_primary=*/true);
548
549 util::StatusOr<KeysetHandle> handle =
550 KeysetHandleBuilder().AddEntry(std::move(entry)).Build();
551 ASSERT_THAT(handle.status(), IsOk());
552 }
553
TEST_F(KeysetHandleBuilderTest,CreateBuilderEntryFromLegacyKey)554 TEST_F(KeysetHandleBuilderTest, CreateBuilderEntryFromLegacyKey) {
555 Keyset keyset;
556 Keyset::Key key;
557 AddTinkKey("first_key_type", 11, key, KeyStatusType::DISABLED,
558 KeyData::SYMMETRIC, &keyset);
559
560 util::StatusOr<internal::ProtoKeySerialization> serialization =
561 internal::ProtoKeySerialization::Create(
562 key.key_data().type_url(),
563 RestrictedData(key.SerializeAsString(),
564 InsecureSecretKeyAccess::Get()),
565 key.key_data().key_material_type(), key.output_prefix_type(),
566 key.key_id());
567
568 util::StatusOr<internal::LegacyProtoKey> proto_key =
569 internal::LegacyProtoKey::Create(*serialization,
570 InsecureSecretKeyAccess::Get());
571 ASSERT_THAT(proto_key.status(), IsOk());
572
573 KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromKey(
574 absl::make_unique<internal::LegacyProtoKey>(std::move(*proto_key)),
575 KeyStatus::kEnabled, /*is_primary=*/true);
576
577 util::StatusOr<KeysetHandle> handle =
578 KeysetHandleBuilder().AddEntry(std::move(entry)).Build();
579 ASSERT_THAT(handle.status(), IsOk());
580 }
581
TEST_F(KeysetHandleBuilderTest,CreateBuilderEntryFromKey)582 TEST_F(KeysetHandleBuilderTest, CreateBuilderEntryFromKey) {
583 util::StatusOr<AesCmacParameters> params = AesCmacParameters::Create(
584 /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
585 AesCmacParameters::Variant::kTink);
586 ASSERT_THAT(params, IsOk());
587
588 RestrictedData secret = RestrictedData(32);
589 util::StatusOr<AesCmacKey> key = AesCmacKey::Create(
590 *params, secret, /*id_requirement=*/123, GetPartialKeyAccess());
591 ASSERT_THAT(key.status(), IsOk());
592
593 KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromKey(
594 absl::make_unique<AesCmacKey>(std::move(*key)), KeyStatus::kEnabled,
595 /*is_primary=*/true);
596
597 util::StatusOr<KeysetHandle> handle =
598 KeysetHandleBuilder().AddEntry(std::move(entry)).Build();
599 ASSERT_THAT(handle.status(), IsOk());
600 }
601
TEST_F(KeysetHandleBuilderTest,CreateBuilderEntryFromCopyableKey)602 TEST_F(KeysetHandleBuilderTest, CreateBuilderEntryFromCopyableKey) {
603 Keyset keyset;
604 Keyset::Key key;
605 AddTinkKey("first_key_type", 11, key, KeyStatusType::DISABLED,
606 KeyData::SYMMETRIC, &keyset);
607
608 util::StatusOr<internal::ProtoKeySerialization> serialization =
609 internal::ProtoKeySerialization::Create(
610 key.key_data().type_url(),
611 RestrictedData(key.SerializeAsString(),
612 InsecureSecretKeyAccess::Get()),
613 key.key_data().key_material_type(), key.output_prefix_type(),
614 key.key_id());
615
616 util::StatusOr<internal::LegacyProtoKey> proto_key =
617 internal::LegacyProtoKey::Create(*serialization,
618 InsecureSecretKeyAccess::Get());
619 ASSERT_THAT(proto_key.status(), IsOk());
620
621 KeysetHandleBuilder::Entry entry =
622 KeysetHandleBuilder::Entry::CreateFromCopyableKey(
623 *proto_key, KeyStatus::kEnabled, /*is_primary=*/true);
624
625 util::StatusOr<KeysetHandle> handle =
626 KeysetHandleBuilder().AddEntry(std::move(entry)).Build();
627 ASSERT_THAT(handle.status(), IsOk());
628 }
629
TEST_F(KeysetHandleBuilderTest,CreateBuilderEntryFromParameters)630 TEST_F(KeysetHandleBuilderTest, CreateBuilderEntryFromParameters) {
631 util::StatusOr<internal::LegacyProtoParameters> parameters =
632 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
633 ASSERT_THAT(parameters.status(), IsOk());
634
635 KeysetHandleBuilder::Entry entry =
636 KeysetHandleBuilder::Entry::CreateFromParams(
637 absl::make_unique<internal::LegacyProtoParameters>(*parameters),
638 KeyStatus::kEnabled, /*is_primary=*/true);
639
640 util::StatusOr<KeysetHandle> handle =
641 KeysetHandleBuilder().AddEntry(std::move(entry)).Build();
642 ASSERT_THAT(handle.status(), IsOk());
643 }
644
TEST_F(KeysetHandleBuilderTest,CreateBuilderEntryFromCopyableParameters)645 TEST_F(KeysetHandleBuilderTest, CreateBuilderEntryFromCopyableParameters) {
646 util::StatusOr<internal::LegacyProtoParameters> parameters =
647 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
648 ASSERT_THAT(parameters.status(), IsOk());
649
650 KeysetHandleBuilder::Entry entry =
651 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
652 *parameters, KeyStatus::kEnabled, /*is_primary=*/true);
653
654 util::StatusOr<KeysetHandle> handle =
655 KeysetHandleBuilder().AddEntry(std::move(entry)).Build();
656 ASSERT_THAT(handle.status(), IsOk());
657 }
658
TEST_F(KeysetHandleBuilderTest,UsePrimitiveFromLegacyProtoParams)659 TEST_F(KeysetHandleBuilderTest, UsePrimitiveFromLegacyProtoParams) {
660 util::StatusOr<internal::LegacyProtoParameters> parameters =
661 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
662 ASSERT_THAT(parameters.status(), IsOk());
663
664 KeysetHandleBuilder::Entry entry =
665 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
666 *parameters, KeyStatus::kEnabled, /*is_primary=*/true);
667
668 util::StatusOr<KeysetHandle> handle =
669 KeysetHandleBuilder().AddEntry(std::move(entry)).Build();
670 ASSERT_THAT(handle.status(), IsOk());
671
672 util::StatusOr<std::unique_ptr<Mac>> mac = handle->GetPrimitive<Mac>();
673 ASSERT_THAT(mac.status(), IsOk());
674 util::StatusOr<std::string> tag = (*mac)->ComputeMac("some input");
675 ASSERT_THAT(tag.status(), IsOk());
676 util::Status verified = (*mac)->VerifyMac(*tag, "some input");
677 EXPECT_THAT(verified, IsOk());
678 }
679
TEST_F(KeysetHandleBuilderTest,UsePrimitiveFromParams)680 TEST_F(KeysetHandleBuilderTest, UsePrimitiveFromParams) {
681 util::StatusOr<AesCmacParameters> params = AesCmacParameters::Create(
682 /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
683 AesCmacParameters::Variant::kTink);
684 ASSERT_THAT(params, IsOk());
685
686 KeysetHandleBuilder::Entry entry =
687 KeysetHandleBuilder::Entry::CreateFromParams(
688 absl::make_unique<AesCmacParameters>(std::move(*params)),
689 KeyStatus::kEnabled, /*is_primary=*/true);
690
691 util::StatusOr<KeysetHandle> handle =
692 KeysetHandleBuilder().AddEntry(std::move(entry)).Build();
693 ASSERT_THAT(handle.status(), IsOk());
694
695 util::StatusOr<std::unique_ptr<Mac>> mac = handle->GetPrimitive<Mac>();
696 ASSERT_THAT(mac.status(), IsOk());
697 util::StatusOr<std::string> tag = (*mac)->ComputeMac("some input");
698 ASSERT_THAT(tag.status(), IsOk());
699 util::Status verified = (*mac)->VerifyMac(*tag, "some input");
700 EXPECT_THAT(verified, IsOk());
701 }
702
TEST_F(KeysetHandleBuilderTest,UsePrimitiveFromLegacyProtoKey)703 TEST_F(KeysetHandleBuilderTest, UsePrimitiveFromLegacyProtoKey) {
704 AesCmacParams params;
705 params.set_tag_size(16);
706 google::crypto::tink::AesCmacKey key;
707 *key.mutable_params() = params;
708 key.set_version(0);
709 key.set_key_value(subtle::Random::GetRandomBytes(32));
710
711 util::StatusOr<internal::ProtoKeySerialization> serialization =
712 internal::ProtoKeySerialization::Create(
713 "type.googleapis.com/google.crypto.tink.AesCmacKey",
714 RestrictedData(key.SerializeAsString(),
715 InsecureSecretKeyAccess::Get()),
716 KeyData::SYMMETRIC, OutputPrefixType::TINK,
717 /*id_requirement=*/123);
718 ASSERT_THAT(serialization, IsOk());
719
720 util::StatusOr<internal::LegacyProtoKey> proto_key =
721 internal::LegacyProtoKey::Create(*serialization,
722 InsecureSecretKeyAccess::Get());
723 ASSERT_THAT(proto_key.status(), IsOk());
724
725 KeysetHandleBuilder::Entry entry =
726 KeysetHandleBuilder::Entry::CreateFromCopyableKey(
727 *proto_key, KeyStatus::kEnabled, /*is_primary=*/true);
728
729 util::StatusOr<KeysetHandle> handle =
730 KeysetHandleBuilder().AddEntry(std::move(entry)).Build();
731 ASSERT_THAT(handle.status(), IsOk());
732
733 util::StatusOr<std::unique_ptr<Mac>> mac = handle->GetPrimitive<Mac>();
734 ASSERT_THAT(mac.status(), IsOk());
735 util::StatusOr<std::string> tag = (*mac)->ComputeMac("some input");
736 ASSERT_THAT(tag.status(), IsOk());
737 util::Status verified = (*mac)->VerifyMac(*tag, "some input");
738 EXPECT_THAT(verified, IsOk());
739 }
740
TEST_F(KeysetHandleBuilderTest,UsePrimitiveFromKey)741 TEST_F(KeysetHandleBuilderTest, UsePrimitiveFromKey) {
742 util::StatusOr<AesCmacParameters> params = AesCmacParameters::Create(
743 /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
744 AesCmacParameters::Variant::kTink);
745 ASSERT_THAT(params, IsOk());
746
747 RestrictedData secret = RestrictedData(32);
748 util::StatusOr<AesCmacKey> key = AesCmacKey::Create(
749 *params, secret, /*id_requirement=*/123, GetPartialKeyAccess());
750 ASSERT_THAT(key.status(), IsOk());
751
752 KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromKey(
753 absl::make_unique<AesCmacKey>(std::move(*key)), KeyStatus::kEnabled,
754 /*is_primary=*/true);
755
756 util::StatusOr<KeysetHandle> handle =
757 KeysetHandleBuilder().AddEntry(std::move(entry)).Build();
758 ASSERT_THAT(handle.status(), IsOk());
759
760 util::StatusOr<std::unique_ptr<Mac>> mac = handle->GetPrimitive<Mac>();
761 ASSERT_THAT(mac.status(), IsOk());
762 util::StatusOr<std::string> tag = (*mac)->ComputeMac("some input");
763 ASSERT_THAT(tag.status(), IsOk());
764 util::Status verified = (*mac)->VerifyMac(*tag, "some input");
765 EXPECT_THAT(verified, IsOk());
766 }
767
TEST_F(KeysetHandleBuilderTest,BuildTwiceFails)768 TEST_F(KeysetHandleBuilderTest, BuildTwiceFails) {
769 util::StatusOr<internal::LegacyProtoParameters> parameters =
770 CreateLegacyProtoParameters(MacKeyTemplates::AesCmac());
771 ASSERT_THAT(parameters.status(), IsOk());
772
773 KeysetHandleBuilder::Entry entry =
774 KeysetHandleBuilder::Entry::CreateFromCopyableParams(
775 *parameters, KeyStatus::kEnabled, /*is_primary=*/true,
776 /*id=*/123);
777
778 KeysetHandleBuilder builder;
779 builder.AddEntry(std::move(entry));
780
781 EXPECT_THAT(builder.Build(), IsOk());
782 EXPECT_THAT(builder.Build().status(),
783 StatusIs(absl::StatusCode::kFailedPrecondition));
784 }
785
TEST_F(KeysetHandleBuilderTest,UsePrimitivesFromSplitKeyset)786 TEST_F(KeysetHandleBuilderTest, UsePrimitivesFromSplitKeyset) {
787 util::StatusOr<AesCmacParameters> params = AesCmacParameters::Create(
788 /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
789 AesCmacParameters::Variant::kTink);
790 ASSERT_THAT(params, IsOk());
791
792 util::StatusOr<KeysetHandle> handle =
793 KeysetHandleBuilder()
794 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
795 *params, KeyStatus::kEnabled, /*is_primary=*/false))
796 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
797 *params, KeyStatus::kEnabled, /*is_primary=*/true))
798 .Build();
799 ASSERT_THAT(handle, IsOkAndHolds(SizeIs(2)));
800
801 util::StatusOr<KeysetHandle> handle0 =
802 KeysetHandleBuilder()
803 .AddEntry(KeysetHandleBuilder::Entry::CreateFromKey(
804 (*handle)[0].GetKey(), KeyStatus::kEnabled,
805 /*is_primary=*/true))
806 .Build();
807 ASSERT_THAT(handle0, IsOkAndHolds(SizeIs(1)));
808 ASSERT_THAT((*handle)[0].GetId(), Eq((*handle0)[0].GetId()));
809
810 util::StatusOr<KeysetHandle> handle1 =
811 KeysetHandleBuilder()
812 .AddEntry(KeysetHandleBuilder::Entry::CreateFromKey(
813 (*handle)[1].GetKey(), KeyStatus::kEnabled,
814 /*is_primary=*/true))
815 .Build();
816 ASSERT_THAT(handle1, IsOkAndHolds(SizeIs(1)));
817 ASSERT_THAT((*handle)[1].GetId(), Eq((*handle1)[0].GetId()));
818
819 util::StatusOr<std::unique_ptr<Mac>> mac0 = handle0->GetPrimitive<Mac>();
820 ASSERT_THAT(mac0.status(), IsOk());
821 util::StatusOr<std::string> tag0 = (*mac0)->ComputeMac("some input");
822 ASSERT_THAT(tag0.status(), IsOk());
823
824 util::StatusOr<std::unique_ptr<Mac>> mac1 = handle1->GetPrimitive<Mac>();
825 ASSERT_THAT(mac1.status(), IsOk());
826 util::StatusOr<std::string> tag1 = (*mac1)->ComputeMac("some other input");
827 ASSERT_THAT(tag1.status(), IsOk());
828
829 // Use original keyset to verify tags computed from new keysets.
830 util::StatusOr<std::unique_ptr<Mac>> mac = handle->GetPrimitive<Mac>();
831 ASSERT_THAT(mac.status(), IsOk());
832 EXPECT_THAT((*mac)->VerifyMac(*tag0, "some input"), IsOk());
833 EXPECT_THAT((*mac)->VerifyMac(*tag1, "some other input"), IsOk());
834 }
835
836 } // namespace
837 } // namespace tink
838 } // namespace crypto
839