xref: /aosp_15_r20/external/tink/cc/keyderivation/internal/prf_based_deriver_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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