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 <cstdint>
16 #include <limits>
17 #include <string>
18 #include <vector>
19 
20 #include <gtest/gtest.h>
21 
22 #include <openssl/base.h>
23 #include <openssl/curve25519.h>
24 #include <openssl/digest.h>
25 #include <openssl/err.h>
26 #include <openssl/evp.h>
27 #include <openssl/sha.h>
28 #include <openssl/span.h>
29 
30 #include "../test/file_test.h"
31 #include "../test/test_util.h"
32 #include "internal.h"
33 
34 
35 namespace bssl {
36 namespace {
37 
38 enum class HPKEMode {
39   kBase = 0,
40   kPSK = 1,
41 };
42 
43 // HPKETestVector corresponds to one array member in the published
44 // test-vectors.json.
45 class HPKETestVector {
46  public:
47   explicit HPKETestVector() = default;
48   ~HPKETestVector() = default;
49 
50   bool ReadFromFileTest(FileTest *t);
51 
Verify() const52   void Verify() const {
53     ScopedEVP_HPKE_CTX sender_ctx;
54     ScopedEVP_HPKE_CTX receiver_ctx;
55 
56     switch (mode_) {
57       case HPKEMode::kBase:
58         ASSERT_GT(secret_key_e_.size(), 0u);
59         ASSERT_EQ(psk_.size(), 0u);
60         ASSERT_EQ(psk_id_.size(), 0u);
61 
62         // Set up the sender.
63         ASSERT_TRUE(EVP_HPKE_CTX_setup_base_s_x25519_for_test(
64             sender_ctx.get(), kdf_id_, aead_id_, public_key_r_.data(),
65             info_.data(), info_.size(), secret_key_e_.data(),
66             public_key_e_.data()));
67 
68         // Set up the receiver.
69         ASSERT_TRUE(EVP_HPKE_CTX_setup_base_r_x25519(
70             receiver_ctx.get(), kdf_id_, aead_id_, public_key_e_.data(),
71             public_key_r_.data(), secret_key_r_.data(), info_.data(),
72             info_.size()));
73         break;
74 
75       case HPKEMode::kPSK:
76         ASSERT_GT(secret_key_e_.size(), 0u);
77         ASSERT_GT(psk_.size(), 0u);
78         ASSERT_GT(psk_id_.size(), 0u);
79 
80         // Set up the sender.
81         ASSERT_TRUE(EVP_HPKE_CTX_setup_psk_s_x25519_for_test(
82             sender_ctx.get(), kdf_id_, aead_id_, public_key_r_.data(),
83             info_.data(), info_.size(), psk_.data(), psk_.size(),
84             psk_id_.data(), psk_id_.size(), secret_key_e_.data(),
85             public_key_e_.data()));
86 
87         // Set up the receiver.
88         ASSERT_TRUE(EVP_HPKE_CTX_setup_psk_r_x25519(
89             receiver_ctx.get(), kdf_id_, aead_id_, public_key_e_.data(),
90             public_key_r_.data(), secret_key_r_.data(), info_.data(),
91             info_.size(), psk_.data(), psk_.size(), psk_id_.data(),
92             psk_id_.size()));
93         break;
94       default:
95         FAIL() << "Unsupported mode";
96         return;
97     }
98 
99     VerifyEncryptions(sender_ctx.get(), receiver_ctx.get());
100     VerifyExports(sender_ctx.get());
101     VerifyExports(receiver_ctx.get());
102   }
103 
104  private:
VerifyEncryptions(EVP_HPKE_CTX * sender_ctx,EVP_HPKE_CTX * receiver_ctx) const105   void VerifyEncryptions(EVP_HPKE_CTX *sender_ctx,
106                          EVP_HPKE_CTX *receiver_ctx) const {
107     for (const Encryption &task : encryptions_) {
108       std::vector<uint8_t> encrypted(task.plaintext.size() +
109                                      EVP_HPKE_CTX_max_overhead(sender_ctx));
110       size_t encrypted_len;
111       ASSERT_TRUE(EVP_HPKE_CTX_seal(
112           sender_ctx, encrypted.data(), &encrypted_len, encrypted.size(),
113           task.plaintext.data(), task.plaintext.size(), task.aad.data(),
114           task.aad.size()));
115 
116       ASSERT_EQ(Bytes(encrypted.data(), encrypted_len), Bytes(task.ciphertext));
117 
118       std::vector<uint8_t> decrypted(task.ciphertext.size());
119       size_t decrypted_len;
120       ASSERT_TRUE(EVP_HPKE_CTX_open(
121           receiver_ctx, decrypted.data(), &decrypted_len, decrypted.size(),
122           task.ciphertext.data(), task.ciphertext.size(), task.aad.data(),
123           task.aad.size()));
124 
125       ASSERT_EQ(Bytes(decrypted.data(), decrypted_len), Bytes(task.plaintext));
126     }
127   }
128 
VerifyExports(EVP_HPKE_CTX * ctx) const129   void VerifyExports(EVP_HPKE_CTX *ctx) const {
130     for (const Export &task : exports_) {
131       std::vector<uint8_t> exported_secret(task.export_length);
132 
133       ASSERT_TRUE(EVP_HPKE_CTX_export(
134           ctx, exported_secret.data(), exported_secret.size(),
135           task.exporter_context.data(), task.exporter_context.size()));
136       ASSERT_EQ(Bytes(exported_secret), Bytes(task.exported_value));
137     }
138   }
139 
140   struct Encryption {
141     std::vector<uint8_t> aad;
142     std::vector<uint8_t> ciphertext;
143     std::vector<uint8_t> plaintext;
144   };
145 
146   struct Export {
147     std::vector<uint8_t> exporter_context;
148     size_t export_length;
149     std::vector<uint8_t> exported_value;
150   };
151 
152   HPKEMode mode_;
153   uint16_t kdf_id_;
154   uint16_t aead_id_;
155   std::vector<uint8_t> context_;
156   std::vector<uint8_t> info_;
157   std::vector<uint8_t> public_key_e_;
158   std::vector<uint8_t> secret_key_e_;
159   std::vector<uint8_t> public_key_r_;
160   std::vector<uint8_t> secret_key_r_;
161   std::vector<Encryption> encryptions_;
162   std::vector<Export> exports_;
163   std::vector<uint8_t> psk_;     // Empty when mode is not PSK.
164   std::vector<uint8_t> psk_id_;  // Empty when mode is not PSK.
165 };
166 
167 // Match FileTest's naming scheme for duplicated attribute names.
BuildAttrName(const std::string & name,int iter)168 std::string BuildAttrName(const std::string &name, int iter) {
169   return iter == 1 ? name : name + "/" + std::to_string(iter);
170 }
171 
172 // Parses |s| as an unsigned integer of type T and writes the value to |out|.
173 // Returns true on success. If the integer value exceeds the maximum T value,
174 // returns false.
175 template <typename T>
ParseIntSafe(T * out,const std::string & s)176 bool ParseIntSafe(T *out, const std::string &s) {
177   T value = 0;
178   for (char c : s) {
179     if (c < '0' || c > '9') {
180       return false;
181     }
182     if (value > (std::numeric_limits<T>::max() - (c - '0')) / 10) {
183       return false;
184     }
185     value = 10 * value + (c - '0');
186   }
187   *out = value;
188   return true;
189 }
190 
191 // Read the |key| attribute from |file_test| and convert it to an integer.
192 template <typename T>
FileTestReadInt(FileTest * file_test,T * out,const std::string & key)193 bool FileTestReadInt(FileTest *file_test, T *out, const std::string &key) {
194   std::string s;
195   return file_test->GetAttribute(&s, key) && ParseIntSafe(out, s);
196 }
197 
198 
ReadFromFileTest(FileTest * t)199 bool HPKETestVector::ReadFromFileTest(FileTest *t) {
200   uint8_t mode_tmp;
201   if (!FileTestReadInt(t, &mode_tmp, "mode")) {
202     return false;
203   }
204   mode_ = static_cast<HPKEMode>(mode_tmp);
205 
206   if (!FileTestReadInt(t, &kdf_id_, "kdf_id") ||
207       !FileTestReadInt(t, &aead_id_, "aead_id") ||
208       !t->GetBytes(&info_, "info") ||
209       !t->GetBytes(&secret_key_r_, "skRm") ||
210       !t->GetBytes(&public_key_r_, "pkRm") ||
211       !t->GetBytes(&secret_key_e_, "skEm") ||
212       !t->GetBytes(&public_key_e_, "pkEm")) {
213     return false;
214   }
215 
216   if (mode_ == HPKEMode::kPSK) {
217     if (!t->GetBytes(&psk_, "psk") ||
218         !t->GetBytes(&psk_id_, "psk_id")) {
219       return false;
220     }
221   }
222 
223   for (int i = 1; t->HasAttribute(BuildAttrName("aad", i)); i++) {
224     Encryption encryption;
225     if (!t->GetBytes(&encryption.aad, BuildAttrName("aad", i)) ||
226         !t->GetBytes(&encryption.ciphertext, BuildAttrName("ciphertext", i)) ||
227         !t->GetBytes(&encryption.plaintext, BuildAttrName("plaintext", i))) {
228       return false;
229     }
230     encryptions_.push_back(std::move(encryption));
231   }
232 
233   for (int i = 1; t->HasAttribute(BuildAttrName("exporter_context", i)); i++) {
234     Export exp;
235     if (!t->GetBytes(&exp.exporter_context,
236                      BuildAttrName("exporter_context", i)) ||
237         !FileTestReadInt(t, &exp.export_length, BuildAttrName("L", i)) ||
238         !t->GetBytes(&exp.exported_value, BuildAttrName("exported_value", i))) {
239       return false;
240     }
241     exports_.push_back(std::move(exp));
242   }
243   return true;
244 }
245 
246 }  // namespace
247 
TEST(HPKETest,VerifyTestVectors)248 TEST(HPKETest, VerifyTestVectors) {
249   FileTestGTest("crypto/hpke/hpke_test_vectors.txt", [](FileTest *t) {
250     HPKETestVector test_vec;
251     EXPECT_TRUE(test_vec.ReadFromFileTest(t));
252     test_vec.Verify();
253   });
254 }
255 
256 // The test vectors used fixed sender ephemeral keys, while HPKE itself
257 // generates new keys for each context. Test this codepath by checking we can
258 // decrypt our own messages.
TEST(HPKETest,RoundTrip)259 TEST(HPKETest, RoundTrip) {
260   uint16_t kdf_ids[] = {EVP_HPKE_HKDF_SHA256, EVP_HPKE_HKDF_SHA384,
261                         EVP_HPKE_HKDF_SHA512};
262   uint16_t aead_ids[] = {EVP_HPKE_AEAD_AES_GCM_128, EVP_HPKE_AEAD_AES_GCM_256,
263                          EVP_HPKE_AEAD_CHACHA20POLY1305};
264 
265   const uint8_t info_a[] = {1, 1, 2, 3, 5, 8};
266   const uint8_t info_b[] = {42, 42, 42};
267   const uint8_t ad_a[] = {1, 2, 4, 8, 16};
268   const uint8_t ad_b[] = {7};
269   Span<const uint8_t> info_values[] = {{nullptr, 0}, info_a, info_b};
270   Span<const uint8_t> ad_values[] = {{nullptr, 0}, ad_a, ad_b};
271 
272   // Generate the receiver's keypair.
273   uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN];
274   uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
275   X25519_keypair(public_key_r, secret_key_r);
276 
277   for (uint16_t kdf_id : kdf_ids) {
278     for (uint16_t aead_id : aead_ids) {
279       for (const Span<const uint8_t> &info : info_values) {
280         for (const Span<const uint8_t> &ad : ad_values) {
281           // Set up the sender.
282           ScopedEVP_HPKE_CTX sender_ctx;
283           uint8_t enc[X25519_PUBLIC_VALUE_LEN];
284           ASSERT_TRUE(EVP_HPKE_CTX_setup_base_s_x25519(
285               sender_ctx.get(), enc, kdf_id, aead_id, public_key_r, info.data(),
286               info.size()));
287 
288           // Set up the receiver.
289           ScopedEVP_HPKE_CTX receiver_ctx;
290           ASSERT_TRUE(EVP_HPKE_CTX_setup_base_r_x25519(
291               receiver_ctx.get(), kdf_id, aead_id, enc, public_key_r,
292               secret_key_r, info.data(), info.size()));
293 
294           const char kCleartextPayload[] = "foobar";
295 
296           // Have sender encrypt message for the receiver.
297           std::vector<uint8_t> ciphertext(
298               sizeof(kCleartextPayload) +
299               EVP_HPKE_CTX_max_overhead(sender_ctx.get()));
300           size_t ciphertext_len;
301           ASSERT_TRUE(EVP_HPKE_CTX_seal(
302               sender_ctx.get(), ciphertext.data(), &ciphertext_len,
303               ciphertext.size(),
304               reinterpret_cast<const uint8_t *>(kCleartextPayload),
305               sizeof(kCleartextPayload), ad.data(), ad.size()));
306 
307           // Have receiver decrypt the message.
308           std::vector<uint8_t> cleartext(ciphertext.size());
309           size_t cleartext_len;
310           ASSERT_TRUE(EVP_HPKE_CTX_open(receiver_ctx.get(), cleartext.data(),
311                                         &cleartext_len, cleartext.size(),
312                                         ciphertext.data(), ciphertext_len,
313                                         ad.data(), ad.size()));
314 
315           // Verify that decrypted message matches the original.
316           ASSERT_EQ(Bytes(cleartext.data(), cleartext_len),
317                     Bytes(kCleartextPayload, sizeof(kCleartextPayload)));
318         }
319       }
320     }
321   }
322 }
323 
324 // Verify that the DH operations inside Encap() and Decap() both fail when the
325 // public key is on a small-order point in the curve.
TEST(HPKETest,X25519EncapSmallOrderPoint)326 TEST(HPKETest, X25519EncapSmallOrderPoint) {
327   // Borrowed from X25519Test.SmallOrder.
328   static const uint8_t kSmallOrderPoint[32] = {
329       0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
330       0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
331       0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8,
332   };
333 
334   // Generate a valid keypair for the receiver.
335   uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN];
336   uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
337   X25519_keypair(public_key_r, secret_key_r);
338 
339   uint16_t kdf_ids[] = {EVP_HPKE_HKDF_SHA256, EVP_HPKE_HKDF_SHA384,
340                         EVP_HPKE_HKDF_SHA512};
341   uint16_t aead_ids[] = {EVP_HPKE_AEAD_AES_GCM_128, EVP_HPKE_AEAD_AES_GCM_256,
342                          EVP_HPKE_AEAD_CHACHA20POLY1305};
343 
344   for (uint16_t kdf_id : kdf_ids) {
345     for (uint16_t aead_id : aead_ids) {
346       // Set up the sender, passing in kSmallOrderPoint as |peer_public_value|.
347       ScopedEVP_HPKE_CTX sender_ctx;
348       uint8_t enc[X25519_PUBLIC_VALUE_LEN];
349       ASSERT_FALSE(EVP_HPKE_CTX_setup_base_s_x25519(
350           sender_ctx.get(), enc, kdf_id, aead_id, kSmallOrderPoint, nullptr,
351           0));
352 
353       // Set up the receiver, passing in kSmallOrderPoint as |enc|.
354       ScopedEVP_HPKE_CTX receiver_ctx;
355       ASSERT_FALSE(EVP_HPKE_CTX_setup_base_r_x25519(
356           receiver_ctx.get(), kdf_id, aead_id, kSmallOrderPoint, public_key_r,
357           secret_key_r, nullptr, 0));
358     }
359   }
360 }
361 
362 // Test that Seal() fails when the context has been initialized as a receiver.
TEST(HPKETest,ReceiverInvalidSeal)363 TEST(HPKETest, ReceiverInvalidSeal) {
364   const uint8_t kMockEnc[X25519_PUBLIC_VALUE_LEN] = {0xff};
365   const char kCleartextPayload[] = "foobar";
366 
367   // Generate the receiver's keypair.
368   uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN];
369   uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
370   X25519_keypair(public_key_r, secret_key_r);
371 
372   // Set up the receiver.
373   ScopedEVP_HPKE_CTX receiver_ctx;
374   ASSERT_TRUE(EVP_HPKE_CTX_setup_base_r_x25519(
375       receiver_ctx.get(), EVP_HPKE_HKDF_SHA256, EVP_HPKE_AEAD_AES_GCM_128,
376       kMockEnc, public_key_r, secret_key_r, nullptr, 0));
377 
378   // Call Seal() on the receiver.
379   size_t ciphertext_len;
380   uint8_t ciphertext[100];
381   ASSERT_FALSE(EVP_HPKE_CTX_seal(
382       receiver_ctx.get(), ciphertext, &ciphertext_len, sizeof(ciphertext),
383       reinterpret_cast<const uint8_t *>(kCleartextPayload),
384       sizeof(kCleartextPayload), nullptr, 0));
385 }
386 
387 // Test that Open() fails when the context has been initialized as a sender.
TEST(HPKETest,SenderInvalidOpen)388 TEST(HPKETest, SenderInvalidOpen) {
389   const uint8_t kMockCiphertext[100] = {0xff};
390   const size_t kMockCiphertextLen = 80;
391 
392   // Generate the receiver's keypair.
393   uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN];
394   uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
395   X25519_keypair(public_key_r, secret_key_r);
396 
397   // Set up the sender.
398   ScopedEVP_HPKE_CTX sender_ctx;
399   uint8_t enc[X25519_PUBLIC_VALUE_LEN];
400   ASSERT_TRUE(EVP_HPKE_CTX_setup_base_s_x25519(
401       sender_ctx.get(), enc, EVP_HPKE_HKDF_SHA256, EVP_HPKE_AEAD_AES_GCM_128,
402       public_key_r, nullptr, 0));
403 
404   // Call Open() on the sender.
405   uint8_t cleartext[128];
406   size_t cleartext_len;
407   ASSERT_FALSE(EVP_HPKE_CTX_open(sender_ctx.get(), cleartext, &cleartext_len,
408                                  sizeof(cleartext), kMockCiphertext,
409                                  kMockCiphertextLen, nullptr, 0));
410 }
411 
412 // Test that the PSK variants of Setup functions fail when any of the PSK inputs
413 // are empty.
TEST(HPKETest,EmptyPSK)414 TEST(HPKETest, EmptyPSK) {
415   const uint8_t kMockEnc[X25519_PUBLIC_VALUE_LEN] = {0xff};
416   const std::vector<uint8_t> kPSKValues[] = {std::vector<uint8_t>(100, 0xff),
417                                              {}};
418 
419   // Generate the receiver's keypair.
420   uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN];
421   uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
422   X25519_keypair(public_key_r, secret_key_r);
423 
424   // Vary the PSK and PSKID inputs for the sender and receiver, trying all four
425   // permutations of empty and nonempty inputs.
426 
427   for (const auto &psk : kPSKValues) {
428     for (const auto &psk_id : kPSKValues) {
429       const bool kExpectSuccess = psk.size() > 0 && psk_id.size() > 0;
430 
431       ASSERT_EQ(ERR_get_error(), 0u);
432 
433       ScopedEVP_HPKE_CTX sender_ctx;
434       uint8_t enc[X25519_PUBLIC_VALUE_LEN];
435       ASSERT_EQ(EVP_HPKE_CTX_setup_psk_s_x25519(
436                     sender_ctx.get(), enc, EVP_HPKE_HKDF_SHA256,
437                     EVP_HPKE_AEAD_AES_GCM_128, public_key_r, nullptr, 0,
438                     psk.data(), psk.size(), psk_id.data(), psk_id.size()),
439                 kExpectSuccess);
440 
441       if (!kExpectSuccess) {
442         uint32_t err = ERR_get_error();
443         EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
444         EXPECT_EQ(EVP_R_EMPTY_PSK, ERR_GET_REASON(err));
445       }
446       ERR_clear_error();
447 
448       ScopedEVP_HPKE_CTX receiver_ctx;
449       ASSERT_EQ(
450           EVP_HPKE_CTX_setup_psk_r_x25519(
451               receiver_ctx.get(), EVP_HPKE_HKDF_SHA256,
452               EVP_HPKE_AEAD_AES_GCM_128, kMockEnc, public_key_r, secret_key_r,
453               nullptr, 0, psk.data(), psk.size(), psk_id.data(), psk_id.size()),
454           kExpectSuccess);
455 
456       if (!kExpectSuccess) {
457         uint32_t err = ERR_get_error();
458         EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
459         EXPECT_EQ(EVP_R_EMPTY_PSK, ERR_GET_REASON(err));
460       }
461       ERR_clear_error();
462     }
463   }
464 }
465 
TEST(HPKETest,InternalParseIntSafe)466 TEST(HPKETest, InternalParseIntSafe) {
467   uint8_t u8 = 0xff;
468   ASSERT_FALSE(ParseIntSafe(&u8, "-1"));
469 
470   ASSERT_TRUE(ParseIntSafe(&u8, "0"));
471   ASSERT_EQ(u8, 0);
472 
473   ASSERT_TRUE(ParseIntSafe(&u8, "255"));
474   ASSERT_EQ(u8, 255);
475 
476   ASSERT_FALSE(ParseIntSafe(&u8, "256"));
477 
478   uint16_t u16 = 0xffff;
479   ASSERT_TRUE(ParseIntSafe(&u16, "257"));
480   ASSERT_EQ(u16, 257);
481 
482   ASSERT_TRUE(ParseIntSafe(&u16, "65535"));
483   ASSERT_EQ(u16, 65535);
484 
485   ASSERT_FALSE(ParseIntSafe(&u16, "65536"));
486 }
487 
488 
489 }  // namespace bssl
490