1 /* Copyright (c) 2020, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <openssl/hpke.h>
16
17 #include <cstdint>
18 #include <limits>
19 #include <string>
20 #include <vector>
21
22 #include <gtest/gtest.h>
23
24 #include <openssl/base.h>
25 #include <openssl/curve25519.h>
26 #include <openssl/digest.h>
27 #include <openssl/err.h>
28 #include <openssl/evp.h>
29 #include <openssl/rand.h>
30 #include <openssl/sha.h>
31 #include <openssl/span.h>
32
33 #include "../test/file_test.h"
34 #include "../test/test_util.h"
35
36
37 namespace bssl {
38 namespace {
39
40 const decltype(&EVP_hpke_aes_128_gcm) kAllAEADs[] = {
41 &EVP_hpke_aes_128_gcm,
42 &EVP_hpke_aes_256_gcm,
43 &EVP_hpke_chacha20_poly1305,
44 };
45
46 const decltype(&EVP_hpke_hkdf_sha256) kAllKDFs[] = {
47 &EVP_hpke_hkdf_sha256,
48 };
49
50 // HPKETestVector corresponds to one array member in the published
51 // test-vectors.json.
52 class HPKETestVector {
53 public:
54 explicit HPKETestVector() = default;
55 ~HPKETestVector() = default;
56
57 bool ReadFromFileTest(FileTest *t);
58
Verify() const59 void Verify() const {
60 const EVP_HPKE_KEM *kem = EVP_hpke_x25519_hkdf_sha256();
61 const EVP_HPKE_AEAD *aead = GetAEAD();
62 ASSERT_TRUE(aead);
63 const EVP_HPKE_KDF *kdf = GetKDF();
64 ASSERT_TRUE(kdf);
65
66 // Test the sender.
67 ScopedEVP_HPKE_CTX sender_ctx;
68 uint8_t enc[EVP_HPKE_MAX_ENC_LENGTH];
69 size_t enc_len = 0;
70 switch (mode_) {
71 case Mode::kBase:
72 ASSERT_TRUE(EVP_HPKE_CTX_setup_sender_with_seed_for_testing(
73 sender_ctx.get(), enc, &enc_len, sizeof(enc), kem, kdf, aead,
74 public_key_r_.data(), public_key_r_.size(), info_.data(),
75 info_.size(), secret_key_e_.data(), secret_key_e_.size()));
76 break;
77 case Mode::kAuth: {
78 ScopedEVP_HPKE_KEY sender_key;
79 ASSERT_TRUE(EVP_HPKE_KEY_init(
80 sender_key.get(), kem, secret_key_s_.data(), secret_key_s_.size()));
81 ASSERT_TRUE(EVP_HPKE_CTX_setup_auth_sender_with_seed_for_testing(
82 sender_ctx.get(), enc, &enc_len, sizeof(enc), sender_key.get(), kdf,
83 aead, public_key_r_.data(), public_key_r_.size(), info_.data(),
84 info_.size(), secret_key_e_.data(), secret_key_e_.size()));
85 break;
86 }
87 }
88
89 EXPECT_EQ(Bytes(enc, enc_len), Bytes(public_key_e_));
90 VerifySender(sender_ctx.get());
91
92 // Test the recipient.
93 ScopedEVP_HPKE_KEY base_key;
94 ASSERT_TRUE(EVP_HPKE_KEY_init(base_key.get(), kem, secret_key_r_.data(),
95 secret_key_r_.size()));
96
97 enum class CopyMode { kOriginal, kCopy, kMove };
98 for (CopyMode copy :
99 {CopyMode::kOriginal, CopyMode::kCopy, CopyMode::kMove}) {
100 SCOPED_TRACE(static_cast<int>(copy));
101 const EVP_HPKE_KEY *key = base_key.get();
102 ScopedEVP_HPKE_KEY key_copy;
103 switch (copy) {
104 case CopyMode::kOriginal:
105 break;
106 case CopyMode::kCopy:
107 ASSERT_TRUE(EVP_HPKE_KEY_copy(key_copy.get(), base_key.get()));
108 key = key_copy.get();
109 break;
110 case CopyMode::kMove:
111 EVP_HPKE_KEY_move(key_copy.get(), base_key.get());
112 key = key_copy.get();
113 break;
114 }
115
116 uint8_t public_key[EVP_HPKE_MAX_PUBLIC_KEY_LENGTH];
117 size_t public_key_len;
118 ASSERT_TRUE(EVP_HPKE_KEY_public_key(key, public_key, &public_key_len,
119 sizeof(public_key)));
120 EXPECT_EQ(Bytes(public_key, public_key_len), Bytes(public_key_r_));
121
122 uint8_t private_key[EVP_HPKE_MAX_PRIVATE_KEY_LENGTH];
123 size_t private_key_len;
124 ASSERT_TRUE(EVP_HPKE_KEY_private_key(key, private_key, &private_key_len,
125 sizeof(private_key)));
126 EXPECT_EQ(Bytes(private_key, private_key_len), Bytes(secret_key_r_));
127
128 // Set up the recipient.
129 ScopedEVP_HPKE_CTX recipient_ctx;
130 switch (mode_) {
131 case Mode::kBase:
132 ASSERT_TRUE(EVP_HPKE_CTX_setup_recipient(recipient_ctx.get(), key,
133 kdf, aead, enc, enc_len,
134 info_.data(), info_.size()));
135 break;
136 case Mode::kAuth:
137 ASSERT_TRUE(EVP_HPKE_CTX_setup_auth_recipient(
138 recipient_ctx.get(), key, kdf, aead, enc, enc_len, info_.data(),
139 info_.size(), public_key_s_.data(), public_key_s_.size()));
140 break;
141 }
142
143 VerifyRecipient(recipient_ctx.get());
144 }
145 }
146
147 private:
GetAEAD() const148 const EVP_HPKE_AEAD *GetAEAD() const {
149 for (const auto aead : kAllAEADs) {
150 if (EVP_HPKE_AEAD_id(aead()) == aead_id_) {
151 return aead();
152 }
153 }
154 return nullptr;
155 }
156
GetKDF() const157 const EVP_HPKE_KDF *GetKDF() const {
158 for (const auto kdf : kAllKDFs) {
159 if (EVP_HPKE_KDF_id(kdf()) == kdf_id_) {
160 return kdf();
161 }
162 }
163 return nullptr;
164 }
165
VerifySender(EVP_HPKE_CTX * ctx) const166 void VerifySender(EVP_HPKE_CTX *ctx) const {
167 for (const Encryption &task : encryptions_) {
168 std::vector<uint8_t> encrypted(task.plaintext.size() +
169 EVP_HPKE_CTX_max_overhead(ctx));
170 size_t encrypted_len;
171 ASSERT_TRUE(EVP_HPKE_CTX_seal(ctx, encrypted.data(), &encrypted_len,
172 encrypted.size(), task.plaintext.data(),
173 task.plaintext.size(), task.aad.data(),
174 task.aad.size()));
175
176 ASSERT_EQ(Bytes(encrypted.data(), encrypted_len), Bytes(task.ciphertext));
177 }
178 VerifyExports(ctx);
179 }
180
VerifyRecipient(EVP_HPKE_CTX * ctx) const181 void VerifyRecipient(EVP_HPKE_CTX *ctx) const {
182 for (const Encryption &task : encryptions_) {
183 std::vector<uint8_t> decrypted(task.ciphertext.size());
184 size_t decrypted_len;
185 ASSERT_TRUE(EVP_HPKE_CTX_open(ctx, decrypted.data(), &decrypted_len,
186 decrypted.size(), task.ciphertext.data(),
187 task.ciphertext.size(), task.aad.data(),
188 task.aad.size()));
189
190 ASSERT_EQ(Bytes(decrypted.data(), decrypted_len), Bytes(task.plaintext));
191 }
192 VerifyExports(ctx);
193 }
194
VerifyExports(EVP_HPKE_CTX * ctx) const195 void VerifyExports(EVP_HPKE_CTX *ctx) const {
196 for (const Export &task : exports_) {
197 std::vector<uint8_t> exported_secret(task.export_length);
198
199 ASSERT_TRUE(EVP_HPKE_CTX_export(
200 ctx, exported_secret.data(), exported_secret.size(),
201 task.exporter_context.data(), task.exporter_context.size()));
202 ASSERT_EQ(Bytes(exported_secret), Bytes(task.exported_value));
203 }
204 }
205
206 enum class Mode {
207 kBase = 0,
208 kAuth = 2,
209 };
210
211 struct Encryption {
212 std::vector<uint8_t> aad;
213 std::vector<uint8_t> ciphertext;
214 std::vector<uint8_t> plaintext;
215 };
216
217 struct Export {
218 std::vector<uint8_t> exporter_context;
219 size_t export_length;
220 std::vector<uint8_t> exported_value;
221 };
222
223 Mode mode_;
224 uint16_t kdf_id_;
225 uint16_t aead_id_;
226 std::vector<uint8_t> context_;
227 std::vector<uint8_t> info_;
228 std::vector<uint8_t> public_key_e_;
229 std::vector<uint8_t> secret_key_e_;
230 std::vector<uint8_t> public_key_r_;
231 std::vector<uint8_t> secret_key_r_;
232 std::vector<uint8_t> public_key_s_;
233 std::vector<uint8_t> secret_key_s_;
234 std::vector<Encryption> encryptions_;
235 std::vector<Export> exports_;
236 };
237
238 // Match FileTest's naming scheme for duplicated attribute names.
BuildAttrName(const std::string & name,int iter)239 std::string BuildAttrName(const std::string &name, int iter) {
240 return iter == 1 ? name : name + "/" + std::to_string(iter);
241 }
242
243 // Parses |s| as an unsigned integer of type T and writes the value to |out|.
244 // Returns true on success. If the integer value exceeds the maximum T value,
245 // returns false.
246 template <typename T>
ParseIntSafe(T * out,const std::string & s)247 bool ParseIntSafe(T *out, const std::string &s) {
248 T value = 0;
249 for (char c : s) {
250 if (c < '0' || c > '9') {
251 return false;
252 }
253 if (value > (std::numeric_limits<T>::max() - (c - '0')) / 10) {
254 return false;
255 }
256 value = 10 * value + (c - '0');
257 }
258 *out = value;
259 return true;
260 }
261
262 // Read the |key| attribute from |file_test| and convert it to an integer.
263 template <typename T>
FileTestReadInt(FileTest * file_test,T * out,const std::string & key)264 bool FileTestReadInt(FileTest *file_test, T *out, const std::string &key) {
265 std::string s;
266 return file_test->GetAttribute(&s, key) && ParseIntSafe(out, s);
267 }
268
269
ReadFromFileTest(FileTest * t)270 bool HPKETestVector::ReadFromFileTest(FileTest *t) {
271 uint8_t mode = 0;
272 if (!FileTestReadInt(t, &mode, "mode") ||
273 !FileTestReadInt(t, &kdf_id_, "kdf_id") ||
274 !FileTestReadInt(t, &aead_id_, "aead_id") ||
275 !t->GetBytes(&info_, "info") ||
276 !t->GetBytes(&secret_key_r_, "skRm") ||
277 !t->GetBytes(&public_key_r_, "pkRm") ||
278 !t->GetBytes(&secret_key_e_, "skEm") ||
279 !t->GetBytes(&public_key_e_, "pkEm")) {
280 return false;
281 }
282
283 switch (mode) {
284 case static_cast<int>(Mode::kBase):
285 mode_ = Mode::kBase;
286 break;
287 case static_cast<int>(Mode::kAuth):
288 mode_ = Mode::kAuth;
289 if (!t->GetBytes(&secret_key_s_, "skSm") ||
290 !t->GetBytes(&public_key_s_, "pkSm")) {
291 return false;
292 }
293 break;
294 default:
295 return false;
296 }
297
298 for (int i = 1; t->HasAttribute(BuildAttrName("aad", i)); i++) {
299 Encryption encryption;
300 if (!t->GetBytes(&encryption.aad, BuildAttrName("aad", i)) ||
301 !t->GetBytes(&encryption.ciphertext, BuildAttrName("ct", i)) ||
302 !t->GetBytes(&encryption.plaintext, BuildAttrName("pt", i))) {
303 return false;
304 }
305 encryptions_.push_back(std::move(encryption));
306 }
307
308 for (int i = 1; t->HasAttribute(BuildAttrName("exporter_context", i)); i++) {
309 Export exp;
310 if (!t->GetBytes(&exp.exporter_context,
311 BuildAttrName("exporter_context", i)) ||
312 !FileTestReadInt(t, &exp.export_length, BuildAttrName("L", i)) ||
313 !t->GetBytes(&exp.exported_value, BuildAttrName("exported_value", i))) {
314 return false;
315 }
316 exports_.push_back(std::move(exp));
317 }
318 return true;
319 }
320
321 } // namespace
322
TEST(HPKETest,VerifyTestVectors)323 TEST(HPKETest, VerifyTestVectors) {
324 FileTestGTest("crypto/hpke/hpke_test_vectors.txt", [](FileTest *t) {
325 HPKETestVector test_vec;
326 EXPECT_TRUE(test_vec.ReadFromFileTest(t));
327 test_vec.Verify();
328 });
329 }
330
331 // The test vectors used fixed sender ephemeral keys, while HPKE itself
332 // generates new keys for each context. Test this codepath by checking we can
333 // decrypt our own messages.
TEST(HPKETest,RoundTrip)334 TEST(HPKETest, RoundTrip) {
335 const uint8_t info_a[] = {1, 1, 2, 3, 5, 8};
336 const uint8_t info_b[] = {42, 42, 42};
337 const uint8_t ad_a[] = {1, 2, 4, 8, 16};
338 const uint8_t ad_b[] = {7};
339 Span<const uint8_t> info_values[] = {{nullptr, 0}, info_a, info_b};
340 Span<const uint8_t> ad_values[] = {{nullptr, 0}, ad_a, ad_b};
341
342 const EVP_HPKE_KEM *kem = EVP_hpke_x25519_hkdf_sha256();
343
344 // Generate the recipient's keypair.
345 ScopedEVP_HPKE_KEY key;
346 ASSERT_TRUE(EVP_HPKE_KEY_generate(key.get(), kem));
347 uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
348 size_t public_key_r_len;
349 ASSERT_TRUE(EVP_HPKE_KEY_public_key(key.get(), public_key_r,
350 &public_key_r_len, sizeof(public_key_r)));
351
352 // Generate the sender's keypair, for auth modes.
353 ScopedEVP_HPKE_KEY sender_key;
354 ASSERT_TRUE(
355 EVP_HPKE_KEY_generate(sender_key.get(), kem));
356 uint8_t public_key_s[X25519_PUBLIC_VALUE_LEN];
357 size_t public_key_s_len;
358 ASSERT_TRUE(EVP_HPKE_KEY_public_key(sender_key.get(), public_key_s,
359 &public_key_s_len, sizeof(public_key_r)));
360
361 for (const auto kdf : kAllKDFs) {
362 SCOPED_TRACE(EVP_HPKE_KDF_id(kdf()));
363 for (const auto aead : kAllAEADs) {
364 SCOPED_TRACE(EVP_HPKE_AEAD_id(aead()));
365 for (const Span<const uint8_t> &info : info_values) {
366 SCOPED_TRACE(Bytes(info));
367 for (const Span<const uint8_t> &ad : ad_values) {
368 SCOPED_TRACE(Bytes(ad));
369
370 auto check_messages = [&](EVP_HPKE_CTX *sender_ctx,
371 EVP_HPKE_CTX *recipient_ctx) {
372 const char kCleartextPayload[] = "foobar";
373
374 // Have sender encrypt message for the recipient.
375 std::vector<uint8_t> ciphertext(
376 sizeof(kCleartextPayload) +
377 EVP_HPKE_CTX_max_overhead(sender_ctx));
378 size_t ciphertext_len;
379 ASSERT_TRUE(EVP_HPKE_CTX_seal(
380 sender_ctx, ciphertext.data(), &ciphertext_len,
381 ciphertext.size(),
382 reinterpret_cast<const uint8_t *>(kCleartextPayload),
383 sizeof(kCleartextPayload), ad.data(), ad.size()));
384
385 // Have recipient decrypt the message.
386 std::vector<uint8_t> cleartext(ciphertext.size());
387 size_t cleartext_len;
388 ASSERT_TRUE(EVP_HPKE_CTX_open(recipient_ctx, cleartext.data(),
389 &cleartext_len, cleartext.size(),
390 ciphertext.data(), ciphertext_len,
391 ad.data(), ad.size()));
392
393 // Verify that decrypted message matches the original.
394 ASSERT_EQ(Bytes(cleartext.data(), cleartext_len),
395 Bytes(kCleartextPayload, sizeof(kCleartextPayload)));
396 };
397
398 // Test the base mode.
399 {
400 ScopedEVP_HPKE_CTX sender_ctx;
401 uint8_t enc[X25519_PUBLIC_VALUE_LEN];
402 size_t enc_len;
403 ASSERT_TRUE(EVP_HPKE_CTX_setup_sender(
404 sender_ctx.get(), enc, &enc_len, sizeof(enc), kem, kdf(),
405 aead(), public_key_r, public_key_r_len, info.data(),
406 info.size()));
407
408 ScopedEVP_HPKE_CTX recipient_ctx;
409 ASSERT_TRUE(EVP_HPKE_CTX_setup_recipient(
410 recipient_ctx.get(), key.get(), kdf(), aead(), enc, enc_len,
411 info.data(), info.size()));
412
413 check_messages(sender_ctx.get(), recipient_ctx.get());
414 }
415
416 // Test the auth mode.
417 {
418 ScopedEVP_HPKE_CTX sender_ctx;
419 uint8_t enc[X25519_PUBLIC_VALUE_LEN];
420 size_t enc_len;
421 ASSERT_TRUE(EVP_HPKE_CTX_setup_auth_sender(
422 sender_ctx.get(), enc, &enc_len, sizeof(enc), sender_key.get(),
423 kdf(), aead(), public_key_r, public_key_r_len, info.data(),
424 info.size()));
425
426 ScopedEVP_HPKE_CTX recipient_ctx;
427 ASSERT_TRUE(EVP_HPKE_CTX_setup_auth_recipient(
428 recipient_ctx.get(), key.get(), kdf(), aead(), enc, enc_len,
429 info.data(), info.size(), public_key_s, public_key_s_len));
430
431 check_messages(sender_ctx.get(), recipient_ctx.get());
432 }
433 }
434 }
435 }
436 }
437 }
438
439 // Verify that the DH operations inside Encap() and Decap() both fail when the
440 // public key is on a small-order point in the curve.
TEST(HPKETest,X25519EncapSmallOrderPoint)441 TEST(HPKETest, X25519EncapSmallOrderPoint) {
442 // Borrowed from X25519Test.SmallOrder.
443 static const uint8_t kSmallOrderPoint[32] = {
444 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
445 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
446 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8,
447 };
448 static const uint8_t kValidPoint[32] = {
449 0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1,
450 0xa4, 0x24, 0xb1, 0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3,
451 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c,
452 };
453
454 ScopedEVP_HPKE_KEY key;
455 ASSERT_TRUE(EVP_HPKE_KEY_generate(key.get(), EVP_hpke_x25519_hkdf_sha256()));
456
457 for (const auto kdf : kAllKDFs) {
458 SCOPED_TRACE(EVP_HPKE_KDF_id(kdf()));
459 for (const auto aead : kAllAEADs) {
460 SCOPED_TRACE(EVP_HPKE_AEAD_id(aead()));
461 // Set up the sender, passing in kSmallOrderPoint as |peer_public_key|.
462 ScopedEVP_HPKE_CTX sender_ctx;
463 uint8_t enc[X25519_PUBLIC_VALUE_LEN];
464 size_t enc_len;
465 EXPECT_FALSE(EVP_HPKE_CTX_setup_sender(
466 sender_ctx.get(), enc, &enc_len, sizeof(enc),
467 EVP_hpke_x25519_hkdf_sha256(), kdf(), aead(), kSmallOrderPoint,
468 sizeof(kSmallOrderPoint), nullptr, 0));
469
470 // Likewise with auth.
471 EXPECT_FALSE(EVP_HPKE_CTX_setup_auth_sender(
472 sender_ctx.get(), enc, &enc_len, sizeof(enc), key.get(), kdf(),
473 aead(), kSmallOrderPoint, sizeof(kSmallOrderPoint), nullptr, 0));
474
475 // Set up the recipient, passing in kSmallOrderPoint as |enc|.
476 ScopedEVP_HPKE_CTX recipient_ctx;
477 EXPECT_FALSE(EVP_HPKE_CTX_setup_recipient(
478 recipient_ctx.get(), key.get(), kdf(), aead(), kSmallOrderPoint,
479 sizeof(kSmallOrderPoint), nullptr, 0));
480
481 // Likewise with auth. With auth, a small-order point could appear as
482 // either |enc| or the peer public key.
483 EXPECT_FALSE(EVP_HPKE_CTX_setup_auth_recipient(
484 recipient_ctx.get(), key.get(), kdf(), aead(), kSmallOrderPoint,
485 sizeof(kSmallOrderPoint), nullptr, 0, kValidPoint,
486 sizeof(kValidPoint)));
487 EXPECT_FALSE(EVP_HPKE_CTX_setup_auth_recipient(
488 recipient_ctx.get(), key.get(), kdf(), aead(), kValidPoint,
489 sizeof(kValidPoint), nullptr, 0, kSmallOrderPoint,
490 sizeof(kSmallOrderPoint)));
491 }
492 }
493 }
494
495 // Test that Seal() fails when the context has been initialized as a recipient.
TEST(HPKETest,RecipientInvalidSeal)496 TEST(HPKETest, RecipientInvalidSeal) {
497 const uint8_t kMockEnc[X25519_PUBLIC_VALUE_LEN] = {0xff};
498 const char kCleartextPayload[] = "foobar";
499
500 ScopedEVP_HPKE_KEY key;
501 ASSERT_TRUE(EVP_HPKE_KEY_generate(key.get(), EVP_hpke_x25519_hkdf_sha256()));
502
503 // Set up the recipient.
504 ScopedEVP_HPKE_CTX recipient_ctx;
505 ASSERT_TRUE(EVP_HPKE_CTX_setup_recipient(
506 recipient_ctx.get(), key.get(), EVP_hpke_hkdf_sha256(),
507 EVP_hpke_aes_128_gcm(), kMockEnc, sizeof(kMockEnc), nullptr, 0));
508
509 // Call Seal() on the recipient.
510 size_t ciphertext_len;
511 uint8_t ciphertext[100];
512 ASSERT_FALSE(EVP_HPKE_CTX_seal(
513 recipient_ctx.get(), ciphertext, &ciphertext_len, sizeof(ciphertext),
514 reinterpret_cast<const uint8_t *>(kCleartextPayload),
515 sizeof(kCleartextPayload), nullptr, 0));
516 }
517
518 // Test that Open() fails when the context has been initialized as a sender.
TEST(HPKETest,SenderInvalidOpen)519 TEST(HPKETest, SenderInvalidOpen) {
520 const uint8_t kMockCiphertext[100] = {0xff};
521 const size_t kMockCiphertextLen = 80;
522
523 // Generate the recipient's keypair.
524 uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN];
525 uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
526 X25519_keypair(public_key_r, secret_key_r);
527
528 // Set up the sender.
529 ScopedEVP_HPKE_CTX sender_ctx;
530 uint8_t enc[X25519_PUBLIC_VALUE_LEN];
531 size_t enc_len;
532 ASSERT_TRUE(EVP_HPKE_CTX_setup_sender(
533 sender_ctx.get(), enc, &enc_len, sizeof(enc),
534 EVP_hpke_x25519_hkdf_sha256(), EVP_hpke_hkdf_sha256(),
535 EVP_hpke_aes_128_gcm(), public_key_r, sizeof(public_key_r), nullptr, 0));
536
537 // Call Open() on the sender.
538 uint8_t cleartext[128];
539 size_t cleartext_len;
540 ASSERT_FALSE(EVP_HPKE_CTX_open(sender_ctx.get(), cleartext, &cleartext_len,
541 sizeof(cleartext), kMockCiphertext,
542 kMockCiphertextLen, nullptr, 0));
543 }
544
TEST(HPKETest,SetupSenderBufferTooSmall)545 TEST(HPKETest, SetupSenderBufferTooSmall) {
546 uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN];
547 uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
548 X25519_keypair(public_key_r, secret_key_r);
549
550 ScopedEVP_HPKE_CTX sender_ctx;
551 uint8_t enc[X25519_PUBLIC_VALUE_LEN - 1];
552 size_t enc_len;
553 ASSERT_FALSE(EVP_HPKE_CTX_setup_sender(
554 sender_ctx.get(), enc, &enc_len, sizeof(enc),
555 EVP_hpke_x25519_hkdf_sha256(), EVP_hpke_hkdf_sha256(),
556 EVP_hpke_aes_128_gcm(), public_key_r, sizeof(public_key_r), nullptr, 0));
557 EXPECT_TRUE(
558 ErrorEquals(ERR_get_error(), ERR_LIB_EVP, EVP_R_INVALID_BUFFER_SIZE));
559 ERR_clear_error();
560 }
561
TEST(HPKETest,SetupSenderBufferTooLarge)562 TEST(HPKETest, SetupSenderBufferTooLarge) {
563 uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN];
564 uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
565 X25519_keypair(public_key_r, secret_key_r);
566
567 // Too large of an output buffer is fine because the function reports the
568 // actual length.
569 ScopedEVP_HPKE_CTX sender_ctx;
570 uint8_t enc[X25519_PUBLIC_VALUE_LEN + 1];
571 size_t enc_len;
572 EXPECT_TRUE(EVP_HPKE_CTX_setup_sender(
573 sender_ctx.get(), enc, &enc_len, sizeof(enc),
574 EVP_hpke_x25519_hkdf_sha256(), EVP_hpke_hkdf_sha256(),
575 EVP_hpke_aes_128_gcm(), public_key_r, sizeof(public_key_r), nullptr, 0));
576 EXPECT_EQ(size_t{X25519_PUBLIC_VALUE_LEN}, enc_len);
577 }
578
TEST(HPKETest,SetupRecipientWrongLengthEnc)579 TEST(HPKETest, SetupRecipientWrongLengthEnc) {
580 ScopedEVP_HPKE_KEY key;
581 ASSERT_TRUE(EVP_HPKE_KEY_generate(key.get(), EVP_hpke_x25519_hkdf_sha256()));
582
583 const uint8_t bogus_enc[X25519_PUBLIC_VALUE_LEN + 5] = {0xff};
584
585 ScopedEVP_HPKE_CTX recipient_ctx;
586 ASSERT_FALSE(EVP_HPKE_CTX_setup_recipient(
587 recipient_ctx.get(), key.get(), EVP_hpke_hkdf_sha256(),
588 EVP_hpke_aes_128_gcm(), bogus_enc, sizeof(bogus_enc), nullptr, 0));
589 EXPECT_TRUE(
590 ErrorEquals(ERR_get_error(), ERR_LIB_EVP, EVP_R_INVALID_PEER_KEY));
591 ERR_clear_error();
592 }
593
TEST(HPKETest,SetupSenderWrongLengthPeerPublicValue)594 TEST(HPKETest, SetupSenderWrongLengthPeerPublicValue) {
595 const uint8_t bogus_public_key_r[X25519_PRIVATE_KEY_LEN + 5] = {0xff};
596 ScopedEVP_HPKE_CTX sender_ctx;
597 uint8_t enc[X25519_PUBLIC_VALUE_LEN];
598 size_t enc_len;
599 ASSERT_FALSE(EVP_HPKE_CTX_setup_sender(
600 sender_ctx.get(), enc, &enc_len, sizeof(enc),
601 EVP_hpke_x25519_hkdf_sha256(), EVP_hpke_hkdf_sha256(),
602 EVP_hpke_aes_128_gcm(), bogus_public_key_r, sizeof(bogus_public_key_r),
603 nullptr, 0));
604 EXPECT_TRUE(
605 ErrorEquals(ERR_get_error(), ERR_LIB_EVP, EVP_R_INVALID_PEER_KEY));
606 ERR_clear_error();
607 }
608
TEST(HPKETest,InvalidRecipientKey)609 TEST(HPKETest, InvalidRecipientKey) {
610 const uint8_t private_key[X25519_PUBLIC_VALUE_LEN + 5] = {0xff};
611 ScopedEVP_HPKE_KEY key;
612 EXPECT_FALSE(EVP_HPKE_KEY_init(key.get(), EVP_hpke_x25519_hkdf_sha256(),
613 private_key, sizeof(private_key)));
614 }
615
TEST(HPKETest,InternalParseIntSafe)616 TEST(HPKETest, InternalParseIntSafe) {
617 uint8_t u8 = 0xff;
618 ASSERT_FALSE(ParseIntSafe(&u8, "-1"));
619
620 ASSERT_TRUE(ParseIntSafe(&u8, "0"));
621 ASSERT_EQ(u8, 0);
622
623 ASSERT_TRUE(ParseIntSafe(&u8, "255"));
624 ASSERT_EQ(u8, 255);
625
626 ASSERT_FALSE(ParseIntSafe(&u8, "256"));
627
628 uint16_t u16 = 0xffff;
629 ASSERT_TRUE(ParseIntSafe(&u16, "257"));
630 ASSERT_EQ(u16, 257);
631
632 ASSERT_TRUE(ParseIntSafe(&u16, "65535"));
633 ASSERT_EQ(u16, 65535);
634
635 ASSERT_FALSE(ParseIntSafe(&u16, "65536"));
636 }
637
638
639 } // namespace bssl
640