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