1 // Copyright 2021 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/hybrid/internal/hpke_private_key_manager.h"
18
19 #include <memory>
20
21 #include "gtest/gtest.h"
22 #include "absl/status/status.h"
23 #include "tink/hybrid/internal/hpke_encrypt.h"
24 #include "tink/hybrid_encrypt.h"
25 #include "tink/subtle/hybrid_test_util.h"
26 #include "tink/util/status.h"
27 #include "tink/util/statusor.h"
28 #include "tink/util/test_matchers.h"
29 #include "tink/util/test_util.h"
30 #include "proto/hpke.pb.h"
31 #include "proto/tink.pb.h"
32
33 namespace crypto {
34 namespace tink {
35 namespace internal {
36 namespace {
37
38 using ::crypto::tink::test::IsOk;
39 using ::crypto::tink::test::StatusIs;
40 using ::google::crypto::tink::HpkeAead;
41 using ::google::crypto::tink::HpkeKdf;
42 using ::google::crypto::tink::HpkeKem;
43 using ::google::crypto::tink::HpkeKeyFormat;
44 using ::google::crypto::tink::HpkeParams;
45 using ::google::crypto::tink::HpkePrivateKey;
46 using ::google::crypto::tink::HpkePublicKey;
47 using ::google::crypto::tink::KeyData;
48 using ::testing::Eq;
49 using ::testing::IsEmpty;
50 using ::testing::Not;
51
CreateKeyFormat(HpkeKem kem,HpkeKdf kdf,HpkeAead aead)52 HpkeKeyFormat CreateKeyFormat(HpkeKem kem, HpkeKdf kdf, HpkeAead aead) {
53 HpkeKeyFormat key_format;
54 HpkeParams *params = key_format.mutable_params();
55 params->set_kem(kem);
56 params->set_kdf(kdf);
57 params->set_aead(aead);
58 return key_format;
59 }
60
CreateKey(HpkeKem kem,HpkeKdf kdf,HpkeAead aead)61 util::StatusOr<HpkePrivateKey> CreateKey(HpkeKem kem, HpkeKdf kdf,
62 HpkeAead aead) {
63 return HpkePrivateKeyManager().CreateKey(CreateKeyFormat(kem, kdf, aead));
64 }
65
TEST(HpkePrivateKeyManagerTest,BasicAccessors)66 TEST(HpkePrivateKeyManagerTest, BasicAccessors) {
67 EXPECT_THAT(HpkePrivateKeyManager().get_version(), Eq(0));
68 EXPECT_THAT(HpkePrivateKeyManager().key_material_type(),
69 Eq(KeyData::ASYMMETRIC_PRIVATE));
70 EXPECT_THAT(HpkePrivateKeyManager().get_key_type(),
71 Eq("type.googleapis.com/google.crypto.tink.HpkePrivateKey"));
72 }
73
TEST(HpkePrivateKeyManagerTest,ValidateEmptyKeyFormatFails)74 TEST(HpkePrivateKeyManagerTest, ValidateEmptyKeyFormatFails) {
75 EXPECT_THAT(HpkePrivateKeyManager().ValidateKeyFormat(HpkeKeyFormat()),
76 StatusIs(absl::StatusCode::kInvalidArgument));
77 }
78
TEST(HpkePrivateKeyManagerTest,ValidateKeyFormatSucceeds)79 TEST(HpkePrivateKeyManagerTest, ValidateKeyFormatSucceeds) {
80 EXPECT_THAT(HpkePrivateKeyManager().ValidateKeyFormat(
81 CreateKeyFormat(HpkeKem::DHKEM_X25519_HKDF_SHA256,
82 HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM)),
83 IsOk());
84 }
85
TEST(HpkePrivateKeyManagerTest,ValidateKeyFormatWithInvalidKemFails)86 TEST(HpkePrivateKeyManagerTest, ValidateKeyFormatWithInvalidKemFails) {
87 EXPECT_THAT(
88 HpkePrivateKeyManager().ValidateKeyFormat(CreateKeyFormat(
89 HpkeKem::KEM_UNKNOWN, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM)),
90 StatusIs(absl::StatusCode::kInvalidArgument));
91 }
92
TEST(HpkePrivateKeyManagerTest,ValidateKeyFormatWithInvalidKdfFails)93 TEST(HpkePrivateKeyManagerTest, ValidateKeyFormatWithInvalidKdfFails) {
94 EXPECT_THAT(HpkePrivateKeyManager().ValidateKeyFormat(
95 CreateKeyFormat(HpkeKem::DHKEM_X25519_HKDF_SHA256,
96 HpkeKdf::KDF_UNKNOWN, HpkeAead::AES_128_GCM)),
97 StatusIs(absl::StatusCode::kInvalidArgument));
98 }
99
TEST(HpkePrivateKeyManagerTest,ValidateKeyFormatWithInvalidAeadFails)100 TEST(HpkePrivateKeyManagerTest, ValidateKeyFormatWithInvalidAeadFails) {
101 EXPECT_THAT(HpkePrivateKeyManager().ValidateKeyFormat(CreateKeyFormat(
102 HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
103 HpkeAead::AEAD_UNKNOWN)),
104 StatusIs(absl::StatusCode::kInvalidArgument));
105 }
106
TEST(HpkePrivateKeyManagerTest,CreateKeySucceeds)107 TEST(HpkePrivateKeyManagerTest, CreateKeySucceeds) {
108 HpkeKeyFormat key_format =
109 CreateKeyFormat(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
110 HpkeAead::AES_128_GCM);
111
112 util::StatusOr<HpkePrivateKey> key =
113 HpkePrivateKeyManager().CreateKey(key_format);
114 ASSERT_THAT(key, IsOk());
115
116 ASSERT_TRUE(key->has_public_key());
117 ASSERT_TRUE(key->public_key().has_params());
118 EXPECT_THAT(key->public_key().params().kem(), Eq(key_format.params().kem()));
119 EXPECT_THAT(key->public_key().params().kdf(), Eq(key_format.params().kdf()));
120 EXPECT_THAT(key->public_key().params().aead(),
121 Eq(key_format.params().aead()));
122 EXPECT_THAT(key->public_key().public_key(), Not(IsEmpty()));
123 EXPECT_THAT(key->private_key(), Not(IsEmpty()));
124 }
125
TEST(HpkePrivateKeyManagerTest,CreateKeyWithInvalidKemFails)126 TEST(HpkePrivateKeyManagerTest, CreateKeyWithInvalidKemFails) {
127 HpkeKeyFormat key_format = CreateKeyFormat(
128 HpkeKem::KEM_UNKNOWN, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM);
129
130 ASSERT_THAT(HpkePrivateKeyManager().CreateKey(key_format).status(),
131 StatusIs(absl::StatusCode::kInvalidArgument));
132 }
133
TEST(HpkePrivateKeyManagerTest,ValidateEmptyKeyFails)134 TEST(HpkePrivateKeyManagerTest, ValidateEmptyKeyFails) {
135 EXPECT_THAT(HpkePrivateKeyManager().ValidateKey(HpkePrivateKey()),
136 StatusIs(absl::StatusCode::kInvalidArgument));
137 }
138
TEST(HpkePrivateKeyManagerTest,ValidateKeySucceeds)139 TEST(HpkePrivateKeyManagerTest, ValidateKeySucceeds) {
140 util::StatusOr<HpkePrivateKey> key =
141 CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
142 HpkeAead::AES_128_GCM);
143 ASSERT_THAT(key, IsOk());
144
145 EXPECT_THAT(HpkePrivateKeyManager().ValidateKey(*key), IsOk());
146 }
147
TEST(HpkePrivateKeyManagerTest,ValidateKeyWithWrongVersionFails)148 TEST(HpkePrivateKeyManagerTest, ValidateKeyWithWrongVersionFails) {
149 util::StatusOr<HpkePrivateKey> key =
150 CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
151 HpkeAead::AES_128_GCM);
152 ASSERT_THAT(key, IsOk());
153 key->set_version(1);
154
155 EXPECT_THAT(HpkePrivateKeyManager().ValidateKey(*key),
156 StatusIs(absl::StatusCode::kInvalidArgument));
157 }
158
TEST(HpkePrivateKeyManagerTest,ValidateKeyWithInvalidKemFails)159 TEST(HpkePrivateKeyManagerTest, ValidateKeyWithInvalidKemFails) {
160 util::StatusOr<HpkePrivateKey> key =
161 CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
162 HpkeAead::AES_128_GCM);
163 ASSERT_THAT(key, IsOk());
164 key->mutable_public_key()->mutable_params()->set_kem(HpkeKem::KEM_UNKNOWN);
165
166 EXPECT_THAT(HpkePrivateKeyManager().ValidateKey(*key),
167 StatusIs(absl::StatusCode::kInvalidArgument));
168 }
169
TEST(HpkePrivateKeyManagerTest,ValidateKeyWithInvalidKdfFails)170 TEST(HpkePrivateKeyManagerTest, ValidateKeyWithInvalidKdfFails) {
171 util::StatusOr<HpkePrivateKey> key =
172 CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::KDF_UNKNOWN,
173 HpkeAead::AES_128_GCM);
174 ASSERT_THAT(key, IsOk());
175
176 EXPECT_THAT(HpkePrivateKeyManager().ValidateKey(*key),
177 StatusIs(absl::StatusCode::kInvalidArgument));
178 }
179
TEST(HpkePrivateKeyManagerTest,ValidateKeyWithInvalidAeadFails)180 TEST(HpkePrivateKeyManagerTest, ValidateKeyWithInvalidAeadFails) {
181 util::StatusOr<HpkePrivateKey> key =
182 CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
183 HpkeAead::AEAD_UNKNOWN);
184 ASSERT_THAT(key, IsOk());
185
186 EXPECT_THAT(HpkePrivateKeyManager().ValidateKey(*key),
187 StatusIs(absl::StatusCode::kInvalidArgument));
188 }
189
TEST(HpkePrivateKeyManagerTest,GetPublicKeySucceeds)190 TEST(HpkePrivateKeyManagerTest, GetPublicKeySucceeds) {
191 HpkeKeyFormat key_format =
192 CreateKeyFormat(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
193 HpkeAead::AES_128_GCM);
194 util::StatusOr<HpkePrivateKey> key =
195 HpkePrivateKeyManager().CreateKey(key_format);
196 ASSERT_THAT(key, IsOk());
197
198 util::StatusOr<HpkePublicKey> public_key =
199 HpkePrivateKeyManager().GetPublicKey(*key);
200 ASSERT_THAT(public_key, IsOk());
201
202 ASSERT_TRUE(key->has_public_key());
203 ASSERT_TRUE(key->public_key().has_params());
204 EXPECT_THAT(public_key->params().kem(), Eq(key_format.params().kem()));
205 EXPECT_THAT(public_key->params().kdf(), Eq(key_format.params().kdf()));
206 EXPECT_THAT(public_key->params().aead(), Eq(key_format.params().aead()));
207 ASSERT_THAT(public_key->public_key(), Not(IsEmpty()));
208 EXPECT_THAT(public_key->public_key(), Eq(key->public_key().public_key()));
209 }
210
TEST(HpkePrivateKeyManagerTest,EncryptThenDecryptSucceeds)211 TEST(HpkePrivateKeyManagerTest, EncryptThenDecryptSucceeds) {
212 util::StatusOr<HpkePrivateKey> private_key =
213 CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
214 HpkeAead::AES_128_GCM);
215 ASSERT_THAT(private_key, IsOk());
216 util::StatusOr<HpkePublicKey> public_key =
217 HpkePrivateKeyManager().GetPublicKey(*private_key);
218 ASSERT_THAT(public_key, IsOk());
219 util::StatusOr<std::unique_ptr<HybridDecrypt>> decrypt =
220 HpkePrivateKeyManager().GetPrimitive<HybridDecrypt>(*private_key);
221 ASSERT_THAT(decrypt, IsOk());
222 util::StatusOr<std::unique_ptr<HybridEncrypt>> encrypt =
223 HpkeEncrypt::New(*public_key);
224 ASSERT_THAT(encrypt, IsOk());
225
226 ASSERT_THAT(HybridEncryptThenDecrypt(encrypt->get(), decrypt->get(),
227 "some text", "some aad"),
228 IsOk());
229 }
230
TEST(HpkePrivateKeyManagerTest,EncryptThenDecryptWithDifferentKeysFails)231 TEST(HpkePrivateKeyManagerTest, EncryptThenDecryptWithDifferentKeysFails) {
232 util::StatusOr<HpkePrivateKey> private_key =
233 CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
234 HpkeAead::AES_128_GCM);
235 ASSERT_THAT(private_key, IsOk());
236 util::StatusOr<HpkePrivateKey> different_private_key =
237 CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
238 HpkeAead::AES_128_GCM);
239 ASSERT_THAT(different_private_key, IsOk());
240 util::StatusOr<HpkePublicKey> public_key =
241 HpkePrivateKeyManager().GetPublicKey(*different_private_key);
242 ASSERT_THAT(public_key, IsOk());
243 util::StatusOr<std::unique_ptr<HybridDecrypt>> decrypt =
244 HpkePrivateKeyManager().GetPrimitive<HybridDecrypt>(*private_key);
245 ASSERT_THAT(decrypt, IsOk());
246 util::StatusOr<std::unique_ptr<HybridEncrypt>> encrypt =
247 HpkeEncrypt::New(*public_key);
248 ASSERT_THAT(encrypt, IsOk());
249
250 ASSERT_THAT(HybridEncryptThenDecrypt(encrypt->get(), decrypt->get(),
251 "some text", "some aad"),
252 Not(IsOk()));
253 }
254
255 } // namespace
256 } // namespace internal
257 } // namespace tink
258 } // namespace crypto
259