xref: /aosp_15_r20/external/tink/cc/mac/mac_config_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2017 Google Inc.
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/mac/mac_config.h"
18 
19 #include <list>
20 #include <memory>
21 #include <string>
22 #include <utility>
23 
24 #include "gtest/gtest.h"
25 #include "absl/status/status.h"
26 #include "tink/chunked_mac.h"
27 #include "tink/insecure_secret_key_access.h"
28 #include "tink/internal/fips_utils.h"
29 #include "tink/internal/mutable_serialization_registry.h"
30 #include "tink/internal/proto_key_serialization.h"
31 #include "tink/internal/proto_parameters_serialization.h"
32 #include "tink/keyset_handle.h"
33 #include "tink/mac.h"
34 #include "tink/mac/aes_cmac_key.h"
35 #include "tink/mac/aes_cmac_key_manager.h"
36 #include "tink/mac/aes_cmac_parameters.h"
37 #include "tink/mac/hmac_key.h"
38 #include "tink/mac/hmac_key_manager.h"
39 #include "tink/mac/hmac_parameters.h"
40 #include "tink/mac/mac_key_templates.h"
41 #include "tink/partial_key_access.h"
42 #include "tink/registry.h"
43 #include "tink/util/status.h"
44 #include "tink/util/test_matchers.h"
45 #include "tink/util/test_util.h"
46 #include "proto/common.pb.h"
47 #include "proto/tink.pb.h"
48 
49 namespace crypto {
50 namespace tink {
51 namespace {
52 
53 using ::crypto::tink::test::DummyMac;
54 using ::crypto::tink::test::IsOk;
55 using ::crypto::tink::test::StatusIs;
56 using ::google::crypto::tink::KeyData;
57 using ::google::crypto::tink::KeysetInfo;
58 using ::google::crypto::tink::KeyStatusType;
59 using ::google::crypto::tink::HashType;
60 using ::google::crypto::tink::KeyTemplate;
61 using ::google::crypto::tink::OutputPrefixType;
62 using ::testing::Values;
63 
64 class MacConfigTest : public ::testing::Test {
65  protected:
SetUp()66   void SetUp() override {
67     Registry::Reset();
68     internal::MutableSerializationRegistry::GlobalInstance().Reset();
69   }
70 };
71 
TEST_F(MacConfigTest,Basic)72 TEST_F(MacConfigTest, Basic) {
73   if (internal::IsFipsModeEnabled()) {
74     GTEST_SKIP() << "Not supported in FIPS-only mode";
75   }
76 
77   EXPECT_THAT(
78       Registry::get_key_manager<Mac>(HmacKeyManager().get_key_type()).status(),
79       StatusIs(absl::StatusCode::kNotFound));
80   EXPECT_THAT(
81       Registry::get_key_manager<ChunkedMac>(HmacKeyManager().get_key_type())
82           .status(),
83       StatusIs(absl::StatusCode::kNotFound));
84   EXPECT_THAT(Registry::get_key_manager<Mac>(AesCmacKeyManager().get_key_type())
85                   .status(),
86               StatusIs(absl::StatusCode::kNotFound));
87   EXPECT_THAT(
88       Registry::get_key_manager<ChunkedMac>(AesCmacKeyManager().get_key_type())
89           .status(),
90       StatusIs(absl::StatusCode::kNotFound));
91 
92   ASSERT_THAT(MacConfig::Register(), IsOk());
93 
94   EXPECT_THAT(
95       Registry::get_key_manager<Mac>(HmacKeyManager().get_key_type()).status(),
96       IsOk());
97   EXPECT_THAT(
98       Registry::get_key_manager<ChunkedMac>(HmacKeyManager().get_key_type())
99           .status(),
100       IsOk());
101   EXPECT_THAT(Registry::get_key_manager<Mac>(AesCmacKeyManager().get_key_type())
102                   .status(),
103               IsOk());
104   EXPECT_THAT(
105       Registry::get_key_manager<ChunkedMac>(AesCmacKeyManager().get_key_type())
106           .status(),
107       IsOk());
108 }
109 
110 // Tests that the MacWrapper has been properly registered and we can wrap
111 // primitives.
TEST_F(MacConfigTest,MacWrappersRegistered)112 TEST_F(MacConfigTest, MacWrappersRegistered) {
113   if (internal::IsFipsModeEnabled()) {
114     GTEST_SKIP() << "Not supported in FIPS-only mode";
115   }
116 
117   ASSERT_TRUE(MacConfig::Register().ok());
118 
119   KeysetInfo::KeyInfo key_info;
120   key_info.set_status(KeyStatusType::ENABLED);
121   key_info.set_key_id(1234);
122   key_info.set_output_prefix_type(OutputPrefixType::RAW);
123   auto primitive_set = absl::make_unique<PrimitiveSet<Mac>>();
124   ASSERT_TRUE(
125       primitive_set
126           ->set_primary(
127               primitive_set
128                   ->AddPrimitive(absl::make_unique<DummyMac>("dummy"), key_info)
129                   .value())
130           .ok());
131 
132   auto primitive_result = Registry::Wrap(std::move(primitive_set));
133 
134   ASSERT_TRUE(primitive_result.ok()) << primitive_result.status();
135   auto mac_result = primitive_result.value()->ComputeMac("verified text");
136   ASSERT_TRUE(mac_result.ok());
137 
138   EXPECT_TRUE(
139       DummyMac("dummy").VerifyMac(mac_result.value(), "verified text").ok());
140   EXPECT_FALSE(
141       DummyMac("dummy").VerifyMac(mac_result.value(), "faked text").ok());
142 }
143 
TEST_F(MacConfigTest,AesCmacProtoParamsSerializationRegistered)144 TEST_F(MacConfigTest, AesCmacProtoParamsSerializationRegistered) {
145   if (internal::IsFipsModeEnabled()) {
146     GTEST_SKIP() << "Not supported in FIPS-only mode";
147   }
148 
149   util::StatusOr<internal::ProtoParametersSerialization>
150       proto_params_serialization =
151           internal::ProtoParametersSerialization::Create(
152               MacKeyTemplates::AesCmac());
153   ASSERT_THAT(proto_params_serialization, IsOk());
154 
155   util::StatusOr<std::unique_ptr<Parameters>> parsed_params =
156       internal::MutableSerializationRegistry::GlobalInstance().ParseParameters(
157           *proto_params_serialization);
158   ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound));
159 
160   util::StatusOr<AesCmacParameters> params = AesCmacParameters::Create(
161       /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
162       AesCmacParameters::Variant::kTink);
163   ASSERT_THAT(params, IsOk());
164 
165   util::StatusOr<std::unique_ptr<Serialization>> serialized_params =
166       internal::MutableSerializationRegistry::GlobalInstance()
167           .SerializeParameters<internal::ProtoParametersSerialization>(*params);
168   ASSERT_THAT(serialized_params.status(),
169               StatusIs(absl::StatusCode::kNotFound));
170 
171   ASSERT_THAT(MacConfig::Register(), IsOk());
172 
173   util::StatusOr<std::unique_ptr<Parameters>> parsed_params2 =
174       internal::MutableSerializationRegistry::GlobalInstance().ParseParameters(
175           *proto_params_serialization);
176   ASSERT_THAT(parsed_params2, IsOk());
177 
178   util::StatusOr<std::unique_ptr<Serialization>> serialized_params2 =
179       internal::MutableSerializationRegistry::GlobalInstance()
180           .SerializeParameters<internal::ProtoParametersSerialization>(*params);
181   ASSERT_THAT(serialized_params2, IsOk());
182 }
183 
TEST_F(MacConfigTest,AesCmacProtoKeySerializationRegistered)184 TEST_F(MacConfigTest, AesCmacProtoKeySerializationRegistered) {
185   if (internal::IsFipsModeEnabled()) {
186     GTEST_SKIP() << "Not supported in FIPS-only mode";
187   }
188 
189   google::crypto::tink::AesCmacKey key_proto;
190   key_proto.set_version(0);
191   key_proto.set_key_value(subtle::Random::GetRandomBytes(32));
192   key_proto.mutable_params()->set_tag_size(16);
193 
194   util::StatusOr<internal::ProtoKeySerialization> proto_key_serialization =
195       internal::ProtoKeySerialization::Create(
196           "type.googleapis.com/google.crypto.tink.AesCmacKey",
197           RestrictedData(key_proto.SerializeAsString(),
198                          InsecureSecretKeyAccess::Get()),
199           KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123);
200   ASSERT_THAT(proto_key_serialization, IsOk());
201 
202   util::StatusOr<std::unique_ptr<Key>> parsed_key =
203       internal::MutableSerializationRegistry::GlobalInstance().ParseKey(
204           *proto_key_serialization, InsecureSecretKeyAccess::Get());
205   ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound));
206 
207   util::StatusOr<AesCmacParameters> params = AesCmacParameters::Create(
208       /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
209       AesCmacParameters::Variant::kTink);
210   ASSERT_THAT(params, IsOk());
211 
212   util::StatusOr<AesCmacKey> key =
213       AesCmacKey::Create(*params,
214                          RestrictedData(subtle::Random::GetRandomBytes(32),
215                                         InsecureSecretKeyAccess::Get()),
216                          /*id_requirement=*/123, GetPartialKeyAccess());
217   ASSERT_THAT(key, IsOk());
218 
219   util::StatusOr<std::unique_ptr<Serialization>> serialized_key =
220       internal::MutableSerializationRegistry::GlobalInstance()
221           .SerializeKey<internal::ProtoKeySerialization>(
222               *key, InsecureSecretKeyAccess::Get());
223   ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound));
224 
225   ASSERT_THAT(MacConfig::Register(), IsOk());
226 
227   util::StatusOr<std::unique_ptr<Key>> parsed_key2 =
228       internal::MutableSerializationRegistry::GlobalInstance().ParseKey(
229           *proto_key_serialization, InsecureSecretKeyAccess::Get());
230   ASSERT_THAT(parsed_key2, IsOk());
231 
232   util::StatusOr<std::unique_ptr<Serialization>> serialized_key2 =
233       internal::MutableSerializationRegistry::GlobalInstance()
234           .SerializeKey<internal::ProtoKeySerialization>(
235               *key, InsecureSecretKeyAccess::Get());
236   ASSERT_THAT(serialized_key2, IsOk());
237 }
238 
TEST_F(MacConfigTest,HmacProtoParamsSerializationRegistered)239 TEST_F(MacConfigTest, HmacProtoParamsSerializationRegistered) {
240   if (internal::IsFipsModeEnabled()) {
241     GTEST_SKIP() << "Not supported in FIPS-only mode";
242   }
243 
244   util::StatusOr<internal::ProtoParametersSerialization>
245       proto_params_serialization =
246           internal::ProtoParametersSerialization::Create(
247               MacKeyTemplates::HmacSha256());
248   ASSERT_THAT(proto_params_serialization, IsOk());
249 
250   util::StatusOr<std::unique_ptr<Parameters>> parsed_params =
251       internal::MutableSerializationRegistry::GlobalInstance().ParseParameters(
252           *proto_params_serialization);
253   ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound));
254 
255   util::StatusOr<HmacParameters> parameters = HmacParameters::Create(
256       /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/32,
257       HmacParameters::HashType::kSha256, HmacParameters::Variant::kTink);
258   ASSERT_THAT(parameters, IsOk());
259 
260   util::StatusOr<std::unique_ptr<Serialization>> serialized_parameters =
261       internal::MutableSerializationRegistry::GlobalInstance()
262           .SerializeParameters<internal::ProtoParametersSerialization>(
263               *parameters);
264   ASSERT_THAT(serialized_parameters.status(),
265               StatusIs(absl::StatusCode::kNotFound));
266 
267   // Register parser and serializer.
268   ASSERT_THAT(MacConfig::Register(), IsOk());
269 
270   util::StatusOr<std::unique_ptr<Parameters>> parsed_params2 =
271       internal::MutableSerializationRegistry::GlobalInstance().ParseParameters(
272           *proto_params_serialization);
273   ASSERT_THAT(parsed_params2, IsOk());
274 
275   util::StatusOr<std::unique_ptr<Serialization>> serialized_params2 =
276       internal::MutableSerializationRegistry::GlobalInstance()
277           .SerializeParameters<internal::ProtoParametersSerialization>(
278               *parameters);
279   ASSERT_THAT(serialized_params2, IsOk());
280 }
281 
TEST_F(MacConfigTest,HmacProtoKeySerializationRegistered)282 TEST_F(MacConfigTest, HmacProtoKeySerializationRegistered) {
283   if (internal::IsFipsModeEnabled()) {
284     GTEST_SKIP() << "Not supported in FIPS-only mode";
285   }
286 
287   google::crypto::tink::HmacKey key_proto;
288   key_proto.set_version(0);
289   key_proto.set_key_value(subtle::Random::GetRandomBytes(32));
290   key_proto.mutable_params()->set_tag_size(32);
291   key_proto.mutable_params()->set_hash(HashType::SHA256);
292 
293   util::StatusOr<internal::ProtoKeySerialization> proto_key_serialization =
294       internal::ProtoKeySerialization::Create(
295           "type.googleapis.com/google.crypto.tink.HmacKey",
296           RestrictedData(key_proto.SerializeAsString(),
297                          InsecureSecretKeyAccess::Get()),
298           KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123);
299   ASSERT_THAT(proto_key_serialization, IsOk());
300 
301   util::StatusOr<std::unique_ptr<Key>> parsed_key =
302       internal::MutableSerializationRegistry::GlobalInstance().ParseKey(
303           *proto_key_serialization, InsecureSecretKeyAccess::Get());
304   ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound));
305 
306   util::StatusOr<HmacParameters> parameters = HmacParameters::Create(
307       /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/32,
308       HmacParameters::HashType::kSha256, HmacParameters::Variant::kTink);
309   ASSERT_THAT(parameters, IsOk());
310 
311   util::StatusOr<HmacKey> key =
312       HmacKey::Create(*parameters,
313                       RestrictedData(subtle::Random::GetRandomBytes(32),
314                                      InsecureSecretKeyAccess::Get()),
315                       /*id_requirement=*/123, GetPartialKeyAccess());
316   ASSERT_THAT(key, IsOk());
317 
318   util::StatusOr<std::unique_ptr<Serialization>> serialized_key =
319       internal::MutableSerializationRegistry::GlobalInstance()
320           .SerializeKey<internal::ProtoKeySerialization>(
321               *key, InsecureSecretKeyAccess::Get());
322   ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound));
323 
324   // Register parser and serializer.
325   ASSERT_THAT(MacConfig::Register(), IsOk());
326 
327   util::StatusOr<std::unique_ptr<Key>> parsed_key2 =
328       internal::MutableSerializationRegistry::GlobalInstance().ParseKey(
329           *proto_key_serialization, InsecureSecretKeyAccess::Get());
330   ASSERT_THAT(parsed_key2, IsOk());
331 
332   util::StatusOr<std::unique_ptr<Serialization>> serialized_key2 =
333       internal::MutableSerializationRegistry::GlobalInstance()
334           .SerializeKey<internal::ProtoKeySerialization>(
335               *key, InsecureSecretKeyAccess::Get());
336   ASSERT_THAT(serialized_key2, IsOk());
337 }
338 
339 class ChunkedMacConfigTest : public ::testing::TestWithParam<KeyTemplate> {
340  protected:
SetUp()341   void SetUp() override { Registry::Reset(); }
342 };
343 
344 INSTANTIATE_TEST_SUITE_P(ChunkedMacConfigTestSuite, ChunkedMacConfigTest,
345                          Values(MacKeyTemplates::AesCmac(),
346                                 MacKeyTemplates::HmacSha256()));
347 
348 // Tests that the ChunkedMacWrapper has been properly registered and we can get
349 // primitives.
TEST_P(ChunkedMacConfigTest,ChunkedMacWrappersRegistered)350 TEST_P(ChunkedMacConfigTest, ChunkedMacWrappersRegistered) {
351   if (internal::IsFipsModeEnabled()) {
352     GTEST_SKIP() << "Not supported in FIPS-only mode";
353   }
354 
355   ASSERT_THAT(MacConfig::Register(), IsOk());
356 
357   KeyTemplate key_template = GetParam();
358   util::StatusOr<std::unique_ptr<KeysetHandle>> key =
359       KeysetHandle::GenerateNew(key_template);
360   ASSERT_THAT(key, IsOk());
361 
362   util::StatusOr<std::unique_ptr<ChunkedMac>> chunked_mac =
363       (*key)->GetPrimitive<ChunkedMac>();
364   ASSERT_THAT(chunked_mac, IsOk());
365 
366   util::StatusOr<std::unique_ptr<ChunkedMacComputation>> computation =
367       (*chunked_mac)->CreateComputation();
368   ASSERT_THAT(computation, IsOk());
369   ASSERT_THAT((*computation)->Update("verified text"), IsOk());
370   util::StatusOr<std::string> tag = (*computation)->ComputeMac();
371   ASSERT_THAT(tag, IsOk());
372 
373   util::StatusOr<std::unique_ptr<ChunkedMacVerification>> verification =
374       (*chunked_mac)->CreateVerification(*tag);
375   ASSERT_THAT(verification, IsOk());
376   ASSERT_THAT((*verification)->Update("verified text"), IsOk());
377 
378   EXPECT_THAT((*verification)->VerifyMac(), IsOk());
379 }
380 
381 // FIPS-only mode tests
TEST_F(MacConfigTest,RegisterNonFipsTemplates)382 TEST_F(MacConfigTest, RegisterNonFipsTemplates) {
383   if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) {
384     GTEST_SKIP() << "Only supported in FIPS-only mode";
385   }
386 
387   EXPECT_THAT(MacConfig::Register(), IsOk());
388 
389   std::list<google::crypto::tink::KeyTemplate> non_fips_key_templates;
390   non_fips_key_templates.push_back(MacKeyTemplates::AesCmac());
391 
392   for (auto key_template : non_fips_key_templates) {
393     EXPECT_THAT(KeysetHandle::GenerateNew(key_template).status(),
394                 StatusIs(absl::StatusCode::kNotFound));
395   }
396 }
397 
TEST_F(MacConfigTest,RegisterFipsValidTemplates)398 TEST_F(MacConfigTest, RegisterFipsValidTemplates) {
399   if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) {
400     GTEST_SKIP() << "Only supported in FIPS-only mode";
401   }
402 
403   EXPECT_THAT(MacConfig::Register(), IsOk());
404 
405   std::list<google::crypto::tink::KeyTemplate> fips_key_templates;
406   fips_key_templates.push_back(MacKeyTemplates::HmacSha256());
407   fips_key_templates.push_back(MacKeyTemplates::HmacSha256HalfSizeTag());
408   fips_key_templates.push_back(MacKeyTemplates::HmacSha512());
409   fips_key_templates.push_back(MacKeyTemplates::HmacSha512HalfSizeTag());
410 
411   for (auto key_template : fips_key_templates) {
412     EXPECT_THAT(KeysetHandle::GenerateNew(key_template), IsOk());
413   }
414 }
415 
416 }  // namespace
417 }  // namespace tink
418 }  // namespace crypto
419