• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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