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/internal/keyset_handle_builder_entry.h"
18
19 #include <string>
20
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include "absl/memory/memory.h"
24 #include "absl/status/status.h"
25 #include "absl/types/optional.h"
26 #include "tink/config/tink_config.h"
27 #include "tink/insecure_secret_key_access.h"
28 #include "tink/internal/legacy_proto_key.h"
29 #include "tink/internal/legacy_proto_parameters.h"
30 #include "tink/internal/proto_key_serialization.h"
31 #include "tink/internal/proto_parameters_serialization.h"
32 #include "tink/key.h"
33 #include "tink/key_status.h"
34 #include "tink/keyset_handle.h"
35 #include "tink/keyset_handle_builder.h"
36 #include "tink/mac/aes_cmac_key.h"
37 #include "tink/mac/aes_cmac_parameters.h"
38 #include "tink/mac/mac_key_templates.h"
39 #include "tink/parameters.h"
40 #include "tink/partial_key_access.h"
41 #include "tink/restricted_data.h"
42 #include "tink/secret_key_access_token.h"
43 #include "tink/util/status.h"
44 #include "tink/util/statusor.h"
45 #include "tink/util/test_matchers.h"
46 #include "proto/tink.pb.h"
47
48 namespace crypto {
49 namespace tink {
50 namespace internal {
51 namespace {
52
53 using ::crypto::tink::test::IsOk;
54 using ::crypto::tink::test::StatusIs;
55 using ::google::crypto::tink::KeyData;
56 using ::google::crypto::tink::Keyset;
57 using ::google::crypto::tink::KeyStatusType;
58 using ::google::crypto::tink::OutputPrefixType;
59 using ::testing::Eq;
60 using ::testing::IsFalse;
61 using ::testing::IsTrue;
62 using ::testing::Test;
63
CreateLegacyProtoParameters()64 util::StatusOr<LegacyProtoParameters> CreateLegacyProtoParameters() {
65 util::StatusOr<ProtoParametersSerialization> serialization =
66 ProtoParametersSerialization::Create(MacKeyTemplates::AesCmac());
67 if (!serialization.ok()) return serialization.status();
68
69 return LegacyProtoParameters(*serialization);
70 }
71
TEST(KeysetHandleBuilderEntryTest,Status)72 TEST(KeysetHandleBuilderEntryTest, Status) {
73 util::StatusOr<LegacyProtoParameters> parameters =
74 CreateLegacyProtoParameters();
75 ASSERT_THAT(parameters, IsOk());
76
77 ParametersEntry entry =
78 ParametersEntry(absl::make_unique<LegacyProtoParameters>(*parameters));
79
80 entry.SetStatus(KeyStatus::kEnabled);
81 EXPECT_THAT(entry.GetStatus(), KeyStatus::kEnabled);
82
83 entry.SetStatus(KeyStatus::kDisabled);
84 EXPECT_THAT(entry.GetStatus(), KeyStatus::kDisabled);
85
86 entry.SetStatus(KeyStatus::kDestroyed);
87 EXPECT_THAT(entry.GetStatus(), KeyStatus::kDestroyed);
88 }
89
TEST(KeysetHandleBuilderEntryTest,IdStrategy)90 TEST(KeysetHandleBuilderEntryTest, IdStrategy) {
91 util::StatusOr<LegacyProtoParameters> parameters =
92 CreateLegacyProtoParameters();
93 ASSERT_THAT(parameters, IsOk());
94
95 ParametersEntry entry =
96 ParametersEntry(absl::make_unique<LegacyProtoParameters>(*parameters));
97
98 entry.SetFixedId(123);
99 EXPECT_THAT(entry.GetKeyIdStrategyEnum(), KeyIdStrategyEnum::kFixedId);
100 EXPECT_THAT(entry.GetKeyIdStrategy().strategy, KeyIdStrategyEnum::kFixedId);
101 EXPECT_THAT(entry.GetKeyIdStrategy().id_requirement, 123);
102 EXPECT_THAT(entry.GetKeyIdRequirement(), 123);
103
104 entry.SetRandomId();
105 EXPECT_THAT(entry.GetKeyIdStrategyEnum(), KeyIdStrategyEnum::kRandomId);
106 EXPECT_THAT(entry.GetKeyIdStrategy().strategy, KeyIdStrategyEnum::kRandomId);
107 EXPECT_THAT(entry.GetKeyIdStrategy().id_requirement, absl::nullopt);
108 EXPECT_THAT(entry.GetKeyIdRequirement(), absl::nullopt);
109 }
110
TEST(KeysetHandleBuilderEntryTest,Primary)111 TEST(KeysetHandleBuilderEntryTest, Primary) {
112 util::StatusOr<LegacyProtoParameters> parameters =
113 CreateLegacyProtoParameters();
114 ASSERT_THAT(parameters, IsOk());
115
116 ParametersEntry entry =
117 ParametersEntry(absl::make_unique<LegacyProtoParameters>(*parameters));
118
119 entry.SetPrimary();
120 EXPECT_THAT(entry.IsPrimary(), IsTrue());
121
122 entry.UnsetPrimary();
123 EXPECT_THAT(entry.IsPrimary(), IsFalse());
124 }
125
126 class CreateKeysetKeyTest : public Test {
127 protected:
SetUp()128 void SetUp() override { ASSERT_THAT(TinkConfig::Register(), IsOk()); }
129 };
130
TEST_F(CreateKeysetKeyTest,CreateKeysetKeyFromParameters)131 TEST_F(CreateKeysetKeyTest, CreateKeysetKeyFromParameters) {
132 util::StatusOr<LegacyProtoParameters> parameters =
133 CreateLegacyProtoParameters();
134 ASSERT_THAT(parameters, IsOk());
135
136 ParametersEntry entry =
137 ParametersEntry(absl::make_unique<LegacyProtoParameters>(*parameters));
138 entry.SetStatus(KeyStatus::kEnabled);
139 entry.SetFixedId(123);
140 util::StatusOr<Keyset::Key> keyset_key = entry.CreateKeysetKey(/*id=*/123);
141 ASSERT_THAT(keyset_key, IsOk());
142
143 EXPECT_THAT(keyset_key->status(), Eq(KeyStatusType::ENABLED));
144 EXPECT_THAT(keyset_key->key_id(), Eq(123));
145 EXPECT_THAT(
146 keyset_key->output_prefix_type(),
147 Eq(parameters->Serialization().GetKeyTemplate().output_prefix_type()));
148 EXPECT_THAT(keyset_key->key_data().type_url(),
149 Eq(parameters->Serialization().GetKeyTemplate().type_url()));
150 }
151
TEST_F(CreateKeysetKeyTest,CreateKeysetKeyFromParametersWithDifferentKeyId)152 TEST_F(CreateKeysetKeyTest, CreateKeysetKeyFromParametersWithDifferentKeyId) {
153 util::StatusOr<LegacyProtoParameters> parameters =
154 CreateLegacyProtoParameters();
155 ASSERT_THAT(parameters, IsOk());
156
157 ParametersEntry entry =
158 ParametersEntry(absl::make_unique<LegacyProtoParameters>(*parameters));
159 entry.SetStatus(KeyStatus::kEnabled);
160 entry.SetFixedId(123);
161 util::StatusOr<Keyset::Key> keyset_key = entry.CreateKeysetKey(/*id=*/456);
162 EXPECT_THAT(keyset_key.status(),
163 StatusIs(absl::StatusCode::kInvalidArgument));
164 }
165
TEST_F(CreateKeysetKeyTest,CreateKeysetKeyFromKey)166 TEST_F(CreateKeysetKeyTest, CreateKeysetKeyFromKey) {
167 RestrictedData serialized_key =
168 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
169 util::StatusOr<ProtoKeySerialization> serialization =
170 ProtoKeySerialization::Create("type_url", serialized_key,
171 KeyData::SYMMETRIC, OutputPrefixType::TINK,
172 /*id_requirement=*/123);
173 ASSERT_THAT(serialization.status(), IsOk());
174
175 util::StatusOr<LegacyProtoKey> key =
176 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
177 ASSERT_THAT(key.status(), IsOk());
178
179 KeyEntry entry = KeyEntry(absl::make_unique<LegacyProtoKey>(*key));
180 entry.SetStatus(KeyStatus::kEnabled);
181 entry.SetFixedId(123);
182 util::StatusOr<Keyset::Key> keyset_key = entry.CreateKeysetKey(/*id=*/123);
183 ASSERT_THAT(keyset_key, IsOk());
184
185 EXPECT_THAT(keyset_key->status(), Eq(KeyStatusType::ENABLED));
186 EXPECT_THAT(keyset_key->key_id(), Eq(123));
187 EXPECT_THAT(keyset_key->output_prefix_type(), OutputPrefixType::TINK);
188 EXPECT_THAT(keyset_key->key_data().type_url(), Eq("type_url"));
189 EXPECT_THAT(keyset_key->key_data().key_material_type(),
190 Eq(KeyData::SYMMETRIC));
191 EXPECT_THAT(keyset_key->key_data().value(), Eq("serialized_key"));
192 }
193
TEST_F(CreateKeysetKeyTest,CreateKeysetKeyFromKeyWithDifferentEntryKeyId)194 TEST_F(CreateKeysetKeyTest, CreateKeysetKeyFromKeyWithDifferentEntryKeyId) {
195 RestrictedData serialized_key =
196 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
197 util::StatusOr<ProtoKeySerialization> serialization =
198 ProtoKeySerialization::Create("type_url", serialized_key,
199 KeyData::SYMMETRIC, OutputPrefixType::TINK,
200 /*id_requirement=*/123);
201 ASSERT_THAT(serialization.status(), IsOk());
202
203 util::StatusOr<LegacyProtoKey> key =
204 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
205 ASSERT_THAT(key.status(), IsOk());
206
207 KeyEntry entry = KeyEntry(absl::make_unique<LegacyProtoKey>(*key));
208 entry.SetStatus(KeyStatus::kEnabled);
209 entry.SetFixedId(123);
210 util::StatusOr<Keyset::Key> keyset_key = entry.CreateKeysetKey(/*id=*/456);
211 EXPECT_THAT(keyset_key.status(),
212 StatusIs(absl::StatusCode::kInvalidArgument));
213 }
214
TEST_F(CreateKeysetKeyTest,CreateKeysetKeyFromKeyWithDifferentSerializationKeyId)215 TEST_F(CreateKeysetKeyTest,
216 CreateKeysetKeyFromKeyWithDifferentSerializationKeyId) {
217 RestrictedData serialized_key =
218 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
219 util::StatusOr<ProtoKeySerialization> serialization =
220 ProtoKeySerialization::Create("type_url", serialized_key,
221 KeyData::SYMMETRIC, OutputPrefixType::TINK,
222 /*id_requirement=*/123);
223 ASSERT_THAT(serialization.status(), IsOk());
224
225 util::StatusOr<LegacyProtoKey> key =
226 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
227 ASSERT_THAT(key.status(), IsOk());
228
229 KeyEntry entry = KeyEntry(absl::make_unique<LegacyProtoKey>(*key));
230 entry.SetStatus(KeyStatus::kEnabled);
231 util::StatusOr<Keyset::Key> keyset_key = entry.CreateKeysetKey(/*id=*/456);
232 EXPECT_THAT(keyset_key.status(),
233 StatusIs(absl::StatusCode::kInvalidArgument));
234 }
235
TEST_F(CreateKeysetKeyTest,CreateKeysetFromNonLegacyParameters)236 TEST_F(CreateKeysetKeyTest, CreateKeysetFromNonLegacyParameters) {
237 util::StatusOr<AesCmacParameters> aes_cmac_parameters =
238 AesCmacParameters::Create(/*key_size_in_bytes=*/32,
239 /*cryptographic_tag_size_in_bytes=*/10,
240 AesCmacParameters::Variant::kTink);
241 ASSERT_THAT(aes_cmac_parameters, IsOk());
242
243 util::StatusOr<KeysetHandle> handle =
244 KeysetHandleBuilder()
245 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
246 *aes_cmac_parameters, KeyStatus::kEnabled, /*is_primary=*/true,
247 /*id=*/123))
248 .Build();
249 ASSERT_THAT(handle, IsOk());
250 }
251
TEST_F(CreateKeysetKeyTest,CreateKeysetWithAllowedParametersProhibitedByKeyManager)252 TEST_F(CreateKeysetKeyTest,
253 CreateKeysetWithAllowedParametersProhibitedByKeyManager) {
254 util::StatusOr<AesCmacParameters> aes_cmac_parameters =
255 AesCmacParameters::Create(/*key_size_in_bytes=*/16,
256 /*cryptographic_tag_size_in_bytes=*/10,
257 AesCmacParameters::Variant::kTink);
258 ASSERT_THAT(aes_cmac_parameters, IsOk());
259
260 util::StatusOr<KeysetHandle> handle =
261 KeysetHandleBuilder()
262 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
263 *aes_cmac_parameters, KeyStatus::kEnabled, /*is_primary=*/true,
264 /*id=*/123))
265 .Build();
266 ASSERT_THAT(handle.status(), StatusIs(absl::StatusCode::kInvalidArgument));
267 }
268
TEST_F(CreateKeysetKeyTest,CreateKeysetFromNonLegacyKey)269 TEST_F(CreateKeysetKeyTest, CreateKeysetFromNonLegacyKey) {
270 util::StatusOr<AesCmacParameters> aes_cmac_parameters =
271 AesCmacParameters::Create(/*key_size_in_bytes=*/32,
272 /*cryptographic_tag_size_in_bytes=*/10,
273 AesCmacParameters::Variant::kTink);
274 ASSERT_THAT(aes_cmac_parameters, IsOk());
275 util::StatusOr<AesCmacKey> aes_cmac_key = AesCmacKey::Create(
276 *aes_cmac_parameters, RestrictedData(32), 123, GetPartialKeyAccess());
277 ASSERT_THAT(aes_cmac_key.status(), IsOk());
278
279 util::StatusOr<KeysetHandle> handle =
280 KeysetHandleBuilder()
281 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey(
282 *aes_cmac_key, KeyStatus::kEnabled, /*is_primary=*/true))
283 .Build();
284 ASSERT_THAT(handle, IsOk());
285 }
286
287 } // namespace
288 } // namespace internal
289 } // namespace tink
290 } // namespace crypto
291