1 // Copyright 2019 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/keyderivation/internal/prf_based_deriver.h"
18
19 #include <memory>
20
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include "absl/status/status.h"
24 #include "tink/aead/aead_key_templates.h"
25 #include "tink/aead/aes_gcm_key_manager.h"
26 #include "tink/cleartext_keyset_handle.h"
27 #include "tink/prf/hkdf_prf_key_manager.h"
28 #include "tink/util/test_matchers.h"
29 #include "tink/util/test_util.h"
30 #include "proto/aes_gcm.pb.h"
31
32 namespace crypto {
33 namespace tink {
34 namespace internal {
35 namespace {
36
37 using ::crypto::tink::test::IsOk;
38 using ::crypto::tink::test::StatusIs;
39 using ::google::crypto::tink::AesGcmKey;
40 using ::google::crypto::tink::HashType;
41 using ::google::crypto::tink::HkdfPrfKey;
42 using ::google::crypto::tink::KeyData;
43 using ::google::crypto::tink::Keyset;
44 using ::google::crypto::tink::KeyStatusType;
45 using ::google::crypto::tink::KeyTemplate;
46 using ::google::crypto::tink::OutputPrefixType;
47 using ::testing::Eq;
48 using ::testing::Ne;
49 using ::testing::SizeIs;
50
51 class PrfBasedDeriverTest : public ::testing::Test {
52 public:
SetUpTestSuite()53 static void SetUpTestSuite() {
54 ASSERT_THAT(Registry::RegisterKeyTypeManager(
55 absl::make_unique<AesGcmKeyManager>(), true),
56 IsOk());
57 ASSERT_THAT(Registry::RegisterKeyTypeManager(
58 absl::make_unique<HkdfPrfKeyManager>(), true),
59 IsOk());
60 }
61 };
62
TEST_F(PrfBasedDeriverTest,New)63 TEST_F(PrfBasedDeriverTest, New) {
64 HkdfPrfKey prf_key;
65 prf_key.set_version(0);
66 prf_key.mutable_params()->set_hash(HashType::SHA256);
67 prf_key.mutable_params()->set_salt("");
68 prf_key.set_key_value("0123456789abcdef0123456789abcdef");
69
70 EXPECT_THAT(PrfBasedDeriver::New(test::AsKeyData(prf_key, KeyData::SYMMETRIC),
71 AeadKeyTemplates::Aes128Gcm()),
72 IsOk());
73 }
74
TEST_F(PrfBasedDeriverTest,NewWithInvalidPrfKey)75 TEST_F(PrfBasedDeriverTest, NewWithInvalidPrfKey) {
76 HkdfPrfKey prf_key;
77 prf_key.set_version(0);
78 prf_key.mutable_params()->set_hash(HashType::UNKNOWN_HASH);
79 prf_key.mutable_params()->set_salt("");
80 prf_key.set_key_value("0123456789abcdef0123456789abcdef");
81
82 EXPECT_THAT(PrfBasedDeriver::New(test::AsKeyData(prf_key, KeyData::SYMMETRIC),
83 AeadKeyTemplates::Aes128Gcm())
84 .status(),
85 StatusIs(absl::StatusCode::kInvalidArgument));
86 }
87
TEST_F(PrfBasedDeriverTest,NewWithInvalidDerivedKeyTemplate)88 TEST_F(PrfBasedDeriverTest, NewWithInvalidDerivedKeyTemplate) {
89 HkdfPrfKey prf_key;
90 prf_key.set_version(0);
91 prf_key.mutable_params()->set_hash(HashType::SHA256);
92 prf_key.mutable_params()->set_salt("");
93 prf_key.set_key_value("0123456789abcdef0123456789abcdef");
94
95 KeyTemplate derived_template;
96 derived_template.set_type_url("some non-existent type url");
97 EXPECT_THAT(PrfBasedDeriver::New(test::AsKeyData(prf_key, KeyData::SYMMETRIC),
98 derived_template)
99 .status(),
100 StatusIs(absl::StatusCode::kNotFound));
101 }
102
103 // Test vector from https://tools.ietf.org/html/rfc5869#appendix-A.2.
TEST_F(PrfBasedDeriverTest,DeriveKeyset)104 TEST_F(PrfBasedDeriverTest, DeriveKeyset) {
105 HkdfPrfKey prf_key;
106 prf_key.set_version(0);
107 prf_key.mutable_params()->set_hash(HashType::SHA256);
108 prf_key.mutable_params()->set_salt(
109 test::HexDecodeOrDie("606162636465666768696a6b6c6d6e6f"
110 "707172737475767778797a7b7c7d7e7f"
111 "808182838485868788898a8b8c8d8e8f"
112 "909192939495969798999a9b9c9d9e9f"
113 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"));
114 prf_key.set_key_value(
115 test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f"
116 "101112131415161718191a1b1c1d1e1f"
117 "202122232425262728292a2b2c2d2e2f"
118 "303132333435363738393a3b3c3d3e3f"
119 "404142434445464748494a4b4c4d4e4f"));
120
121 util::StatusOr<std::unique_ptr<KeysetDeriver>> deriver =
122 PrfBasedDeriver::New(test::AsKeyData(prf_key, KeyData::SYMMETRIC),
123 AeadKeyTemplates::Aes256Gcm());
124 ASSERT_THAT(deriver, IsOk());
125
126 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
127 (*deriver)->DeriveKeyset(
128 test::HexDecodeOrDie("b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
129 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
130 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
131 "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
132 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"));
133 ASSERT_THAT(handle, IsOk());
134
135 Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle);
136 ASSERT_THAT(keyset.key(), SizeIs(1));
137 EXPECT_THAT(keyset.key(0).key_data().type_url(),
138 Eq(AesGcmKeyManager().get_key_type()));
139 EXPECT_THAT(keyset.key(0).key_data().key_material_type(),
140 Eq(AesGcmKeyManager().key_material_type()));
141
142 AesGcmKey derived_key;
143 ASSERT_TRUE(derived_key.ParseFromString(keyset.key(0).key_data().value()));
144 EXPECT_THAT(derived_key.version(), Eq(AesGcmKeyManager().get_version()));
145 // The derived key value is the first 32 bytes of the test vector's OKM field.
146 EXPECT_THAT(test::HexEncode(derived_key.key_value()),
147 Eq("b11e398dc80327a1c8e7f78c596a4934"
148 "4f012eda2d4efad8a050cc4c19afa97c"));
149 }
150
TEST_F(PrfBasedDeriverTest,DeriveKeysetHoldsPlaceholderValues)151 TEST_F(PrfBasedDeriverTest, DeriveKeysetHoldsPlaceholderValues) {
152 HkdfPrfKey prf_key;
153 prf_key.set_version(0);
154 prf_key.mutable_params()->set_hash(HashType::SHA256);
155 prf_key.mutable_params()->set_salt("");
156 prf_key.set_key_value("0123456789abcdef0123456789abcdef");
157
158 util::StatusOr<std::unique_ptr<KeysetDeriver>> deriver =
159 PrfBasedDeriver::New(test::AsKeyData(prf_key, KeyData::SYMMETRIC),
160 AeadKeyTemplates::Aes128Gcm());
161 ASSERT_THAT(deriver, IsOk());
162
163 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
164 (*deriver)->DeriveKeyset("salt");
165 ASSERT_THAT(handle, IsOk());
166
167 Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle);
168 EXPECT_THAT(keyset.primary_key_id(), Eq(0));
169 ASSERT_THAT(keyset.key(), SizeIs(1));
170 EXPECT_THAT(keyset.key(0).status(), Eq(KeyStatusType::UNKNOWN_STATUS));
171 EXPECT_THAT(keyset.key(0).key_id(), Eq(0));
172 EXPECT_THAT(keyset.key(0).output_prefix_type(),
173 Eq(OutputPrefixType::UNKNOWN_PREFIX));
174 }
175
TEST_F(PrfBasedDeriverTest,DeriveKeysetWithDifferentPrfKeys)176 TEST_F(PrfBasedDeriverTest, DeriveKeysetWithDifferentPrfKeys) {
177 HkdfPrfKey prf_key;
178 prf_key.set_version(0);
179 prf_key.mutable_params()->set_hash(HashType::SHA512);
180 prf_key.mutable_params()->set_salt("");
181 prf_key.set_key_value(subtle::Random::GetRandomBytes(32));
182
183 AesGcmKey derived_key_0;
184 AesGcmKey derived_key_1;
185 {
186 util::StatusOr<std::unique_ptr<KeysetDeriver>> deriver =
187 PrfBasedDeriver::New(test::AsKeyData(prf_key, KeyData::SYMMETRIC),
188 AeadKeyTemplates::Aes128Gcm());
189 ASSERT_THAT(deriver, IsOk());
190
191 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
192 (*deriver)->DeriveKeyset("salt");
193 ASSERT_THAT(handle, IsOk());
194
195 Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle);
196 ASSERT_TRUE(
197 derived_key_0.ParseFromString(keyset.key(0).key_data().value()));
198 }
199 {
200 prf_key.set_key_value(prf_key.key_value() + '\0');
201 util::StatusOr<std::unique_ptr<KeysetDeriver>> deriver =
202 PrfBasedDeriver::New(test::AsKeyData(prf_key, KeyData::SYMMETRIC),
203 AeadKeyTemplates::Aes128Gcm());
204 ASSERT_THAT(deriver, IsOk());
205
206 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
207 (*deriver)->DeriveKeyset("salt");
208 ASSERT_THAT(handle, IsOk());
209
210 Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle);
211 ASSERT_TRUE(
212 derived_key_1.ParseFromString(keyset.key(0).key_data().value()));
213 }
214 EXPECT_THAT(derived_key_0.key_value(), SizeIs(16));
215 EXPECT_THAT(derived_key_1.key_value(), SizeIs(16));
216 EXPECT_THAT(derived_key_0.key_value(), Ne(derived_key_1.key_value()));
217 }
218
TEST_F(PrfBasedDeriverTest,DeriveKeysetWithDifferentSalts)219 TEST_F(PrfBasedDeriverTest, DeriveKeysetWithDifferentSalts) {
220 HkdfPrfKey prf_key;
221 prf_key.set_version(0);
222 prf_key.mutable_params()->set_hash(HashType::SHA512);
223 prf_key.set_key_value(subtle::Random::GetRandomBytes(32));
224
225 AesGcmKey derived_key_0;
226 AesGcmKey derived_key_1;
227 {
228 util::StatusOr<std::unique_ptr<KeysetDeriver>> deriver =
229 PrfBasedDeriver::New(test::AsKeyData(prf_key, KeyData::SYMMETRIC),
230 AeadKeyTemplates::Aes128Gcm());
231 ASSERT_THAT(deriver, IsOk());
232
233 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
234 (*deriver)->DeriveKeyset(std::string(10, '\0'));
235 ASSERT_THAT(handle, IsOk());
236
237 Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle);
238 ASSERT_TRUE(
239 derived_key_0.ParseFromString(keyset.key(0).key_data().value()));
240 }
241 {
242 util::StatusOr<std::unique_ptr<KeysetDeriver>> deriver =
243 PrfBasedDeriver::New(test::AsKeyData(prf_key, KeyData::SYMMETRIC),
244 AeadKeyTemplates::Aes128Gcm());
245 ASSERT_THAT(deriver, IsOk());
246
247 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
248 (*deriver)->DeriveKeyset(std::string(11, '\0'));
249 ASSERT_THAT(handle, IsOk());
250
251 Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle);
252 ASSERT_TRUE(
253 derived_key_1.ParseFromString(keyset.key(0).key_data().value()));
254 }
255 EXPECT_THAT(derived_key_0.key_value(), SizeIs(16));
256 EXPECT_THAT(derived_key_1.key_value(), SizeIs(16));
257 EXPECT_THAT(derived_key_0.key_value(), Ne(derived_key_1.key_value()));
258 }
259
260 // Test vector generated with Java implementation.
TEST_F(PrfBasedDeriverTest,DeriveKeysetWithTestVector0)261 TEST_F(PrfBasedDeriverTest, DeriveKeysetWithTestVector0) {
262 HkdfPrfKey prf_key;
263 prf_key.set_version(0);
264 prf_key.mutable_params()->set_hash(HashType::SHA512);
265 prf_key.set_key_value(test::HexDecodeOrDie(
266 "a1a2a3a4a5a6a7a8a9aaabacadaeafb1b2b3b4b5b6b7b8b9babbbcbdbebf"
267 "c1c2c3c4c5c6c7c8c9cacbcccdcecfc1c2c3c4c5c6c7c8c9cacbcccdcecf"
268 "00"));
269
270 util::StatusOr<std::unique_ptr<KeysetDeriver>> deriver =
271 PrfBasedDeriver::New(test::AsKeyData(prf_key, KeyData::SYMMETRIC),
272 AeadKeyTemplates::Aes128Gcm());
273 ASSERT_THAT(deriver, IsOk());
274
275 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
276 (*deriver)->DeriveKeyset(test::HexDecodeOrDie("1122334455"));
277 ASSERT_THAT(handle, IsOk());
278
279 Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle);
280 AesGcmKey derived_key;
281 ASSERT_TRUE(derived_key.ParseFromString(keyset.key(0).key_data().value()));
282 EXPECT_THAT(derived_key.version(), Eq(AesGcmKeyManager().get_version()));
283 EXPECT_THAT(test::HexEncode(derived_key.key_value()),
284 Eq("31c449af66b669b9963ef2df30dfe5f9"));
285 }
286
287 // Test vector generated with Java implementation.
TEST_F(PrfBasedDeriverTest,DeriveKeysetWithTestVector1)288 TEST_F(PrfBasedDeriverTest, DeriveKeysetWithTestVector1) {
289 HkdfPrfKey prf_key;
290 prf_key.set_version(0);
291 prf_key.mutable_params()->set_hash(HashType::SHA512);
292 prf_key.set_key_value(test::HexDecodeOrDie(
293 "c1c2c3c4c5c6c7c8c9cacbcccdcecfc1c2c3c4c5c6c7c8c9cacbcccdcecf"
294 "a1a2a3a4a5a6a7a8a9aaabacadaeafb1b2b3b4b5b6b7b8b9babbbcbdbebf"));
295
296 util::StatusOr<std::unique_ptr<KeysetDeriver>> deriver =
297 PrfBasedDeriver::New(test::AsKeyData(prf_key, KeyData::SYMMETRIC),
298 AeadKeyTemplates::Aes128Gcm());
299 ASSERT_THAT(deriver, IsOk());
300
301 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
302 (*deriver)->DeriveKeyset(test::HexDecodeOrDie("00"));
303 ASSERT_THAT(handle, IsOk());
304
305 Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle);
306 AesGcmKey derived_key;
307 ASSERT_TRUE(derived_key.ParseFromString(keyset.key(0).key_data().value()));
308 EXPECT_THAT(derived_key.version(), Eq(AesGcmKeyManager().get_version()));
309 EXPECT_THAT(test::HexEncode(derived_key.key_value()),
310 Eq("887af0808c1855eba1594bf540adb957"));
311 }
312
313 // Test vector generated with Java implementation.
TEST_F(PrfBasedDeriverTest,DeriveKeysetWithEmptySaltTestVector)314 TEST_F(PrfBasedDeriverTest, DeriveKeysetWithEmptySaltTestVector) {
315 HkdfPrfKey prf_key;
316 prf_key.set_version(0);
317 prf_key.mutable_params()->set_hash(HashType::SHA512);
318 prf_key.set_key_value(test::HexDecodeOrDie(
319 "c1c2c3c4c5c6c7c8c9cacbcccdcecfc1c2c3c4c5c6c7c8c9cacbcccdcecf"
320 "a1a2a3a4a5a6a7a8a9aaabacadaeafb1b2b3b4b5b6b7b8b9babbbcbdbebf"));
321
322 util::StatusOr<std::unique_ptr<KeysetDeriver>> deriver =
323 PrfBasedDeriver::New(test::AsKeyData(prf_key, KeyData::SYMMETRIC),
324 AeadKeyTemplates::Aes128Gcm());
325 ASSERT_THAT(deriver, IsOk());
326
327 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
328 (*deriver)->DeriveKeyset("");
329 ASSERT_THAT(handle, IsOk());
330
331 Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle);
332 AesGcmKey derived_key;
333 ASSERT_TRUE(derived_key.ParseFromString(keyset.key(0).key_data().value()));
334 EXPECT_THAT(derived_key.version(), Eq(AesGcmKeyManager().get_version()));
335 EXPECT_THAT(test::HexEncode(derived_key.key_value()),
336 Eq("fb2b448c2595caf75129e282af758bf1"));
337 }
338
339 } // namespace
340 } // namespace internal
341 } // namespace tink
342 } // namespace crypto
343