• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2014, 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 <stdint.h>
16 #include <string.h>
17 
18 #include <vector>
19 
20 #include <gtest/gtest.h>
21 
22 #include <openssl/aead.h>
23 #include <openssl/cipher.h>
24 #include <openssl/err.h>
25 
26 #include "../fipsmodule/cipher/internal.h"
27 #include "../internal.h"
28 #include "../test/file_test.h"
29 #include "../test/test_util.h"
30 #include "../test/wycheproof_util.h"
31 
32 
33 struct KnownAEAD {
34   const char name[40];
35   const EVP_AEAD *(*func)(void);
36   const char *test_vectors;
37   // limited_implementation indicates that tests that assume a generic AEAD
38   // interface should not be performed. For example, the key-wrap AEADs only
39   // handle inputs that are a multiple of eight bytes in length and the TLS CBC
40   // AEADs have the concept of “direction”.
41   bool limited_implementation;
42   // truncated_tags is true if the AEAD supports truncating tags to arbitrary
43   // lengths.
44   bool truncated_tags;
45   // variable_nonce is true if the AEAD supports a variable nonce length.
46   bool variable_nonce;
47   // ad_len, if non-zero, is the required length of the AD.
48   size_t ad_len;
49 };
50 
51 static const struct KnownAEAD kAEADs[] = {
52     {"AES_128_GCM", EVP_aead_aes_128_gcm, "aes_128_gcm_tests.txt", false, true,
53      true, 0},
54     {"AES_128_GCM_NIST", EVP_aead_aes_128_gcm, "nist_cavp/aes_128_gcm.txt",
55      false, true, true, 0},
56     {"AES_192_GCM", EVP_aead_aes_192_gcm, "aes_192_gcm_tests.txt", false, true,
57      true, 0},
58     {"AES_256_GCM", EVP_aead_aes_256_gcm, "aes_256_gcm_tests.txt", false, true,
59      true, 0},
60     {"AES_256_GCM_NIST", EVP_aead_aes_256_gcm, "nist_cavp/aes_256_gcm.txt",
61      false, true, true, 0},
62     {"AES_128_GCM_SIV", EVP_aead_aes_128_gcm_siv, "aes_128_gcm_siv_tests.txt",
63      false, false, false, 0},
64     {"AES_256_GCM_SIV", EVP_aead_aes_256_gcm_siv, "aes_256_gcm_siv_tests.txt",
65      false, false, false, 0},
66     {"ChaCha20Poly1305", EVP_aead_chacha20_poly1305,
67      "chacha20_poly1305_tests.txt", false, true, false, 0},
68     {"XChaCha20Poly1305", EVP_aead_xchacha20_poly1305,
69      "xchacha20_poly1305_tests.txt", false, true, false, 0},
70     {"AES_128_CBC_SHA1_TLS", EVP_aead_aes_128_cbc_sha1_tls,
71      "aes_128_cbc_sha1_tls_tests.txt", true, false, false, 11},
72     {"AES_128_CBC_SHA1_TLSImplicitIV",
73      EVP_aead_aes_128_cbc_sha1_tls_implicit_iv,
74      "aes_128_cbc_sha1_tls_implicit_iv_tests.txt", true, false, false, 11},
75     {"AES_128_CBC_SHA256_TLS", EVP_aead_aes_128_cbc_sha256_tls,
76      "aes_128_cbc_sha256_tls_tests.txt", true, false, false, 11},
77     {"AES_256_CBC_SHA1_TLS", EVP_aead_aes_256_cbc_sha1_tls,
78      "aes_256_cbc_sha1_tls_tests.txt", true, false, false, 11},
79     {"AES_256_CBC_SHA1_TLSImplicitIV",
80      EVP_aead_aes_256_cbc_sha1_tls_implicit_iv,
81      "aes_256_cbc_sha1_tls_implicit_iv_tests.txt", true, false, false, 11},
82     {"AES_256_CBC_SHA256_TLS", EVP_aead_aes_256_cbc_sha256_tls,
83      "aes_256_cbc_sha256_tls_tests.txt", true, false, false, 11},
84     {"AES_256_CBC_SHA384_TLS", EVP_aead_aes_256_cbc_sha384_tls,
85      "aes_256_cbc_sha384_tls_tests.txt", true, false, false, 11},
86     {"DES_EDE3_CBC_SHA1_TLS", EVP_aead_des_ede3_cbc_sha1_tls,
87      "des_ede3_cbc_sha1_tls_tests.txt", true, false, false, 11},
88     {"DES_EDE3_CBC_SHA1_TLSImplicitIV",
89      EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv,
90      "des_ede3_cbc_sha1_tls_implicit_iv_tests.txt", true, false, false, 11},
91     {"AES_128_CTR_HMAC_SHA256", EVP_aead_aes_128_ctr_hmac_sha256,
92      "aes_128_ctr_hmac_sha256.txt", false, true, false, 0},
93     {"AES_256_CTR_HMAC_SHA256", EVP_aead_aes_256_ctr_hmac_sha256,
94      "aes_256_ctr_hmac_sha256.txt", false, true, false, 0},
95     {"AES_128_CCM_BLUETOOTH", EVP_aead_aes_128_ccm_bluetooth,
96      "aes_128_ccm_bluetooth_tests.txt", false, false, false, 0},
97     {"AES_128_CCM_BLUETOOTH_8", EVP_aead_aes_128_ccm_bluetooth_8,
98      "aes_128_ccm_bluetooth_8_tests.txt", false, false, false, 0},
99 };
100 
101 class PerAEADTest : public testing::TestWithParam<KnownAEAD> {
102  public:
aead()103   const EVP_AEAD *aead() { return GetParam().func(); }
104 };
105 
106 INSTANTIATE_TEST_SUITE_P(All, PerAEADTest, testing::ValuesIn(kAEADs),
107                          [](const testing::TestParamInfo<KnownAEAD> &params)
__anon383ad5bb0102(const testing::TestParamInfo<KnownAEAD> &params) 108                              -> std::string { return params.param.name; });
109 
110 // Tests an AEAD against a series of test vectors from a file, using the
111 // FileTest format. As an example, here's a valid test case:
112 //
113 //   KEY: 5a19f3173586b4c42f8412f4d5a786531b3231753e9e00998aec12fda8df10e4
114 //   NONCE: 978105dfce667bf4
115 //   IN: 6a4583908d
116 //   AD: b654574932
117 //   CT: 5294265a60
118 //   TAG: 1d45758621762e061368e68868e2f929
TEST_P(PerAEADTest,TestVector)119 TEST_P(PerAEADTest, TestVector) {
120   std::string test_vectors = "crypto/cipher_extra/test/";
121   test_vectors += GetParam().test_vectors;
122   FileTestGTest(test_vectors.c_str(), [&](FileTest *t) {
123     std::vector<uint8_t> key, nonce, in, ad, ct, tag;
124     ASSERT_TRUE(t->GetBytes(&key, "KEY"));
125     ASSERT_TRUE(t->GetBytes(&nonce, "NONCE"));
126     ASSERT_TRUE(t->GetBytes(&in, "IN"));
127     ASSERT_TRUE(t->GetBytes(&ad, "AD"));
128     ASSERT_TRUE(t->GetBytes(&ct, "CT"));
129     ASSERT_TRUE(t->GetBytes(&tag, "TAG"));
130     size_t tag_len = tag.size();
131     if (t->HasAttribute("TAG_LEN")) {
132       // Legacy AEADs are MAC-then-encrypt and may include padding in the TAG
133       // field. TAG_LEN contains the actual size of the digest in that case.
134       std::string tag_len_str;
135       ASSERT_TRUE(t->GetAttribute(&tag_len_str, "TAG_LEN"));
136       tag_len = strtoul(tag_len_str.c_str(), nullptr, 10);
137       ASSERT_TRUE(tag_len);
138     }
139 
140     bssl::ScopedEVP_AEAD_CTX ctx;
141     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
142         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_seal));
143 
144     std::vector<uint8_t> out(in.size() + EVP_AEAD_max_overhead(aead()));
145     if (!t->HasAttribute("NO_SEAL")) {
146       size_t out_len;
147       ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
148                                     nonce.data(), nonce.size(), in.data(),
149                                     in.size(), ad.data(), ad.size()));
150       out.resize(out_len);
151 
152       ASSERT_EQ(out.size(), ct.size() + tag.size());
153       EXPECT_EQ(Bytes(ct), Bytes(out.data(), ct.size()));
154       EXPECT_EQ(Bytes(tag), Bytes(out.data() + ct.size(), tag.size()));
155     } else {
156       out.resize(ct.size() + tag.size());
157       OPENSSL_memcpy(out.data(), ct.data(), ct.size());
158       OPENSSL_memcpy(out.data() + ct.size(), tag.data(), tag.size());
159     }
160 
161     // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
162     // reset after each operation.
163     ctx.Reset();
164     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
165         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
166 
167     std::vector<uint8_t> out2(out.size());
168     size_t out2_len;
169     int ret = EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(),
170                                 nonce.data(), nonce.size(), out.data(),
171                                 out.size(), ad.data(), ad.size());
172     if (t->HasAttribute("FAILS")) {
173       ASSERT_FALSE(ret) << "Decrypted bad data.";
174       ERR_clear_error();
175       return;
176     }
177 
178     ASSERT_TRUE(ret) << "Failed to decrypt.";
179     out2.resize(out2_len);
180     EXPECT_EQ(Bytes(in), Bytes(out2));
181 
182     // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
183     // reset after each operation.
184     ctx.Reset();
185     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
186         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
187 
188     // Garbage at the end isn't ignored.
189     out.push_back(0);
190     out2.resize(out.size());
191     EXPECT_FALSE(EVP_AEAD_CTX_open(
192         ctx.get(), out2.data(), &out2_len, out2.size(), nonce.data(),
193         nonce.size(), out.data(), out.size(), ad.data(), ad.size()))
194         << "Decrypted bad data with trailing garbage.";
195     ERR_clear_error();
196 
197     // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
198     // reset after each operation.
199     ctx.Reset();
200     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
201         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
202 
203     // Verify integrity is checked.
204     out[0] ^= 0x80;
205     out.resize(out.size() - 1);
206     out2.resize(out.size());
207     EXPECT_FALSE(EVP_AEAD_CTX_open(
208         ctx.get(), out2.data(), &out2_len, out2.size(), nonce.data(),
209         nonce.size(), out.data(), out.size(), ad.data(), ad.size()))
210         << "Decrypted bad data with corrupted byte.";
211     ERR_clear_error();
212   });
213 }
214 
TEST_P(PerAEADTest,TestExtraInput)215 TEST_P(PerAEADTest, TestExtraInput) {
216   const KnownAEAD &aead_config = GetParam();
217   if (!aead()->seal_scatter_supports_extra_in) {
218     return;
219   }
220 
221   const std::string test_vectors =
222       "crypto/cipher_extra/test/" + std::string(aead_config.test_vectors);
223   FileTestGTest(test_vectors.c_str(), [&](FileTest *t) {
224     if (t->HasAttribute("NO_SEAL") ||
225         t->HasAttribute("FAILS")) {
226       t->SkipCurrent();
227       return;
228     }
229 
230     std::vector<uint8_t> key, nonce, in, ad, ct, tag;
231     ASSERT_TRUE(t->GetBytes(&key, "KEY"));
232     ASSERT_TRUE(t->GetBytes(&nonce, "NONCE"));
233     ASSERT_TRUE(t->GetBytes(&in, "IN"));
234     ASSERT_TRUE(t->GetBytes(&ad, "AD"));
235     ASSERT_TRUE(t->GetBytes(&ct, "CT"));
236     ASSERT_TRUE(t->GetBytes(&tag, "TAG"));
237 
238     bssl::ScopedEVP_AEAD_CTX ctx;
239     ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead(), key.data(), key.size(),
240                                   tag.size(), nullptr));
241     std::vector<uint8_t> out_tag(EVP_AEAD_max_overhead(aead()) + in.size());
242     std::vector<uint8_t> out(in.size());
243 
244     for (size_t extra_in_size = 0; extra_in_size < in.size(); extra_in_size++) {
245       size_t tag_bytes_written;
246       SCOPED_TRACE(extra_in_size);
247       ASSERT_TRUE(EVP_AEAD_CTX_seal_scatter(
248           ctx.get(), out.data(), out_tag.data(), &tag_bytes_written,
249           out_tag.size(), nonce.data(), nonce.size(), in.data(),
250           in.size() - extra_in_size, in.data() + in.size() - extra_in_size,
251           extra_in_size, ad.data(), ad.size()));
252 
253       ASSERT_EQ(tag_bytes_written, extra_in_size + tag.size());
254 
255       memcpy(out.data() + in.size() - extra_in_size, out_tag.data(),
256              extra_in_size);
257 
258       EXPECT_EQ(Bytes(ct), Bytes(out.data(), in.size()));
259       EXPECT_EQ(Bytes(tag), Bytes(out_tag.data() + extra_in_size,
260                                   tag_bytes_written - extra_in_size));
261     }
262   });
263 }
264 
TEST_P(PerAEADTest,TestVectorScatterGather)265 TEST_P(PerAEADTest, TestVectorScatterGather) {
266   std::string test_vectors = "crypto/cipher_extra/test/";
267   const KnownAEAD &aead_config = GetParam();
268   test_vectors += aead_config.test_vectors;
269   FileTestGTest(test_vectors.c_str(), [&](FileTest *t) {
270     std::vector<uint8_t> key, nonce, in, ad, ct, tag;
271     ASSERT_TRUE(t->GetBytes(&key, "KEY"));
272     ASSERT_TRUE(t->GetBytes(&nonce, "NONCE"));
273     ASSERT_TRUE(t->GetBytes(&in, "IN"));
274     ASSERT_TRUE(t->GetBytes(&ad, "AD"));
275     ASSERT_TRUE(t->GetBytes(&ct, "CT"));
276     ASSERT_TRUE(t->GetBytes(&tag, "TAG"));
277     size_t tag_len = tag.size();
278     if (t->HasAttribute("TAG_LEN")) {
279       // Legacy AEADs are MAC-then-encrypt and may include padding in the TAG
280       // field. TAG_LEN contains the actual size of the digest in that case.
281       std::string tag_len_str;
282       ASSERT_TRUE(t->GetAttribute(&tag_len_str, "TAG_LEN"));
283       tag_len = strtoul(tag_len_str.c_str(), nullptr, 10);
284       ASSERT_TRUE(tag_len);
285     }
286 
287     bssl::ScopedEVP_AEAD_CTX ctx;
288     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
289         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_seal));
290 
291     std::vector<uint8_t> out(in.size());
292     std::vector<uint8_t> out_tag(EVP_AEAD_max_overhead(aead()));
293     if (!t->HasAttribute("NO_SEAL")) {
294       size_t out_tag_len;
295       ASSERT_TRUE(EVP_AEAD_CTX_seal_scatter(
296           ctx.get(), out.data(), out_tag.data(), &out_tag_len, out_tag.size(),
297           nonce.data(), nonce.size(), in.data(), in.size(), nullptr, 0,
298           ad.data(), ad.size()));
299       out_tag.resize(out_tag_len);
300 
301       ASSERT_EQ(out.size(), ct.size());
302       ASSERT_EQ(out_tag.size(), tag.size());
303       EXPECT_EQ(Bytes(ct), Bytes(out.data(), ct.size()));
304       EXPECT_EQ(Bytes(tag), Bytes(out_tag.data(), tag.size()));
305     } else {
306       out.resize(ct.size());
307       out_tag.resize(tag.size());
308       OPENSSL_memcpy(out.data(), ct.data(), ct.size());
309       OPENSSL_memcpy(out_tag.data(), tag.data(), tag.size());
310     }
311 
312     // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
313     // reset after each operation.
314     ctx.Reset();
315     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
316         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
317 
318     std::vector<uint8_t> out2(out.size());
319     int ret = EVP_AEAD_CTX_open_gather(
320         ctx.get(), out2.data(), nonce.data(), nonce.size(), out.data(),
321         out.size(), out_tag.data(), out_tag.size(), ad.data(), ad.size());
322 
323     // Skip decryption for AEADs that don't implement open_gather().
324     if (!ret) {
325       int err = ERR_peek_error();
326       if (ERR_GET_LIB(err) == ERR_LIB_CIPHER &&
327           ERR_GET_REASON(err) == CIPHER_R_CTRL_NOT_IMPLEMENTED) {
328           t->SkipCurrent();
329           return;
330         }
331     }
332 
333     if (t->HasAttribute("FAILS")) {
334       ASSERT_FALSE(ret) << "Decrypted bad data";
335       ERR_clear_error();
336       return;
337     }
338 
339     ASSERT_TRUE(ret) << "Failed to decrypt: "
340                      << ERR_reason_error_string(ERR_get_error());
341     EXPECT_EQ(Bytes(in), Bytes(out2));
342 
343     // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
344     // reset after each operation.
345     ctx.Reset();
346     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
347         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
348 
349     // Garbage at the end isn't ignored.
350     out_tag.push_back(0);
351     out2.resize(out.size());
352     EXPECT_FALSE(EVP_AEAD_CTX_open_gather(
353         ctx.get(), out2.data(), nonce.data(), nonce.size(), out.data(),
354         out.size(), out_tag.data(), out_tag.size(), ad.data(), ad.size()))
355         << "Decrypted bad data with trailing garbage.";
356     ERR_clear_error();
357 
358     // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
359     // reset after each operation.
360     ctx.Reset();
361     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
362         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
363 
364     // Verify integrity is checked.
365     out_tag[0] ^= 0x80;
366     out_tag.resize(out_tag.size() - 1);
367     out2.resize(out.size());
368     EXPECT_FALSE(EVP_AEAD_CTX_open_gather(
369         ctx.get(), out2.data(), nonce.data(), nonce.size(), out.data(),
370         out.size(), out_tag.data(), out_tag.size(), ad.data(), ad.size()))
371         << "Decrypted bad data with corrupted byte.";
372     ERR_clear_error();
373 
374     ctx.Reset();
375     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
376         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
377 
378     // Check edge case for tag length.
379     EXPECT_FALSE(EVP_AEAD_CTX_open_gather(
380         ctx.get(), out2.data(), nonce.data(), nonce.size(), out.data(),
381         out.size(), out_tag.data(), 0, ad.data(), ad.size()))
382         << "Decrypted bad data with corrupted byte.";
383     ERR_clear_error();
384   });
385 }
386 
TEST_P(PerAEADTest,CleanupAfterInitFailure)387 TEST_P(PerAEADTest, CleanupAfterInitFailure) {
388   uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
389   OPENSSL_memset(key, 0, sizeof(key));
390   const size_t key_len = EVP_AEAD_key_length(aead());
391   ASSERT_GE(sizeof(key), key_len);
392 
393   EVP_AEAD_CTX ctx;
394   ASSERT_FALSE(EVP_AEAD_CTX_init(
395       &ctx, aead(), key, key_len,
396       9999 /* a silly tag length to trigger an error */, NULL /* ENGINE */));
397   ERR_clear_error();
398 
399   // Running a second, failed _init should not cause a memory leak.
400   ASSERT_FALSE(EVP_AEAD_CTX_init(
401       &ctx, aead(), key, key_len,
402       9999 /* a silly tag length to trigger an error */, NULL /* ENGINE */));
403   ERR_clear_error();
404 
405   // Calling _cleanup on an |EVP_AEAD_CTX| after a failed _init should be a
406   // no-op.
407   EVP_AEAD_CTX_cleanup(&ctx);
408 }
409 
TEST_P(PerAEADTest,TruncatedTags)410 TEST_P(PerAEADTest, TruncatedTags) {
411   if (!GetParam().truncated_tags) {
412     return;
413   }
414 
415   uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
416   OPENSSL_memset(key, 0, sizeof(key));
417   const size_t key_len = EVP_AEAD_key_length(aead());
418   ASSERT_GE(sizeof(key), key_len);
419 
420   uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
421   OPENSSL_memset(nonce, 0, sizeof(nonce));
422   const size_t nonce_len = EVP_AEAD_nonce_length(aead());
423   ASSERT_GE(sizeof(nonce), nonce_len);
424 
425   bssl::ScopedEVP_AEAD_CTX ctx;
426   ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead(), key, key_len,
427                                 1 /* one byte tag */, NULL /* ENGINE */));
428 
429   const uint8_t plaintext[1] = {'A'};
430 
431   uint8_t ciphertext[128];
432   size_t ciphertext_len;
433   constexpr uint8_t kSentinel = 42;
434   OPENSSL_memset(ciphertext, kSentinel, sizeof(ciphertext));
435 
436   ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), ciphertext, &ciphertext_len,
437                                 sizeof(ciphertext), nonce, nonce_len, plaintext,
438                                 sizeof(plaintext), nullptr /* ad */, 0));
439 
440   for (size_t i = ciphertext_len; i < sizeof(ciphertext); i++) {
441     // Sealing must not write past where it said it did.
442     EXPECT_EQ(kSentinel, ciphertext[i])
443         << "Sealing wrote off the end of the buffer.";
444   }
445 
446   const size_t overhead_used = ciphertext_len - sizeof(plaintext);
447   const size_t expected_overhead =
448       1 + EVP_AEAD_max_overhead(aead()) - EVP_AEAD_max_tag_len(aead());
449   EXPECT_EQ(overhead_used, expected_overhead)
450       << "AEAD is probably ignoring request to truncate tags.";
451 
452   uint8_t plaintext2[sizeof(plaintext) + 16];
453   OPENSSL_memset(plaintext2, kSentinel, sizeof(plaintext2));
454 
455   size_t plaintext2_len;
456   ASSERT_TRUE(EVP_AEAD_CTX_open(
457       ctx.get(), plaintext2, &plaintext2_len, sizeof(plaintext2), nonce,
458       nonce_len, ciphertext, ciphertext_len, nullptr /* ad */, 0))
459       << "Opening with truncated tag didn't work.";
460 
461   for (size_t i = plaintext2_len; i < sizeof(plaintext2); i++) {
462     // Likewise, opening should also stay within bounds.
463     EXPECT_EQ(kSentinel, plaintext2[i])
464         << "Opening wrote off the end of the buffer.";
465   }
466 
467   EXPECT_EQ(Bytes(plaintext), Bytes(plaintext2, plaintext2_len));
468 }
469 
TEST_P(PerAEADTest,AliasedBuffers)470 TEST_P(PerAEADTest, AliasedBuffers) {
471   if (GetParam().limited_implementation) {
472     return;
473   }
474 
475   const size_t key_len = EVP_AEAD_key_length(aead());
476   const size_t nonce_len = EVP_AEAD_nonce_length(aead());
477   const size_t max_overhead = EVP_AEAD_max_overhead(aead());
478 
479   std::vector<uint8_t> key(key_len, 'a');
480   bssl::ScopedEVP_AEAD_CTX ctx;
481   ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead(), key.data(), key_len,
482                                 EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
483 
484   static const uint8_t kPlaintext[260] =
485       "testing123456testing123456testing123456testing123456testing123456testing"
486       "123456testing123456testing123456testing123456testing123456testing123456t"
487       "esting123456testing123456testing123456testing123456testing123456testing1"
488       "23456testing123456testing123456testing12345";
489   const std::vector<size_t> offsets = {
490       0,  1,  2,  8,  15, 16,  17,  31,  32,  33,  63,
491       64, 65, 95, 96, 97, 127, 128, 129, 255, 256, 257,
492   };
493 
494   std::vector<uint8_t> nonce(nonce_len, 'b');
495   std::vector<uint8_t> valid_encryption(sizeof(kPlaintext) + max_overhead);
496   size_t valid_encryption_len;
497   ASSERT_TRUE(EVP_AEAD_CTX_seal(
498       ctx.get(), valid_encryption.data(), &valid_encryption_len,
499       sizeof(kPlaintext) + max_overhead, nonce.data(), nonce_len, kPlaintext,
500       sizeof(kPlaintext), nullptr, 0))
501       << "EVP_AEAD_CTX_seal failed with disjoint buffers.";
502 
503   // Test with out != in which we expect to fail.
504   std::vector<uint8_t> buffer(2 + valid_encryption_len);
505   uint8_t *in = buffer.data() + 1;
506   uint8_t *out1 = buffer.data();
507   uint8_t *out2 = buffer.data() + 2;
508 
509   OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
510   size_t out_len;
511   EXPECT_FALSE(EVP_AEAD_CTX_seal(
512       ctx.get(), out1 /* in - 1 */, &out_len, sizeof(kPlaintext) + max_overhead,
513       nonce.data(), nonce_len, in, sizeof(kPlaintext), nullptr, 0));
514   EXPECT_FALSE(EVP_AEAD_CTX_seal(
515       ctx.get(), out2 /* in + 1 */, &out_len, sizeof(kPlaintext) + max_overhead,
516       nonce.data(), nonce_len, in, sizeof(kPlaintext), nullptr, 0));
517   ERR_clear_error();
518 
519   OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
520   EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), out1 /* in - 1 */, &out_len,
521                                  valid_encryption_len, nonce.data(), nonce_len,
522                                  in, valid_encryption_len, nullptr, 0));
523   EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), out2 /* in + 1 */, &out_len,
524                                  valid_encryption_len, nonce.data(), nonce_len,
525                                  in, valid_encryption_len, nullptr, 0));
526   ERR_clear_error();
527 
528   // Test with out == in, which we expect to work.
529   OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
530 
531   ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), in, &out_len,
532                                 sizeof(kPlaintext) + max_overhead, nonce.data(),
533                                 nonce_len, in, sizeof(kPlaintext), nullptr, 0));
534   EXPECT_EQ(Bytes(valid_encryption.data(), valid_encryption_len),
535             Bytes(in, out_len));
536 
537   OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
538   ASSERT_TRUE(EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len,
539                                 nonce.data(), nonce_len, in,
540                                 valid_encryption_len, nullptr, 0));
541   EXPECT_EQ(Bytes(kPlaintext), Bytes(in, out_len));
542 }
543 
TEST_P(PerAEADTest,UnalignedInput)544 TEST_P(PerAEADTest, UnalignedInput) {
545   alignas(64) uint8_t key[EVP_AEAD_MAX_KEY_LENGTH + 1];
546   alignas(64) uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH + 1];
547   alignas(64) uint8_t plaintext[32 + 1];
548   alignas(64) uint8_t ad[32 + 1];
549   OPENSSL_memset(key, 'K', sizeof(key));
550   OPENSSL_memset(nonce, 'N', sizeof(nonce));
551   OPENSSL_memset(plaintext, 'P', sizeof(plaintext));
552   OPENSSL_memset(ad, 'A', sizeof(ad));
553   const size_t key_len = EVP_AEAD_key_length(aead());
554   ASSERT_GE(sizeof(key) - 1, key_len);
555   const size_t nonce_len = EVP_AEAD_nonce_length(aead());
556   ASSERT_GE(sizeof(nonce) - 1, nonce_len);
557   const size_t ad_len =
558       GetParam().ad_len != 0 ? GetParam().ad_len : sizeof(ad) - 1;
559   ASSERT_GE(sizeof(ad) - 1, ad_len);
560 
561   // Encrypt some input.
562   bssl::ScopedEVP_AEAD_CTX ctx;
563   ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
564       ctx.get(), aead(), key + 1, key_len, EVP_AEAD_DEFAULT_TAG_LENGTH,
565       evp_aead_seal));
566   alignas(64) uint8_t ciphertext[sizeof(plaintext) + EVP_AEAD_MAX_OVERHEAD];
567   size_t ciphertext_len;
568   ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), ciphertext + 1, &ciphertext_len,
569                                 sizeof(ciphertext) - 1, nonce + 1, nonce_len,
570                                 plaintext + 1, sizeof(plaintext) - 1, ad + 1,
571                                 ad_len));
572 
573   // It must successfully decrypt.
574   alignas(64) uint8_t out[sizeof(ciphertext)];
575   ctx.Reset();
576   ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
577       ctx.get(), aead(), key + 1, key_len, EVP_AEAD_DEFAULT_TAG_LENGTH,
578       evp_aead_open));
579   size_t out_len;
580   ASSERT_TRUE(EVP_AEAD_CTX_open(ctx.get(), out + 1, &out_len, sizeof(out) - 1,
581                                 nonce + 1, nonce_len, ciphertext + 1,
582                                 ciphertext_len, ad + 1, ad_len));
583   EXPECT_EQ(Bytes(plaintext + 1, sizeof(plaintext) - 1),
584             Bytes(out + 1, out_len));
585 }
586 
TEST_P(PerAEADTest,Overflow)587 TEST_P(PerAEADTest, Overflow) {
588   alignas(64) uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
589   OPENSSL_memset(key, 'K', sizeof(key));
590 
591   bssl::ScopedEVP_AEAD_CTX ctx;
592   const size_t max_tag_len = EVP_AEAD_max_tag_len(aead());
593   ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(ctx.get(), aead(), key,
594                                                EVP_AEAD_key_length(aead()),
595                                                max_tag_len, evp_aead_seal));
596 
597   uint8_t plaintext[1] = {0};
598   uint8_t ciphertext[1024] = {0};
599   size_t ciphertext_len;
600   // The AEAD must not overflow when calculating the ciphertext length.
601   ASSERT_FALSE(EVP_AEAD_CTX_seal(
602       ctx.get(), ciphertext, &ciphertext_len, sizeof(ciphertext), nullptr, 0,
603       plaintext, std::numeric_limits<size_t>::max() - max_tag_len + 1, nullptr,
604       0));
605   ERR_clear_error();
606 
607   // (Can't test the scatter interface because it'll attempt to zero the output
608   // buffer on error and the primary output buffer is implicitly the same size
609   // as the input.)
610 }
611 
TEST_P(PerAEADTest,InvalidNonceLength)612 TEST_P(PerAEADTest, InvalidNonceLength) {
613   size_t valid_nonce_len = EVP_AEAD_nonce_length(aead());
614   std::vector<size_t> nonce_lens;
615   if (valid_nonce_len != 0) {
616     // Other than the implicit IV TLS "AEAD"s, none of our AEADs allow empty
617     // nonces. In particular, although AES-GCM was incorrectly specified with
618     // variable-length nonces, it does not allow the empty nonce.
619     nonce_lens.push_back(0);
620   }
621   if (!GetParam().variable_nonce) {
622     nonce_lens.push_back(valid_nonce_len + 1);
623     if (valid_nonce_len != 0) {
624       nonce_lens.push_back(valid_nonce_len - 1);
625     }
626   }
627 
628   static const uint8_t kZeros[EVP_AEAD_MAX_KEY_LENGTH] = {0};
629   const size_t ad_len = GetParam().ad_len != 0 ? GetParam().ad_len : 16;
630   ASSERT_LE(ad_len, sizeof(kZeros));
631 
632   for (size_t nonce_len : nonce_lens) {
633     SCOPED_TRACE(nonce_len);
634     uint8_t buf[256];
635     size_t len;
636     std::vector<uint8_t> nonce(nonce_len);
637     bssl::ScopedEVP_AEAD_CTX ctx;
638     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
639         ctx.get(), aead(), kZeros, EVP_AEAD_key_length(aead()),
640         EVP_AEAD_DEFAULT_TAG_LENGTH, evp_aead_seal));
641 
642     EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
643                                    nonce.data(), nonce.size(), nullptr /* in */,
644                                    0, kZeros /* ad */, ad_len));
645     uint32_t err = ERR_get_error();
646     EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
647     // TODO(davidben): Merge these errors. https://crbug.com/boringssl/129.
648     if (ERR_GET_REASON(err) != CIPHER_R_UNSUPPORTED_NONCE_SIZE) {
649       EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
650     }
651 
652     ctx.Reset();
653     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
654         ctx.get(), aead(), kZeros, EVP_AEAD_key_length(aead()),
655         EVP_AEAD_DEFAULT_TAG_LENGTH, evp_aead_open));
656     EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
657                                    nonce.data(), nonce.size(), kZeros /* in */,
658                                    sizeof(kZeros), kZeros /* ad */, ad_len));
659     err = ERR_get_error();
660     EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
661     if (ERR_GET_REASON(err) != CIPHER_R_UNSUPPORTED_NONCE_SIZE) {
662       EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
663     }
664   }
665 }
666 
TEST(AEADTest,AESCCMLargeAD)667 TEST(AEADTest, AESCCMLargeAD) {
668   static const std::vector<uint8_t> kKey(16, 'A');
669   static const std::vector<uint8_t> kNonce(13, 'N');
670   static const std::vector<uint8_t> kAD(65536, 'D');
671   static const std::vector<uint8_t> kPlaintext = {
672       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
673       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
674   static const std::vector<uint8_t> kCiphertext = {
675       0xa2, 0x12, 0x3f, 0x0b, 0x07, 0xd5, 0x02, 0xff,
676       0xa9, 0xcd, 0xa0, 0xf3, 0x69, 0x1c, 0x49, 0x0c};
677   static const std::vector<uint8_t> kTag = {0x4a, 0x31, 0x82, 0x96};
678 
679   // Test AES-128-CCM-Bluetooth.
680   bssl::ScopedEVP_AEAD_CTX ctx;
681   ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_ccm_bluetooth(),
682                                 kKey.data(), kKey.size(),
683                                 EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
684 
685   std::vector<uint8_t> out(kCiphertext.size() + kTag.size());
686   size_t out_len;
687   EXPECT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
688                                 kNonce.data(), kNonce.size(), kPlaintext.data(),
689                                 kPlaintext.size(), kAD.data(), kAD.size()));
690 
691   ASSERT_EQ(out_len, kCiphertext.size() + kTag.size());
692   EXPECT_EQ(Bytes(kCiphertext), Bytes(out.data(), kCiphertext.size()));
693   EXPECT_EQ(Bytes(kTag), Bytes(out.data() + kCiphertext.size(), kTag.size()));
694 
695   EXPECT_TRUE(EVP_AEAD_CTX_open(ctx.get(), out.data(), &out_len, out.size(),
696                                 kNonce.data(), kNonce.size(), out.data(),
697                                 out.size(), kAD.data(), kAD.size()));
698 
699   ASSERT_EQ(out_len, kPlaintext.size());
700   EXPECT_EQ(Bytes(kPlaintext), Bytes(out.data(), kPlaintext.size()));
701 }
702 
RunWycheproofTestCase(FileTest * t,const EVP_AEAD * aead)703 static void RunWycheproofTestCase(FileTest *t, const EVP_AEAD *aead) {
704   t->IgnoreInstruction("ivSize");
705 
706   std::vector<uint8_t> aad, ct, iv, key, msg, tag;
707   ASSERT_TRUE(t->GetBytes(&aad, "aad"));
708   ASSERT_TRUE(t->GetBytes(&ct, "ct"));
709   ASSERT_TRUE(t->GetBytes(&iv, "iv"));
710   ASSERT_TRUE(t->GetBytes(&key, "key"));
711   ASSERT_TRUE(t->GetBytes(&msg, "msg"));
712   ASSERT_TRUE(t->GetBytes(&tag, "tag"));
713   std::string tag_size_str;
714   ASSERT_TRUE(t->GetInstruction(&tag_size_str, "tagSize"));
715   size_t tag_size = static_cast<size_t>(atoi(tag_size_str.c_str()));
716   ASSERT_EQ(0u, tag_size % 8);
717   tag_size /= 8;
718   WycheproofResult result;
719   ASSERT_TRUE(GetWycheproofResult(t, &result));
720 
721   std::vector<uint8_t> ct_and_tag = ct;
722   ct_and_tag.insert(ct_and_tag.end(), tag.begin(), tag.end());
723 
724   bssl::ScopedEVP_AEAD_CTX ctx;
725   ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key.size(),
726                                 tag_size, nullptr));
727   std::vector<uint8_t> out(msg.size());
728   size_t out_len;
729   // Wycheproof tags small AES-GCM IVs as "acceptable" and otherwise does not
730   // use it in AEADs. Any AES-GCM IV that isn't 96 bits is absurd, but our API
731   // supports those, so we treat "acceptable" as "valid" here.
732   if (result != WycheproofResult::kInvalid) {
733     // Decryption should succeed.
734     ASSERT_TRUE(EVP_AEAD_CTX_open(ctx.get(), out.data(), &out_len, out.size(),
735                                   iv.data(), iv.size(), ct_and_tag.data(),
736                                   ct_and_tag.size(), aad.data(), aad.size()));
737     EXPECT_EQ(Bytes(msg), Bytes(out.data(), out_len));
738 
739     // Decryption in-place should succeed.
740     out = ct_and_tag;
741     ASSERT_TRUE(EVP_AEAD_CTX_open(ctx.get(), out.data(), &out_len, out.size(),
742                                   iv.data(), iv.size(), out.data(), out.size(),
743                                   aad.data(), aad.size()));
744     EXPECT_EQ(Bytes(msg), Bytes(out.data(), out_len));
745 
746     // AEADs are deterministic, so encryption should produce the same result.
747     out.resize(ct_and_tag.size());
748     ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
749                                   iv.data(), iv.size(), msg.data(), msg.size(),
750                                   aad.data(), aad.size()));
751     EXPECT_EQ(Bytes(ct_and_tag), Bytes(out.data(), out_len));
752 
753     // Encrypt in-place.
754     out = msg;
755     out.resize(ct_and_tag.size());
756     ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
757                                   iv.data(), iv.size(), out.data(), msg.size(),
758                                   aad.data(), aad.size()));
759     EXPECT_EQ(Bytes(ct_and_tag), Bytes(out.data(), out_len));
760   } else {
761     // Decryption should fail.
762     EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), out.data(), &out_len, out.size(),
763                                    iv.data(), iv.size(), ct_and_tag.data(),
764                                    ct_and_tag.size(), aad.data(), aad.size()));
765 
766     // Decryption in-place should also fail.
767     out = ct_and_tag;
768     EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), out.data(), &out_len, out.size(),
769                                    iv.data(), iv.size(), out.data(), out.size(),
770                                    aad.data(), aad.size()));
771   }
772 }
773 
TEST(AEADTest,WycheproofAESGCMSIV)774 TEST(AEADTest, WycheproofAESGCMSIV) {
775   FileTestGTest("third_party/wycheproof_testvectors/aes_gcm_siv_test.txt",
776                 [](FileTest *t) {
777     std::string key_size_str;
778     ASSERT_TRUE(t->GetInstruction(&key_size_str, "keySize"));
779     const EVP_AEAD *aead;
780     switch (atoi(key_size_str.c_str())) {
781       case 128:
782         aead = EVP_aead_aes_128_gcm_siv();
783         break;
784       case 256:
785         aead = EVP_aead_aes_256_gcm_siv();
786         break;
787       default:
788         FAIL() << "Unknown key size: " << key_size_str;
789     }
790 
791     RunWycheproofTestCase(t, aead);
792   });
793 }
794 
TEST(AEADTest,WycheproofAESGCM)795 TEST(AEADTest, WycheproofAESGCM) {
796   FileTestGTest("third_party/wycheproof_testvectors/aes_gcm_test.txt",
797                 [](FileTest *t) {
798     std::string key_size_str;
799     ASSERT_TRUE(t->GetInstruction(&key_size_str, "keySize"));
800     const EVP_AEAD *aead;
801     switch (atoi(key_size_str.c_str())) {
802       case 128:
803         aead = EVP_aead_aes_128_gcm();
804         break;
805       case 192:
806         aead = EVP_aead_aes_192_gcm();
807         break;
808       case 256:
809         aead = EVP_aead_aes_256_gcm();
810         break;
811       default:
812         FAIL() << "Unknown key size: " << key_size_str;
813     }
814 
815     RunWycheproofTestCase(t, aead);
816   });
817 }
818 
TEST(AEADTest,WycheproofChaCha20Poly1305)819 TEST(AEADTest, WycheproofChaCha20Poly1305) {
820   FileTestGTest("third_party/wycheproof_testvectors/chacha20_poly1305_test.txt",
821                 [](FileTest *t) {
822     t->IgnoreInstruction("keySize");
823     RunWycheproofTestCase(t, EVP_aead_chacha20_poly1305());
824   });
825 }
826