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_key_manager.h"
18
19 #include <memory>
20 #include <string>
21
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "absl/status/status.h"
25 #include "tink/aead/aead_key_templates.h"
26 #include "tink/aead/aes_gcm_key_manager.h"
27 #include "tink/cleartext_keyset_handle.h"
28 #include "tink/keyderivation/keyset_deriver.h"
29 #include "tink/prf/hkdf_prf_key_manager.h"
30 #include "tink/subtle/random.h"
31 #include "tink/util/statusor.h"
32 #include "tink/util/test_matchers.h"
33 #include "tink/util/test_util.h"
34 #include "proto/aes_gcm.pb.h"
35 #include "proto/hkdf_prf.pb.h"
36 #include "proto/prf_based_deriver.pb.h"
37 #include "proto/tink.pb.h"
38
39 namespace crypto {
40 namespace tink {
41 namespace internal {
42 namespace {
43
44 using ::crypto::tink::test::IsOk;
45 using ::crypto::tink::test::StatusIs;
46 using ::crypto::tink::util::StatusOr;
47 using ::google::crypto::tink::AesGcmKey;
48 using ::google::crypto::tink::HashType;
49 using ::google::crypto::tink::HkdfPrfKey;
50 using ::google::crypto::tink::HkdfPrfKeyFormat;
51 using ::google::crypto::tink::KeyData;
52 using ::google::crypto::tink::Keyset;
53 using ::google::crypto::tink::KeyTemplate;
54 using ::google::crypto::tink::PrfBasedDeriverKey;
55 using ::google::crypto::tink::PrfBasedDeriverKeyFormat;
56 using ::testing::Eq;
57 using ::testing::SizeIs;
58
TEST(PrfBasedDeriverKeyManagerTest,Basics)59 TEST(PrfBasedDeriverKeyManagerTest, Basics) {
60 EXPECT_THAT(PrfBasedDeriverKeyManager().get_version(), Eq(0));
61 EXPECT_THAT(PrfBasedDeriverKeyManager().get_key_type(),
62 Eq("type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey"));
63 EXPECT_THAT(PrfBasedDeriverKeyManager().key_material_type(),
64 Eq(KeyData::SYMMETRIC));
65 }
66
TEST(PrfBasedDeriverKeyManagerTest,ValidateKeyEmpty)67 TEST(PrfBasedDeriverKeyManagerTest, ValidateKeyEmpty) {
68 EXPECT_THAT(PrfBasedDeriverKeyManager().ValidateKey(PrfBasedDeriverKey()),
69 StatusIs(absl::StatusCode::kInvalidArgument));
70 }
71
TEST(PrfBasedDeriverKeyManagerTest,ValidateKey)72 TEST(PrfBasedDeriverKeyManagerTest, ValidateKey) {
73 HkdfPrfKey prf_key;
74 prf_key.set_version(0);
75 prf_key.set_key_value("0123456789abcdef");
76 prf_key.mutable_params()->set_hash(HashType::SHA256);
77
78 PrfBasedDeriverKey key;
79 key.set_version(0);
80 *key.mutable_prf_key() = test::AsKeyData(prf_key, KeyData::SYMMETRIC);
81 *key.mutable_params()->mutable_derived_key_template() =
82 AeadKeyTemplates::Aes256Gcm();
83
84 EXPECT_THAT(PrfBasedDeriverKeyManager().ValidateKey(key), IsOk());
85 }
86
TEST(PrfBasedDeriverKeyManagerTest,ValidateKeyWithWrongVersion)87 TEST(PrfBasedDeriverKeyManagerTest, ValidateKeyWithWrongVersion) {
88 HkdfPrfKey prf_key;
89 prf_key.set_version(0);
90 prf_key.set_key_value("0123456789abcdef");
91 prf_key.mutable_params()->set_hash(HashType::SHA256);
92
93 PrfBasedDeriverKey key;
94 key.set_version(1);
95 *key.mutable_prf_key() = test::AsKeyData(prf_key, KeyData::SYMMETRIC);
96 *key.mutable_params()->mutable_derived_key_template() =
97 AeadKeyTemplates::Aes256Gcm();
98
99 EXPECT_THAT(PrfBasedDeriverKeyManager().ValidateKey(key),
100 StatusIs(absl::StatusCode::kInvalidArgument));
101 }
102
TEST(PrfBasedDeriverKeyManagerTest,ValidateKeyFormat)103 TEST(PrfBasedDeriverKeyManagerTest, ValidateKeyFormat) {
104 HkdfPrfKeyFormat prf_key_format;
105 prf_key_format.set_key_size(16);
106 prf_key_format.mutable_params()->set_hash(HashType::SHA256);
107
108 PrfBasedDeriverKeyFormat key_format;
109 key_format.mutable_prf_key_template()->set_type_url(
110 HkdfPrfKeyManager().get_key_type());
111 key_format.mutable_prf_key_template()->set_value(
112 prf_key_format.SerializeAsString());
113 *key_format.mutable_params()->mutable_derived_key_template() =
114 AeadKeyTemplates::Aes256Gcm();
115
116 EXPECT_THAT(PrfBasedDeriverKeyManager().ValidateKeyFormat(key_format),
117 IsOk());
118 }
119
TEST(PrfBasedDeriverKeyManagerTest,ValidateKeyFormatEmpty)120 TEST(PrfBasedDeriverKeyManagerTest, ValidateKeyFormatEmpty) {
121 EXPECT_THAT(
122 PrfBasedDeriverKeyManager().ValidateKeyFormat(PrfBasedDeriverKeyFormat()),
123 StatusIs(absl::StatusCode::kInvalidArgument));
124 }
125
TEST(PrfBasedDeriverKeyManagerTest,CreateKey)126 TEST(PrfBasedDeriverKeyManagerTest, CreateKey) {
127 Registry::Reset();
128 ASSERT_THAT(Registry::RegisterKeyTypeManager(
129 absl::make_unique<HkdfPrfKeyManager>(), true),
130 IsOk());
131 ASSERT_THAT(Registry::RegisterKeyTypeManager(
132 absl::make_unique<HkdfPrfKeyManager>(), true),
133 IsOk());
134 ASSERT_THAT(Registry::RegisterKeyTypeManager(
135 absl::make_unique<AesGcmKeyManager>(), true),
136 IsOk());
137
138 HkdfPrfKeyFormat prf_key_format;
139 prf_key_format.set_key_size(32);
140 prf_key_format.mutable_params()->set_hash(HashType::SHA256);
141
142 PrfBasedDeriverKeyFormat key_format;
143 key_format.mutable_prf_key_template()->set_type_url(
144 HkdfPrfKeyManager().get_key_type());
145 key_format.mutable_prf_key_template()->set_value(
146 prf_key_format.SerializeAsString());
147 *key_format.mutable_params()->mutable_derived_key_template() =
148 AeadKeyTemplates::Aes256Gcm();
149
150 util::StatusOr<PrfBasedDeriverKey> key =
151 PrfBasedDeriverKeyManager().CreateKey(key_format);
152 ASSERT_THAT(key, IsOk());
153 EXPECT_THAT((*key).version(), Eq(0));
154 EXPECT_THAT((*key).prf_key().type_url(),
155 Eq(HkdfPrfKeyManager().get_key_type()));
156 EXPECT_THAT((*key).prf_key().key_material_type(), Eq(KeyData::SYMMETRIC));
157
158 HkdfPrfKey prf_key;
159 ASSERT_TRUE(prf_key.ParseFromString((*key).prf_key().value()));
160 EXPECT_THAT(prf_key.key_value().size(), Eq(32));
161
162 EXPECT_THAT((*key).params().derived_key_template().type_url(),
163 Eq(key_format.params().derived_key_template().type_url()));
164 EXPECT_THAT((*key).params().derived_key_template().value(),
165 Eq(key_format.params().derived_key_template().value()));
166 }
167
TEST(PrfBasedDeriverKeyManagerTest,CreateKeyWithInvalidPrfKey)168 TEST(PrfBasedDeriverKeyManagerTest, CreateKeyWithInvalidPrfKey) {
169 Registry::Reset();
170 ASSERT_THAT(Registry::RegisterKeyTypeManager(
171 absl::make_unique<HkdfPrfKeyManager>(), true),
172 IsOk());
173 ASSERT_THAT(Registry::RegisterKeyTypeManager(
174 absl::make_unique<HkdfPrfKeyManager>(), true),
175 IsOk());
176 ASSERT_THAT(Registry::RegisterKeyTypeManager(
177 absl::make_unique<AesGcmKeyManager>(), true),
178 IsOk());
179
180 HkdfPrfKeyFormat prf_key_format;
181 prf_key_format.set_key_size(32);
182 prf_key_format.mutable_params()->set_hash(HashType::UNKNOWN_HASH);
183
184 PrfBasedDeriverKeyFormat key_format;
185 key_format.mutable_prf_key_template()->set_type_url(
186 HkdfPrfKeyManager().get_key_type());
187 key_format.mutable_prf_key_template()->set_value(
188 prf_key_format.SerializeAsString());
189 *key_format.mutable_params()->mutable_derived_key_template() =
190 AeadKeyTemplates::Aes256Gcm();
191
192 EXPECT_THAT(PrfBasedDeriverKeyManager().CreateKey(key_format).status(),
193 StatusIs(absl::StatusCode::kInvalidArgument));
194 }
195
TEST(PrfBasedDeriverKeyManagerTest,CreateKeyWithInvalidDerivedKeyTemplate)196 TEST(PrfBasedDeriverKeyManagerTest, CreateKeyWithInvalidDerivedKeyTemplate) {
197 Registry::Reset();
198 ASSERT_THAT(Registry::RegisterKeyTypeManager(
199 absl::make_unique<HkdfPrfKeyManager>(), true),
200 IsOk());
201 ASSERT_THAT(Registry::RegisterKeyTypeManager(
202 absl::make_unique<HkdfPrfKeyManager>(), true),
203 IsOk());
204 ASSERT_THAT(Registry::RegisterKeyTypeManager(
205 absl::make_unique<AesGcmKeyManager>(), true),
206 IsOk());
207
208 HkdfPrfKeyFormat prf_key_format;
209 prf_key_format.set_key_size(32);
210 prf_key_format.mutable_params()->set_hash(HashType::SHA256);
211 KeyTemplate derived_template;
212 derived_template.set_type_url("nonexistent.type.url");
213
214 PrfBasedDeriverKeyFormat key_format;
215 key_format.mutable_prf_key_template()->set_type_url(
216 HkdfPrfKeyManager().get_key_type());
217 key_format.mutable_prf_key_template()->set_value(
218 prf_key_format.SerializeAsString());
219 *key_format.mutable_params()->mutable_derived_key_template() =
220 derived_template;
221
222 // See comment in PrfBasedDeriverKeyManager::CreateKey().
223 EXPECT_THAT(PrfBasedDeriverKeyManager().CreateKey(key_format).status(),
224 IsOk());
225 }
226
TEST(PrfBasedDeriverKeyManagerTest,GetPrimitive)227 TEST(PrfBasedDeriverKeyManagerTest, GetPrimitive) {
228 Registry::Reset();
229 ASSERT_THAT(Registry::RegisterKeyTypeManager(
230 absl::make_unique<PrfBasedDeriverKeyManager>(), true),
231 IsOk());
232 ASSERT_THAT(Registry::RegisterKeyTypeManager(
233 absl::make_unique<HkdfPrfKeyManager>(), true),
234 IsOk());
235 ASSERT_THAT(Registry::RegisterKeyTypeManager(
236 absl::make_unique<AesGcmKeyManager>(), true),
237 IsOk());
238
239 HkdfPrfKey prf_key;
240 prf_key.set_version(0);
241 prf_key.mutable_params()->set_hash(HashType::SHA256);
242 prf_key.mutable_params()->set_salt(subtle::Random::GetRandomBytes(15));
243 prf_key.set_key_value(subtle::Random::GetRandomBytes(33));
244 prf_key.mutable_params()->set_hash(HashType::SHA256);
245 PrfBasedDeriverKey key;
246 key.set_version(0);
247 *key.mutable_prf_key() = test::AsKeyData(prf_key, KeyData::SYMMETRIC);
248 *key.mutable_params()->mutable_derived_key_template() =
249 AeadKeyTemplates::Aes256Gcm();
250
251 StatusOr<std::unique_ptr<KeysetDeriver>> deriver =
252 PrfBasedDeriverKeyManager().GetPrimitive<KeysetDeriver>(key);
253 ASSERT_THAT(deriver, IsOk());
254
255 std::string salt = subtle::Random::GetRandomBytes(23);
256 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
257 (*deriver)->DeriveKeyset(salt);
258 ASSERT_THAT(handle, IsOk());
259 Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle);
260
261 StatusOr<std::unique_ptr<KeysetDeriver>> direct_deriver =
262 internal::PrfBasedDeriver::New(key.prf_key(),
263 key.params().derived_key_template());
264 ASSERT_THAT(direct_deriver, IsOk());
265 util::StatusOr<std::unique_ptr<KeysetHandle>> direct_handle =
266 (*direct_deriver)->DeriveKeyset(salt);
267 ASSERT_THAT(direct_handle, IsOk());
268 Keyset direct_keyset = CleartextKeysetHandle::GetKeyset(**direct_handle);
269
270 ASSERT_THAT(keyset.key(), SizeIs(1));
271 ASSERT_THAT(direct_keyset.key(), SizeIs(1));
272
273 ASSERT_THAT(keyset.key(0).key_data().type_url(),
274 Eq(keyset.key(0).key_data().type_url()));
275
276 AesGcmKey derived_key;
277 ASSERT_TRUE(derived_key.ParseFromString(keyset.key(0).key_data().value()));
278 AesGcmKey direct_derived_key;
279 ASSERT_TRUE(direct_derived_key.ParseFromString(
280 direct_keyset.key(0).key_data().value()));
281 EXPECT_THAT(derived_key.key_value(), Eq(direct_derived_key.key_value()));
282 }
283
284 } // namespace
285 } // namespace internal
286 } // namespace tink
287 } // namespace crypto
288