xref: /aosp_15_r20/external/tink/cc/mac/hmac_key_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2023 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/mac/hmac_key.h"
18 
19 #include <memory>
20 #include <string>
21 #include <tuple>
22 #include <utility>
23 
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 #include "absl/types/optional.h"
27 #include "tink/mac/hmac_parameters.h"
28 #include "tink/partial_key_access.h"
29 #include "tink/restricted_data.h"
30 #include "tink/util/statusor.h"
31 #include "tink/util/test_matchers.h"
32 
33 namespace crypto {
34 namespace tink {
35 namespace {
36 
37 using ::crypto::tink::test::IsOk;
38 using ::crypto::tink::test::StatusIs;
39 using ::testing::Combine;
40 using ::testing::Eq;
41 using ::testing::Range;
42 using ::testing::TestWithParam;
43 using ::testing::Values;
44 
45 struct TestCase {
46   HmacParameters::Variant variant;
47   absl::optional<int> id_requirement;
48   std::string output_prefix;
49 };
50 
51 using HmacKeyTest =
52     TestWithParam<std::tuple<int, int, HmacParameters::HashType, TestCase>>;
53 
54 INSTANTIATE_TEST_SUITE_P(
55     HmacKeyTestSuite, HmacKeyTest,
56     Combine(Values(16, 32), Range(10, 20),
57             Values(HmacParameters::HashType::kSha1,
58                    HmacParameters::HashType::kSha224,
59                    HmacParameters::HashType::kSha256,
60                    HmacParameters::HashType::kSha384,
61                    HmacParameters::HashType::kSha512),
62             Values(TestCase{HmacParameters::Variant::kTink, 0x02030400,
63                             std::string("\x01\x02\x03\x04\x00", 5)},
64                    TestCase{HmacParameters::Variant::kCrunchy, 0x01030005,
65                             std::string("\x00\x01\x03\x00\x05", 5)},
66                    TestCase{HmacParameters::Variant::kLegacy, 0x01020304,
67                             std::string("\x00\x01\x02\x03\x04", 5)},
68                    TestCase{HmacParameters::Variant::kNoPrefix, absl::nullopt,
69                             ""})));
70 
TEST_P(HmacKeyTest,CreateSucceeds)71 TEST_P(HmacKeyTest, CreateSucceeds) {
72   int key_size;
73   int cryptographic_tag_size;
74   HmacParameters::HashType hash_type;
75   TestCase test_case;
76   std::tie(key_size, cryptographic_tag_size, hash_type, test_case) = GetParam();
77 
78   util::StatusOr<HmacParameters> params = HmacParameters::Create(
79       key_size, cryptographic_tag_size, hash_type, test_case.variant);
80   ASSERT_THAT(params, IsOk());
81 
82   RestrictedData secret = RestrictedData(key_size);
83   util::StatusOr<HmacKey> key = HmacKey::Create(
84       *params, secret, test_case.id_requirement, GetPartialKeyAccess());
85   ASSERT_THAT(key.status(), IsOk());
86 
87   EXPECT_THAT(key->GetParameters(), Eq(*params));
88   EXPECT_THAT(key->GetIdRequirement(), Eq(test_case.id_requirement));
89   EXPECT_THAT(key->GetOutputPrefix(), Eq(test_case.output_prefix));
90 }
91 
TEST(HmacKeyTest,CreateKeyWithMismatchedKeySizeFails)92 TEST(HmacKeyTest, CreateKeyWithMismatchedKeySizeFails) {
93   // Key size parameter is 32 bytes.
94   util::StatusOr<HmacParameters> params = HmacParameters::Create(
95       /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
96       HmacParameters::HashType::kSha256, HmacParameters::Variant::kTink);
97   ASSERT_THAT(params, IsOk());
98 
99   // Key material is 16 bytes (another valid key length).
100   RestrictedData mismatched_secret = RestrictedData(/*num_random_bytes=*/16);
101 
102   EXPECT_THAT(HmacKey::Create(*params, mismatched_secret,
103                               /*id_requirement=*/123, GetPartialKeyAccess())
104                   .status(),
105               StatusIs(absl::StatusCode::kInvalidArgument));
106 }
107 
TEST(HmacKeyTest,CreateKeyWithWrongIdRequirementFails)108 TEST(HmacKeyTest, CreateKeyWithWrongIdRequirementFails) {
109   util::StatusOr<HmacParameters> no_prefix_params = HmacParameters::Create(
110       /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
111       HmacParameters::HashType::kSha512, HmacParameters::Variant::kNoPrefix);
112   ASSERT_THAT(no_prefix_params, IsOk());
113 
114   util::StatusOr<HmacParameters> tink_params = HmacParameters::Create(
115       /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
116       HmacParameters::HashType::kSha512, HmacParameters::Variant::kTink);
117   ASSERT_THAT(tink_params, IsOk());
118 
119   RestrictedData secret = RestrictedData(/*num_random_bytes=*/32);
120 
121   EXPECT_THAT(HmacKey::Create(*no_prefix_params, secret,
122                               /*id_requirement=*/123, GetPartialKeyAccess())
123                   .status(),
124               StatusIs(absl::StatusCode::kInvalidArgument));
125   EXPECT_THAT(
126       HmacKey::Create(*tink_params, secret,
127                       /*id_requirement=*/absl::nullopt, GetPartialKeyAccess())
128           .status(),
129       StatusIs(absl::StatusCode::kInvalidArgument));
130 }
131 
TEST_P(HmacKeyTest,GetKeyBytes)132 TEST_P(HmacKeyTest, GetKeyBytes) {
133   int key_size;
134   int cryptographic_tag_size;
135   HmacParameters::HashType hash_type;
136   TestCase test_case;
137   std::tie(key_size, cryptographic_tag_size, hash_type, test_case) = GetParam();
138 
139   util::StatusOr<HmacParameters> params = HmacParameters::Create(
140       key_size, cryptographic_tag_size, hash_type, test_case.variant);
141   ASSERT_THAT(params, IsOk());
142 
143   RestrictedData secret = RestrictedData(key_size);
144 
145   util::StatusOr<HmacKey> key = HmacKey::Create(
146       *params, secret, test_case.id_requirement, GetPartialKeyAccess());
147   ASSERT_THAT(key.status(), IsOk());
148 
149   EXPECT_THAT(key->GetKeyBytes(GetPartialKeyAccess()), Eq(secret));
150 }
151 
TEST_P(HmacKeyTest,KeyEquals)152 TEST_P(HmacKeyTest, KeyEquals) {
153   int key_size;
154   int cryptographic_tag_size;
155   HmacParameters::HashType hash_type;
156   TestCase test_case;
157   std::tie(key_size, cryptographic_tag_size, hash_type, test_case) = GetParam();
158 
159   util::StatusOr<HmacParameters> params = HmacParameters::Create(
160       key_size, cryptographic_tag_size, hash_type, test_case.variant);
161   ASSERT_THAT(params, IsOk());
162 
163   RestrictedData secret = RestrictedData(key_size);
164   util::StatusOr<HmacKey> key = HmacKey::Create(
165       *params, secret, test_case.id_requirement, GetPartialKeyAccess());
166   ASSERT_THAT(key, IsOk());
167 
168   util::StatusOr<HmacKey> other_key = HmacKey::Create(
169       *params, secret, test_case.id_requirement, GetPartialKeyAccess());
170   ASSERT_THAT(other_key, IsOk());
171 
172   EXPECT_TRUE(*key == *other_key);
173   EXPECT_TRUE(*other_key == *key);
174   EXPECT_FALSE(*key != *other_key);
175   EXPECT_FALSE(*other_key != *key);
176 }
177 
TEST(HmacKeyTest,DifferentFormatNotEqual)178 TEST(HmacKeyTest, DifferentFormatNotEqual) {
179   util::StatusOr<HmacParameters> legacy_params = HmacParameters::Create(
180       /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
181       HmacParameters::HashType::kSha256, HmacParameters::Variant::kLegacy);
182   ASSERT_THAT(legacy_params, IsOk());
183 
184   util::StatusOr<HmacParameters> tink_params = HmacParameters::Create(
185       /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
186       HmacParameters::HashType::kSha256, HmacParameters::Variant::kTink);
187   ASSERT_THAT(tink_params, IsOk());
188 
189   RestrictedData secret = RestrictedData(/*num_random_bytes=*/32);
190 
191   util::StatusOr<HmacKey> key =
192       HmacKey::Create(*legacy_params, secret, /*id_requirement=*/0x01020304,
193                       GetPartialKeyAccess());
194   ASSERT_THAT(key.status(), IsOk());
195 
196   util::StatusOr<HmacKey> other_key =
197       HmacKey::Create(*tink_params, secret, /*id_requirement=*/0x01020304,
198                       GetPartialKeyAccess());
199   ASSERT_THAT(other_key.status(), IsOk());
200 
201   EXPECT_TRUE(*key != *other_key);
202   EXPECT_TRUE(*other_key != *key);
203   EXPECT_FALSE(*key == *other_key);
204   EXPECT_FALSE(*other_key == *key);
205 }
206 
TEST(HmacKeyTest,DifferentSecretDataNotEqual)207 TEST(HmacKeyTest, DifferentSecretDataNotEqual) {
208   util::StatusOr<HmacParameters> params = HmacParameters::Create(
209       /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
210       HmacParameters::HashType::kSha384, HmacParameters::Variant::kTink);
211   ASSERT_THAT(params, IsOk());
212 
213   RestrictedData secret1 = RestrictedData(/*num_random_bytes=*/32);
214   RestrictedData secret2 = RestrictedData(/*num_random_bytes=*/32);
215 
216   util::StatusOr<HmacKey> key = HmacKey::Create(
217       *params, secret1, /*id_requirement=*/0x01020304, GetPartialKeyAccess());
218   ASSERT_THAT(key.status(), IsOk());
219 
220   util::StatusOr<HmacKey> other_key = HmacKey::Create(
221       *params, secret2, /*id_requirement=*/0x01020304, GetPartialKeyAccess());
222   ASSERT_THAT(other_key.status(), IsOk());
223 
224   EXPECT_TRUE(*key != *other_key);
225   EXPECT_TRUE(*other_key != *key);
226   EXPECT_FALSE(*key == *other_key);
227   EXPECT_FALSE(*other_key == *key);
228 }
229 
TEST(HmacKeyTest,DifferentIdRequirementNotEqual)230 TEST(HmacKeyTest, DifferentIdRequirementNotEqual) {
231   util::StatusOr<HmacParameters> params = HmacParameters::Create(
232       /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16,
233       HmacParameters::HashType::kSha224, HmacParameters::Variant::kTink);
234   ASSERT_THAT(params, IsOk());
235 
236   RestrictedData secret = RestrictedData(/*num_random_bytes=*/32);
237 
238   util::StatusOr<HmacKey> key = HmacKey::Create(
239       *params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess());
240   ASSERT_THAT(key.status(), IsOk());
241 
242   util::StatusOr<HmacKey> other_key = HmacKey::Create(
243       *params, secret, /*id_requirement=*/0x02030405, GetPartialKeyAccess());
244   ASSERT_THAT(other_key.status(), IsOk());
245 
246   EXPECT_TRUE(*key != *other_key);
247   EXPECT_TRUE(*other_key != *key);
248   EXPECT_FALSE(*key == *other_key);
249   EXPECT_FALSE(*other_key == *key);
250 }
251 
252 }  // namespace
253 }  // namespace tink
254 }  // namespace crypto
255