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