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