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/legacy_proto_key.h"
18
19 #include <string>
20 #include <tuple>
21
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "absl/status/status.h"
25 #include "absl/types/optional.h"
26 #include "tink/insecure_secret_key_access.h"
27 #include "tink/internal/proto_key_serialization.h"
28 #include "tink/key.h"
29 #include "tink/parameters.h"
30 #include "tink/restricted_data.h"
31 #include "tink/secret_key_access_token.h"
32 #include "tink/util/statusor.h"
33 #include "tink/util/test_matchers.h"
34 #include "proto/tink.pb.h"
35
36 namespace crypto {
37 namespace tink {
38 namespace internal {
39
40 using ::crypto::tink::test::IsOk;
41 using ::crypto::tink::test::StatusIs;
42 using ::google::crypto::tink::KeyData;
43 using ::google::crypto::tink::OutputPrefixType;
44 using ::testing::Eq;
45 using ::testing::IsTrue;
46 using ::testing::TestWithParam;
47 using ::testing::Values;
48
49 class LegacyProtoKeyTest : public ::testing::Test {
50 protected:
51 // Although this is a friend class, this utility function is necessary to
52 // access `ProtoKeySerialization::EqualsWithPotentialFalseNegatives()`
53 // since the test fixtures are subclasses that would not have direct access.
Equals(ProtoKeySerialization serialization,ProtoKeySerialization other)54 bool Equals(ProtoKeySerialization serialization,
55 ProtoKeySerialization other) {
56 return serialization.EqualsWithPotentialFalseNegatives(other);
57 }
58 };
59
TEST_F(LegacyProtoKeyTest,CreateAndSerialization)60 TEST_F(LegacyProtoKeyTest, CreateAndSerialization) {
61 RestrictedData serialized_key =
62 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
63 util::StatusOr<ProtoKeySerialization> serialization =
64 ProtoKeySerialization::Create("type_url", serialized_key,
65 KeyData::SYMMETRIC, OutputPrefixType::TINK,
66 /*id_requirement=*/12345);
67 ASSERT_THAT(serialization.status(), IsOk());
68
69 util::StatusOr<LegacyProtoKey> key =
70 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
71 ASSERT_THAT(key.status(), IsOk());
72
73 EXPECT_THAT(key->GetIdRequirement(), Eq(12345));
74 EXPECT_THAT(key->GetParameters().HasIdRequirement(), IsTrue());
75 EXPECT_THAT(key->Serialization(InsecureSecretKeyAccess::Get()), IsOk());
76
77 util::StatusOr<const ProtoKeySerialization*> key_serialization =
78 key->Serialization(InsecureSecretKeyAccess::Get());
79 ASSERT_THAT(key_serialization.status(), IsOk());
80 EXPECT_THAT(Equals(**key_serialization, *serialization), IsTrue());
81 }
82
TEST_F(LegacyProtoKeyTest,Equals)83 TEST_F(LegacyProtoKeyTest, Equals) {
84 RestrictedData serialized_key =
85 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
86
87 util::StatusOr<ProtoKeySerialization> serialization =
88 ProtoKeySerialization::Create("type_url", serialized_key,
89 KeyData::SYMMETRIC, OutputPrefixType::TINK,
90 /*id_requirement=*/12345);
91 ASSERT_THAT(serialization.status(), IsOk());
92
93 util::StatusOr<ProtoKeySerialization> other_serialization =
94 ProtoKeySerialization::Create("type_url", serialized_key,
95 KeyData::SYMMETRIC, OutputPrefixType::TINK,
96 /*id_requirement=*/12345);
97 ASSERT_THAT(other_serialization.status(), IsOk());
98
99 util::StatusOr<LegacyProtoKey> key =
100 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
101 ASSERT_THAT(key.status(), IsOk());
102
103 util::StatusOr<LegacyProtoKey> other_key = LegacyProtoKey::Create(
104 *other_serialization, InsecureSecretKeyAccess::Get());
105 ASSERT_THAT(other_key.status(), IsOk());
106
107 EXPECT_TRUE(*key == *other_key);
108 EXPECT_TRUE(*other_key == *key);
109 EXPECT_FALSE(*key != *other_key);
110 EXPECT_FALSE(*other_key != *key);
111 }
112
TEST_F(LegacyProtoKeyTest,TypeUrlNotEqual)113 TEST_F(LegacyProtoKeyTest, TypeUrlNotEqual) {
114 RestrictedData serialized_key =
115 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
116
117 util::StatusOr<ProtoKeySerialization> serialization =
118 ProtoKeySerialization::Create("type_url", serialized_key,
119 KeyData::SYMMETRIC, OutputPrefixType::TINK,
120 /*id_requirement=*/12345);
121 ASSERT_THAT(serialization.status(), IsOk());
122
123 util::StatusOr<ProtoKeySerialization> other_serialization =
124 ProtoKeySerialization::Create("other_type_url", serialized_key,
125 KeyData::SYMMETRIC, OutputPrefixType::TINK,
126 /*id_requirement=*/12345);
127 ASSERT_THAT(other_serialization.status(), IsOk());
128
129 util::StatusOr<LegacyProtoKey> key =
130 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
131 ASSERT_THAT(key.status(), IsOk());
132
133 util::StatusOr<LegacyProtoKey> other_key = LegacyProtoKey::Create(
134 *other_serialization, InsecureSecretKeyAccess::Get());
135 ASSERT_THAT(other_key.status(), IsOk());
136
137 EXPECT_TRUE(*key != *other_key);
138 EXPECT_TRUE(*other_key != *key);
139 EXPECT_FALSE(*key == *other_key);
140 EXPECT_FALSE(*other_key == *key);
141 }
142
TEST_F(LegacyProtoKeyTest,SerializedKeyNotEqual)143 TEST_F(LegacyProtoKeyTest, SerializedKeyNotEqual) {
144 RestrictedData serialized_key =
145 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
146 RestrictedData other_serialized_key =
147 RestrictedData("other_serialized_key", InsecureSecretKeyAccess::Get());
148
149 util::StatusOr<ProtoKeySerialization> serialization =
150 ProtoKeySerialization::Create("type_url", serialized_key,
151 KeyData::SYMMETRIC, OutputPrefixType::TINK,
152 /*id_requirement=*/12345);
153 ASSERT_THAT(serialization.status(), IsOk());
154
155 util::StatusOr<ProtoKeySerialization> other_serialization =
156 ProtoKeySerialization::Create("type_url", other_serialized_key,
157 KeyData::SYMMETRIC, OutputPrefixType::TINK,
158 /*id_requirement=*/12345);
159 ASSERT_THAT(other_serialization.status(), IsOk());
160
161 util::StatusOr<LegacyProtoKey> key =
162 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
163 ASSERT_THAT(key.status(), IsOk());
164
165 util::StatusOr<LegacyProtoKey> other_key = LegacyProtoKey::Create(
166 *other_serialization, InsecureSecretKeyAccess::Get());
167 ASSERT_THAT(other_key.status(), IsOk());
168
169 EXPECT_TRUE(*key != *other_key);
170 EXPECT_TRUE(*other_key != *key);
171 EXPECT_FALSE(*key == *other_key);
172 EXPECT_FALSE(*other_key == *key);
173 }
174
TEST_F(LegacyProtoKeyTest,KeyMaterialTypeNotEqual)175 TEST_F(LegacyProtoKeyTest, KeyMaterialTypeNotEqual) {
176 RestrictedData serialized_key =
177 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
178
179 util::StatusOr<ProtoKeySerialization> serialization =
180 ProtoKeySerialization::Create("type_url", serialized_key,
181 KeyData::SYMMETRIC, OutputPrefixType::TINK,
182 /*id_requirement=*/12345);
183 ASSERT_THAT(serialization.status(), IsOk());
184
185 util::StatusOr<ProtoKeySerialization> other_serialization =
186 ProtoKeySerialization::Create("type_url", serialized_key, KeyData::REMOTE,
187 OutputPrefixType::TINK,
188 /*id_requirement=*/12345);
189 ASSERT_THAT(other_serialization.status(), IsOk());
190
191 util::StatusOr<LegacyProtoKey> key =
192 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
193 ASSERT_THAT(key.status(), IsOk());
194
195 util::StatusOr<LegacyProtoKey> other_key = LegacyProtoKey::Create(
196 *other_serialization, InsecureSecretKeyAccess::Get());
197 ASSERT_THAT(other_key.status(), IsOk());
198
199 EXPECT_TRUE(*key != *other_key);
200 EXPECT_TRUE(*other_key != *key);
201 EXPECT_FALSE(*key == *other_key);
202 EXPECT_FALSE(*other_key == *key);
203 }
204
TEST_F(LegacyProtoKeyTest,OutputPrefixTypeNotEqual)205 TEST_F(LegacyProtoKeyTest, OutputPrefixTypeNotEqual) {
206 RestrictedData serialized_key =
207 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
208
209 util::StatusOr<ProtoKeySerialization> serialization =
210 ProtoKeySerialization::Create("type_url", serialized_key,
211 KeyData::SYMMETRIC, OutputPrefixType::TINK,
212 /*id_requirement=*/12345);
213 ASSERT_THAT(serialization.status(), IsOk());
214
215 util::StatusOr<ProtoKeySerialization> other_serialization =
216 ProtoKeySerialization::Create("type_url", serialized_key,
217 KeyData::SYMMETRIC,
218 OutputPrefixType::CRUNCHY,
219 /*id_requirement=*/12345);
220 ASSERT_THAT(other_serialization.status(), IsOk());
221
222 util::StatusOr<LegacyProtoKey> key =
223 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
224 ASSERT_THAT(key.status(), IsOk());
225
226 util::StatusOr<LegacyProtoKey> other_key = LegacyProtoKey::Create(
227 *other_serialization, InsecureSecretKeyAccess::Get());
228 ASSERT_THAT(other_key.status(), IsOk());
229
230 EXPECT_TRUE(*key != *other_key);
231 EXPECT_TRUE(*other_key != *key);
232 EXPECT_FALSE(*key == *other_key);
233 EXPECT_FALSE(*other_key == *key);
234 }
235
TEST_F(LegacyProtoKeyTest,IdRequirementNotEqual)236 TEST_F(LegacyProtoKeyTest, IdRequirementNotEqual) {
237 RestrictedData serialized_key =
238 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
239
240 util::StatusOr<ProtoKeySerialization> serialization =
241 ProtoKeySerialization::Create("type_url", serialized_key,
242 KeyData::SYMMETRIC, OutputPrefixType::TINK,
243 /*id_requirement=*/12345);
244 ASSERT_THAT(serialization.status(), IsOk());
245
246 util::StatusOr<ProtoKeySerialization> other_serialization =
247 ProtoKeySerialization::Create("type_url", serialized_key,
248 KeyData::SYMMETRIC, OutputPrefixType::TINK,
249 /*id_requirement=*/6789);
250 ASSERT_THAT(other_serialization.status(), IsOk());
251
252 util::StatusOr<LegacyProtoKey> key =
253 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
254 ASSERT_THAT(key.status(), IsOk());
255
256 util::StatusOr<LegacyProtoKey> other_key = LegacyProtoKey::Create(
257 *other_serialization, InsecureSecretKeyAccess::Get());
258 ASSERT_THAT(other_key.status(), IsOk());
259
260 EXPECT_TRUE(*key != *other_key);
261 EXPECT_TRUE(*other_key != *key);
262 EXPECT_FALSE(*key == *other_key);
263 EXPECT_FALSE(*other_key == *key);
264 }
265
266 using AllOutputPrefixTypesTest =
267 TestWithParam<std::tuple<OutputPrefixType, absl::optional<int>>>;
268
269 INSTANTIATE_TEST_SUITE_P(
270 AllOutputPrefixTypesTestSuite, AllOutputPrefixTypesTest,
271 Values(std::make_tuple(OutputPrefixType::RAW, absl::nullopt),
272 std::make_tuple(OutputPrefixType::TINK, 123),
273 std::make_tuple(OutputPrefixType::CRUNCHY, 456),
274 std::make_tuple(OutputPrefixType::LEGACY, 789)));
275
TEST_P(AllOutputPrefixTypesTest,GetIdRequirement)276 TEST_P(AllOutputPrefixTypesTest, GetIdRequirement) {
277 OutputPrefixType output_prefix_type;
278 absl::optional<int> id_requirement;
279 std::tie(output_prefix_type, id_requirement) = GetParam();
280
281 RestrictedData serialized_key =
282 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
283 util::StatusOr<ProtoKeySerialization> serialization =
284 ProtoKeySerialization::Create("type_url", serialized_key,
285 KeyData::SYMMETRIC, output_prefix_type,
286 id_requirement);
287 ASSERT_THAT(serialization.status(), IsOk());
288
289 util::StatusOr<LegacyProtoKey> key =
290 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
291 ASSERT_THAT(key.status(), IsOk());
292
293 EXPECT_THAT(key->GetIdRequirement(), Eq(id_requirement));
294 }
295
296 using AllKeyMaterialTypesTest = TestWithParam<KeyData::KeyMaterialType>;
297
298 INSTANTIATE_TEST_SUITE_P(AllKeyMaterialTypesTestSuite, AllKeyMaterialTypesTest,
299 Values(KeyData::SYMMETRIC, KeyData::ASYMMETRIC_PRIVATE,
300 KeyData::ASYMMETRIC_PUBLIC, KeyData::REMOTE));
301
TEST_P(AllKeyMaterialTypesTest,CreateAndSerializationWithSecretAccessToken)302 TEST_P(AllKeyMaterialTypesTest, CreateAndSerializationWithSecretAccessToken) {
303 KeyData::KeyMaterialType key_material_type = GetParam();
304
305 RestrictedData serialized_key =
306 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
307
308 util::StatusOr<ProtoKeySerialization> serialization =
309 ProtoKeySerialization::Create("type_url", serialized_key,
310 key_material_type, OutputPrefixType::TINK,
311 /*id_requirement=*/12345);
312 ASSERT_THAT(serialization.status(), IsOk());
313
314 util::StatusOr<LegacyProtoKey> key =
315 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
316 ASSERT_THAT(key.status(), IsOk());
317
318 util::StatusOr<const ProtoKeySerialization*> key_serialization =
319 key->Serialization(InsecureSecretKeyAccess::Get());
320 ASSERT_THAT(key_serialization.status(), IsOk());
321 }
322
323 using SecretKeyMaterialTypesTest = TestWithParam<KeyData::KeyMaterialType>;
324
325 INSTANTIATE_TEST_SUITE_P(SecretKeyMaterialTypesTestSuite,
326 SecretKeyMaterialTypesTest,
327 Values(KeyData::SYMMETRIC,
328 KeyData::ASYMMETRIC_PRIVATE));
329
TEST_P(SecretKeyMaterialTypesTest,CreateWithoutSecretAccessToken)330 TEST_P(SecretKeyMaterialTypesTest, CreateWithoutSecretAccessToken) {
331 KeyData::KeyMaterialType key_material_type = GetParam();
332
333 RestrictedData serialized_key =
334 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
335
336 util::StatusOr<ProtoKeySerialization> serialization =
337 ProtoKeySerialization::Create("type_url", serialized_key,
338 key_material_type, OutputPrefixType::TINK,
339 /*id_requirement=*/12345);
340 ASSERT_THAT(serialization.status(), IsOk());
341
342 util::StatusOr<LegacyProtoKey> key =
343 LegacyProtoKey::Create(*serialization, /*token=*/absl::nullopt);
344 ASSERT_THAT(key.status(), StatusIs(absl::StatusCode::kPermissionDenied));
345 }
346
TEST_P(SecretKeyMaterialTypesTest,SerializationWithoutSecretAccessToken)347 TEST_P(SecretKeyMaterialTypesTest, SerializationWithoutSecretAccessToken) {
348 KeyData::KeyMaterialType key_material_type = GetParam();
349
350 RestrictedData serialized_key =
351 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
352
353 util::StatusOr<ProtoKeySerialization> serialization =
354 ProtoKeySerialization::Create("type_url", serialized_key,
355 key_material_type, OutputPrefixType::TINK,
356 /*id_requirement=*/12345);
357 ASSERT_THAT(serialization.status(), IsOk());
358
359 // Must use token for key creation.
360 util::StatusOr<LegacyProtoKey> key =
361 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
362 ASSERT_THAT(key.status(), IsOk());
363
364 util::StatusOr<const ProtoKeySerialization*> key_serialization =
365 key->Serialization(/*token=*/absl::nullopt);
366 ASSERT_THAT(key_serialization.status(),
367 StatusIs(absl::StatusCode::kPermissionDenied));
368 }
369
370 using NonSecretKeyMaterialTypesTest = TestWithParam<KeyData::KeyMaterialType>;
371
372 INSTANTIATE_TEST_SUITE_P(NonSecretKeyMaterialTypesTestSuite,
373 NonSecretKeyMaterialTypesTest,
374 Values(KeyData::ASYMMETRIC_PUBLIC, KeyData::REMOTE));
375
TEST_P(NonSecretKeyMaterialTypesTest,CreateWithoutSecretAccessToken)376 TEST_P(NonSecretKeyMaterialTypesTest, CreateWithoutSecretAccessToken) {
377 KeyData::KeyMaterialType key_material_type = GetParam();
378
379 RestrictedData serialized_key =
380 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
381
382 util::StatusOr<ProtoKeySerialization> serialization =
383 ProtoKeySerialization::Create("type_url", serialized_key,
384 key_material_type, OutputPrefixType::TINK,
385 /*id_requirement=*/12345);
386 ASSERT_THAT(serialization.status(), IsOk());
387
388 util::StatusOr<LegacyProtoKey> key =
389 LegacyProtoKey::Create(*serialization, /*token=*/absl::nullopt);
390 ASSERT_THAT(key.status(), IsOk());
391 }
392
TEST_P(NonSecretKeyMaterialTypesTest,SerializationWithoutSecretAccessToken)393 TEST_P(NonSecretKeyMaterialTypesTest, SerializationWithoutSecretAccessToken) {
394 KeyData::KeyMaterialType key_material_type = GetParam();
395
396 RestrictedData serialized_key =
397 RestrictedData("serialized_key", InsecureSecretKeyAccess::Get());
398
399 util::StatusOr<ProtoKeySerialization> serialization =
400 ProtoKeySerialization::Create("type_url", serialized_key,
401 key_material_type, OutputPrefixType::TINK,
402 /*id_requirement=*/12345);
403 ASSERT_THAT(serialization.status(), IsOk());
404
405 // Must use token for key creation.
406 util::StatusOr<LegacyProtoKey> key =
407 LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get());
408 ASSERT_THAT(key.status(), IsOk());
409
410 util::StatusOr<const ProtoKeySerialization*> key_serialization =
411 key->Serialization(/*token=*/absl::nullopt);
412 ASSERT_THAT(key_serialization.status(), IsOk());
413 }
414
415 } // namespace internal
416 } // namespace tink
417 } // namespace crypto
418