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