xref: /aosp_15_r20/external/boringssl/src/crypto/hpke/hpke_test.cc (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
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