• 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 
31 
32 struct KnownAEAD {
33   const char name[40];
34   const EVP_AEAD *(*func)(void);
35   const char *test_vectors;
36   // limited_implementation indicates that tests that assume a generic AEAD
37   // interface should not be performed. For example, the key-wrap AEADs only
38   // handle inputs that are a multiple of eight bytes in length and the
39   // SSLv3/TLS AEADs have the concept of “direction”.
40   bool limited_implementation;
41   // truncated_tags is true if the AEAD supports truncating tags to arbitrary
42   // lengths.
43   bool truncated_tags;
44   // ad_len, if non-zero, is the required length of the AD.
45   size_t ad_len;
46 };
47 
48 static const struct KnownAEAD kAEADs[] = {
49     {"AES_128_GCM", EVP_aead_aes_128_gcm, "aes_128_gcm_tests.txt", false, true,
50      0},
51     {"AES_128_GCM_NIST", EVP_aead_aes_128_gcm, "nist_cavp/aes_128_gcm.txt",
52      false, true, 0},
53     {"AES_256_GCM", EVP_aead_aes_256_gcm, "aes_256_gcm_tests.txt", false, true,
54      0},
55     {"AES_256_GCM_NIST", EVP_aead_aes_256_gcm, "nist_cavp/aes_256_gcm.txt",
56      false, true, 0},
57 #if !defined(OPENSSL_SMALL)
58     {"AES_128_GCM_SIV", EVP_aead_aes_128_gcm_siv, "aes_128_gcm_siv_tests.txt",
59      false, false, 0},
60     {"AES_256_GCM_SIV", EVP_aead_aes_256_gcm_siv, "aes_256_gcm_siv_tests.txt",
61      false, false, 0},
62 #endif
63     {"ChaCha20Poly1305", EVP_aead_chacha20_poly1305,
64      "chacha20_poly1305_tests.txt", false, true, 0},
65     {"AES_128_CBC_SHA1_TLS", EVP_aead_aes_128_cbc_sha1_tls,
66      "aes_128_cbc_sha1_tls_tests.txt", true, false, 11},
67     {"AES_128_CBC_SHA1_TLSImplicitIV",
68      EVP_aead_aes_128_cbc_sha1_tls_implicit_iv,
69      "aes_128_cbc_sha1_tls_implicit_iv_tests.txt", true, false, 11},
70     {"AES_128_CBC_SHA256_TLS", EVP_aead_aes_128_cbc_sha256_tls,
71      "aes_128_cbc_sha256_tls_tests.txt", true, false, 11},
72     {"AES_256_CBC_SHA1_TLS", EVP_aead_aes_256_cbc_sha1_tls,
73      "aes_256_cbc_sha1_tls_tests.txt", true, false, 11},
74     {"AES_256_CBC_SHA1_TLSImplicitIV",
75      EVP_aead_aes_256_cbc_sha1_tls_implicit_iv,
76      "aes_256_cbc_sha1_tls_implicit_iv_tests.txt", true, false, 11},
77     {"AES_256_CBC_SHA256_TLS", EVP_aead_aes_256_cbc_sha256_tls,
78      "aes_256_cbc_sha256_tls_tests.txt", true, false, 11},
79     {"AES_256_CBC_SHA384_TLS", EVP_aead_aes_256_cbc_sha384_tls,
80      "aes_256_cbc_sha384_tls_tests.txt", true, false, 11},
81     {"DES_EDE3_CBC_SHA1_TLS", EVP_aead_des_ede3_cbc_sha1_tls,
82      "des_ede3_cbc_sha1_tls_tests.txt", true, false, 11},
83     {"DES_EDE3_CBC_SHA1_TLSImplicitIV",
84      EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv,
85      "des_ede3_cbc_sha1_tls_implicit_iv_tests.txt", true, false, 11},
86     {"AES_128_CBC_SHA1_SSL3", EVP_aead_aes_128_cbc_sha1_ssl3,
87      "aes_128_cbc_sha1_ssl3_tests.txt", true, false, 9},
88     {"AES_256_CBC_SHA1_SSL3", EVP_aead_aes_256_cbc_sha1_ssl3,
89      "aes_256_cbc_sha1_ssl3_tests.txt", true, false, 9},
90     {"DES_EDE3_CBC_SHA1_SSL3", EVP_aead_des_ede3_cbc_sha1_ssl3,
91      "des_ede3_cbc_sha1_ssl3_tests.txt", true, false, 9},
92     {"AES_128_CTR_HMAC_SHA256", EVP_aead_aes_128_ctr_hmac_sha256,
93      "aes_128_ctr_hmac_sha256.txt", false, true, 0},
94     {"AES_256_CTR_HMAC_SHA256", EVP_aead_aes_256_ctr_hmac_sha256,
95      "aes_256_ctr_hmac_sha256.txt", false, true, 0},
96 };
97 
98 class PerAEADTest : public testing::TestWithParam<KnownAEAD> {
99  public:
aead()100   const EVP_AEAD *aead() { return GetParam().func(); }
101 };
102 
103 INSTANTIATE_TEST_CASE_P(, PerAEADTest, testing::ValuesIn(kAEADs),
104                         [](const testing::TestParamInfo<KnownAEAD> &params)
__anonb7b6f6820102(const testing::TestParamInfo<KnownAEAD> &params) 105                             -> std::string { return params.param.name; });
106 
107 // Tests an AEAD against a series of test vectors from a file, using the
108 // FileTest format. As an example, here's a valid test case:
109 //
110 //   KEY: 5a19f3173586b4c42f8412f4d5a786531b3231753e9e00998aec12fda8df10e4
111 //   NONCE: 978105dfce667bf4
112 //   IN: 6a4583908d
113 //   AD: b654574932
114 //   CT: 5294265a60
115 //   TAG: 1d45758621762e061368e68868e2f929
TEST_P(PerAEADTest,TestVector)116 TEST_P(PerAEADTest, TestVector) {
117   std::string test_vectors = "crypto/cipher_extra/test/";
118   test_vectors += GetParam().test_vectors;
119   FileTestGTest(test_vectors.c_str(), [&](FileTest *t) {
120     std::vector<uint8_t> key, nonce, in, ad, ct, tag;
121     ASSERT_TRUE(t->GetBytes(&key, "KEY"));
122     ASSERT_TRUE(t->GetBytes(&nonce, "NONCE"));
123     ASSERT_TRUE(t->GetBytes(&in, "IN"));
124     ASSERT_TRUE(t->GetBytes(&ad, "AD"));
125     ASSERT_TRUE(t->GetBytes(&ct, "CT"));
126     ASSERT_TRUE(t->GetBytes(&tag, "TAG"));
127     size_t tag_len = tag.size();
128     if (t->HasAttribute("TAG_LEN")) {
129       // Legacy AEADs are MAC-then-encrypt and may include padding in the TAG
130       // field. TAG_LEN contains the actual size of the digest in that case.
131       std::string tag_len_str;
132       ASSERT_TRUE(t->GetAttribute(&tag_len_str, "TAG_LEN"));
133       tag_len = strtoul(tag_len_str.c_str(), nullptr, 10);
134       ASSERT_TRUE(tag_len);
135     }
136 
137     bssl::ScopedEVP_AEAD_CTX ctx;
138     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
139         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_seal));
140 
141     std::vector<uint8_t> out(in.size() + EVP_AEAD_max_overhead(aead()));
142     if (!t->HasAttribute("NO_SEAL")) {
143       size_t out_len;
144       ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
145                                     nonce.data(), nonce.size(), in.data(),
146                                     in.size(), ad.data(), ad.size()));
147       out.resize(out_len);
148 
149       ASSERT_EQ(out.size(), ct.size() + tag.size());
150       EXPECT_EQ(Bytes(ct), Bytes(out.data(), ct.size()));
151       EXPECT_EQ(Bytes(tag), Bytes(out.data() + ct.size(), tag.size()));
152     } else {
153       out.resize(ct.size() + tag.size());
154       OPENSSL_memcpy(out.data(), ct.data(), ct.size());
155       OPENSSL_memcpy(out.data() + ct.size(), tag.data(), tag.size());
156     }
157 
158     // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
159     // reset after each operation.
160     ctx.Reset();
161     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
162         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
163 
164     std::vector<uint8_t> out2(out.size());
165     size_t out2_len;
166     int ret = EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(),
167                                 nonce.data(), nonce.size(), out.data(),
168                                 out.size(), ad.data(), ad.size());
169     if (t->HasAttribute("FAILS")) {
170       ASSERT_FALSE(ret) << "Decrypted bad data.";
171       ERR_clear_error();
172       return;
173     }
174 
175     ASSERT_TRUE(ret) << "Failed to decrypt.";
176     out2.resize(out2_len);
177     EXPECT_EQ(Bytes(in), Bytes(out2));
178 
179     // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
180     // reset after each operation.
181     ctx.Reset();
182     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
183         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
184 
185     // Garbage at the end isn't ignored.
186     out.push_back(0);
187     out2.resize(out.size());
188     EXPECT_FALSE(EVP_AEAD_CTX_open(
189         ctx.get(), out2.data(), &out2_len, out2.size(), nonce.data(),
190         nonce.size(), out.data(), out.size(), ad.data(), ad.size()))
191         << "Decrypted bad data with trailing garbage.";
192     ERR_clear_error();
193 
194     // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
195     // reset after each operation.
196     ctx.Reset();
197     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
198         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
199 
200     // Verify integrity is checked.
201     out[0] ^= 0x80;
202     out.resize(out.size() - 1);
203     out2.resize(out.size());
204     EXPECT_FALSE(EVP_AEAD_CTX_open(
205         ctx.get(), out2.data(), &out2_len, out2.size(), nonce.data(),
206         nonce.size(), out.data(), out.size(), ad.data(), ad.size()))
207         << "Decrypted bad data with corrupted byte.";
208     ERR_clear_error();
209   });
210 }
211 
TEST_P(PerAEADTest,TestExtraInput)212 TEST_P(PerAEADTest, TestExtraInput) {
213   const KnownAEAD &aead_config = GetParam();
214   if (!aead()->seal_scatter_supports_extra_in) {
215     return;
216   }
217 
218   const std::string test_vectors =
219       "crypto/cipher_extra/test/" + std::string(aead_config.test_vectors);
220   FileTestGTest(test_vectors.c_str(), [&](FileTest *t) {
221     if (t->HasAttribute("NO_SEAL") ||
222         t->HasAttribute("FAILS")) {
223       t->SkipCurrent();
224       return;
225     }
226 
227     std::vector<uint8_t> key, nonce, in, ad, ct, tag;
228     ASSERT_TRUE(t->GetBytes(&key, "KEY"));
229     ASSERT_TRUE(t->GetBytes(&nonce, "NONCE"));
230     ASSERT_TRUE(t->GetBytes(&in, "IN"));
231     ASSERT_TRUE(t->GetBytes(&ad, "AD"));
232     ASSERT_TRUE(t->GetBytes(&ct, "CT"));
233     ASSERT_TRUE(t->GetBytes(&tag, "TAG"));
234 
235     bssl::ScopedEVP_AEAD_CTX ctx;
236     ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead(), key.data(), key.size(),
237                                   tag.size(), nullptr));
238     std::vector<uint8_t> out_tag(EVP_AEAD_max_overhead(aead()) + in.size());
239     std::vector<uint8_t> out(in.size());
240 
241     for (size_t extra_in_size = 0; extra_in_size < in.size(); extra_in_size++) {
242       size_t tag_bytes_written;
243       SCOPED_TRACE(extra_in_size);
244       ASSERT_TRUE(EVP_AEAD_CTX_seal_scatter(
245           ctx.get(), out.data(), out_tag.data(), &tag_bytes_written,
246           out_tag.size(), nonce.data(), nonce.size(), in.data(),
247           in.size() - extra_in_size, in.data() + in.size() - extra_in_size,
248           extra_in_size, ad.data(), ad.size()));
249 
250       ASSERT_EQ(tag_bytes_written, extra_in_size + tag.size());
251 
252       memcpy(out.data() + in.size() - extra_in_size, out_tag.data(),
253              extra_in_size);
254 
255       EXPECT_EQ(Bytes(ct), Bytes(out.data(), in.size()));
256       EXPECT_EQ(Bytes(tag), Bytes(out_tag.data() + extra_in_size,
257                                   tag_bytes_written - extra_in_size));
258     }
259   });
260 }
261 
TEST_P(PerAEADTest,TestVectorScatterGather)262 TEST_P(PerAEADTest, TestVectorScatterGather) {
263   std::string test_vectors = "crypto/cipher_extra/test/";
264   const KnownAEAD &aead_config = GetParam();
265   test_vectors += aead_config.test_vectors;
266   FileTestGTest(test_vectors.c_str(), [&](FileTest *t) {
267     std::vector<uint8_t> key, nonce, in, ad, ct, tag;
268     ASSERT_TRUE(t->GetBytes(&key, "KEY"));
269     ASSERT_TRUE(t->GetBytes(&nonce, "NONCE"));
270     ASSERT_TRUE(t->GetBytes(&in, "IN"));
271     ASSERT_TRUE(t->GetBytes(&ad, "AD"));
272     ASSERT_TRUE(t->GetBytes(&ct, "CT"));
273     ASSERT_TRUE(t->GetBytes(&tag, "TAG"));
274     size_t tag_len = tag.size();
275     if (t->HasAttribute("TAG_LEN")) {
276       // Legacy AEADs are MAC-then-encrypt and may include padding in the TAG
277       // field. TAG_LEN contains the actual size of the digest in that case.
278       std::string tag_len_str;
279       ASSERT_TRUE(t->GetAttribute(&tag_len_str, "TAG_LEN"));
280       tag_len = strtoul(tag_len_str.c_str(), nullptr, 10);
281       ASSERT_TRUE(tag_len);
282     }
283 
284     bssl::ScopedEVP_AEAD_CTX ctx;
285     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
286         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_seal));
287 
288     std::vector<uint8_t> out(in.size());
289     std::vector<uint8_t> out_tag(EVP_AEAD_max_overhead(aead()));
290     if (!t->HasAttribute("NO_SEAL")) {
291       size_t out_tag_len;
292       ASSERT_TRUE(EVP_AEAD_CTX_seal_scatter(
293           ctx.get(), out.data(), out_tag.data(), &out_tag_len, out_tag.size(),
294           nonce.data(), nonce.size(), in.data(), in.size(), nullptr, 0,
295           ad.data(), ad.size()));
296       out_tag.resize(out_tag_len);
297 
298       ASSERT_EQ(out.size(), ct.size());
299       ASSERT_EQ(out_tag.size(), tag.size());
300       EXPECT_EQ(Bytes(ct), Bytes(out.data(), ct.size()));
301       EXPECT_EQ(Bytes(tag), Bytes(out_tag.data(), tag.size()));
302     } else {
303       out.resize(ct.size());
304       out_tag.resize(tag.size());
305       OPENSSL_memcpy(out.data(), ct.data(), ct.size());
306       OPENSSL_memcpy(out_tag.data(), tag.data(), tag.size());
307     }
308 
309     // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
310     // reset after each operation.
311     ctx.Reset();
312     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
313         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
314 
315     std::vector<uint8_t> out2(out.size());
316     int ret = EVP_AEAD_CTX_open_gather(
317         ctx.get(), out2.data(), nonce.data(), nonce.size(), out.data(),
318         out.size(), out_tag.data(), out_tag.size(), ad.data(), ad.size());
319 
320     // Skip decryption for AEADs that don't implement open_gather().
321     if (!ret) {
322       int err = ERR_peek_error();
323       if (ERR_GET_LIB(err) == ERR_LIB_CIPHER &&
324           ERR_GET_REASON(err) == CIPHER_R_CTRL_NOT_IMPLEMENTED) {
325           t->SkipCurrent();
326           return;
327         }
328     }
329 
330     if (t->HasAttribute("FAILS")) {
331       ASSERT_FALSE(ret) << "Decrypted bad data";
332       ERR_clear_error();
333       return;
334     }
335 
336     ASSERT_TRUE(ret) << "Failed to decrypt: "
337                      << ERR_reason_error_string(ERR_get_error());
338     EXPECT_EQ(Bytes(in), Bytes(out2));
339 
340     // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
341     // reset after each operation.
342     ctx.Reset();
343     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
344         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
345 
346     // Garbage at the end isn't ignored.
347     out_tag.push_back(0);
348     out2.resize(out.size());
349     EXPECT_FALSE(EVP_AEAD_CTX_open_gather(
350         ctx.get(), out2.data(), nonce.data(), nonce.size(), out.data(),
351         out.size(), out_tag.data(), out_tag.size(), ad.data(), ad.size()))
352         << "Decrypted bad data with trailing garbage.";
353     ERR_clear_error();
354 
355     // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
356     // reset after each operation.
357     ctx.Reset();
358     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
359         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
360 
361     // Verify integrity is checked.
362     out_tag[0] ^= 0x80;
363     out_tag.resize(out_tag.size() - 1);
364     out2.resize(out.size());
365     EXPECT_FALSE(EVP_AEAD_CTX_open_gather(
366         ctx.get(), out2.data(), nonce.data(), nonce.size(), out.data(),
367         out.size(), out_tag.data(), out_tag.size(), ad.data(), ad.size()))
368         << "Decrypted bad data with corrupted byte.";
369     ERR_clear_error();
370 
371     ctx.Reset();
372     ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
373         ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
374 
375     // Check edge case for tag length.
376     EXPECT_FALSE(EVP_AEAD_CTX_open_gather(
377         ctx.get(), out2.data(), nonce.data(), nonce.size(), out.data(),
378         out.size(), out_tag.data(), 0, ad.data(), ad.size()))
379         << "Decrypted bad data with corrupted byte.";
380     ERR_clear_error();
381   });
382 }
383 
TEST_P(PerAEADTest,CleanupAfterInitFailure)384 TEST_P(PerAEADTest, CleanupAfterInitFailure) {
385   uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
386   OPENSSL_memset(key, 0, sizeof(key));
387   const size_t key_len = EVP_AEAD_key_length(aead());
388   ASSERT_GE(sizeof(key), key_len);
389 
390   EVP_AEAD_CTX ctx;
391   ASSERT_FALSE(EVP_AEAD_CTX_init(
392       &ctx, aead(), key, key_len,
393       9999 /* a silly tag length to trigger an error */, NULL /* ENGINE */));
394   ERR_clear_error();
395 
396   // Running a second, failed _init should not cause a memory leak.
397   ASSERT_FALSE(EVP_AEAD_CTX_init(
398       &ctx, aead(), key, key_len,
399       9999 /* a silly tag length to trigger an error */, NULL /* ENGINE */));
400   ERR_clear_error();
401 
402   // Calling _cleanup on an |EVP_AEAD_CTX| after a failed _init should be a
403   // no-op.
404   EVP_AEAD_CTX_cleanup(&ctx);
405 }
406 
TEST_P(PerAEADTest,TruncatedTags)407 TEST_P(PerAEADTest, TruncatedTags) {
408   if (!GetParam().truncated_tags) {
409     return;
410   }
411 
412   uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
413   OPENSSL_memset(key, 0, sizeof(key));
414   const size_t key_len = EVP_AEAD_key_length(aead());
415   ASSERT_GE(sizeof(key), key_len);
416 
417   uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
418   OPENSSL_memset(nonce, 0, sizeof(nonce));
419   const size_t nonce_len = EVP_AEAD_nonce_length(aead());
420   ASSERT_GE(sizeof(nonce), nonce_len);
421 
422   bssl::ScopedEVP_AEAD_CTX ctx;
423   ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead(), key, key_len,
424                                 1 /* one byte tag */, NULL /* ENGINE */));
425 
426   const uint8_t plaintext[1] = {'A'};
427 
428   uint8_t ciphertext[128];
429   size_t ciphertext_len;
430   constexpr uint8_t kSentinel = 42;
431   OPENSSL_memset(ciphertext, kSentinel, sizeof(ciphertext));
432 
433   ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), ciphertext, &ciphertext_len,
434                                 sizeof(ciphertext), nonce, nonce_len, plaintext,
435                                 sizeof(plaintext), nullptr /* ad */, 0));
436 
437   for (size_t i = ciphertext_len; i < sizeof(ciphertext); i++) {
438     // Sealing must not write past where it said it did.
439     EXPECT_EQ(kSentinel, ciphertext[i])
440         << "Sealing wrote off the end of the buffer.";
441   }
442 
443   const size_t overhead_used = ciphertext_len - sizeof(plaintext);
444   const size_t expected_overhead =
445       1 + EVP_AEAD_max_overhead(aead()) - EVP_AEAD_max_tag_len(aead());
446   EXPECT_EQ(overhead_used, expected_overhead)
447       << "AEAD is probably ignoring request to truncate tags.";
448 
449   uint8_t plaintext2[sizeof(plaintext) + 16];
450   OPENSSL_memset(plaintext2, kSentinel, sizeof(plaintext2));
451 
452   size_t plaintext2_len;
453   ASSERT_TRUE(EVP_AEAD_CTX_open(
454       ctx.get(), plaintext2, &plaintext2_len, sizeof(plaintext2), nonce,
455       nonce_len, ciphertext, ciphertext_len, nullptr /* ad */, 0))
456       << "Opening with truncated tag didn't work.";
457 
458   for (size_t i = plaintext2_len; i < sizeof(plaintext2); i++) {
459     // Likewise, opening should also stay within bounds.
460     EXPECT_EQ(kSentinel, plaintext2[i])
461         << "Opening wrote off the end of the buffer.";
462   }
463 
464   EXPECT_EQ(Bytes(plaintext), Bytes(plaintext2, plaintext2_len));
465 }
466 
TEST_P(PerAEADTest,AliasedBuffers)467 TEST_P(PerAEADTest, AliasedBuffers) {
468   if (GetParam().limited_implementation) {
469     return;
470   }
471 
472   const size_t key_len = EVP_AEAD_key_length(aead());
473   const size_t nonce_len = EVP_AEAD_nonce_length(aead());
474   const size_t max_overhead = EVP_AEAD_max_overhead(aead());
475 
476   std::vector<uint8_t> key(key_len, 'a');
477   bssl::ScopedEVP_AEAD_CTX ctx;
478   ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead(), key.data(), key_len,
479                                 EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
480 
481   static const uint8_t kPlaintext[260] =
482       "testing123456testing123456testing123456testing123456testing123456testing"
483       "123456testing123456testing123456testing123456testing123456testing123456t"
484       "esting123456testing123456testing123456testing123456testing123456testing1"
485       "23456testing123456testing123456testing12345";
486   const std::vector<size_t> offsets = {
487       0,  1,  2,  8,  15, 16,  17,  31,  32,  33,  63,
488       64, 65, 95, 96, 97, 127, 128, 129, 255, 256, 257,
489   };
490 
491   std::vector<uint8_t> nonce(nonce_len, 'b');
492   std::vector<uint8_t> valid_encryption(sizeof(kPlaintext) + max_overhead);
493   size_t valid_encryption_len;
494   ASSERT_TRUE(EVP_AEAD_CTX_seal(
495       ctx.get(), valid_encryption.data(), &valid_encryption_len,
496       sizeof(kPlaintext) + max_overhead, nonce.data(), nonce_len, kPlaintext,
497       sizeof(kPlaintext), nullptr, 0))
498       << "EVP_AEAD_CTX_seal failed with disjoint buffers.";
499 
500   // Test with out != in which we expect to fail.
501   std::vector<uint8_t> buffer(2 + valid_encryption_len);
502   uint8_t *in = buffer.data() + 1;
503   uint8_t *out1 = buffer.data();
504   uint8_t *out2 = buffer.data() + 2;
505 
506   OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
507   size_t out_len;
508   EXPECT_FALSE(EVP_AEAD_CTX_seal(
509       ctx.get(), out1 /* in - 1 */, &out_len, sizeof(kPlaintext) + max_overhead,
510       nonce.data(), nonce_len, in, sizeof(kPlaintext), nullptr, 0));
511   EXPECT_FALSE(EVP_AEAD_CTX_seal(
512       ctx.get(), out2 /* in + 1 */, &out_len, sizeof(kPlaintext) + max_overhead,
513       nonce.data(), nonce_len, in, sizeof(kPlaintext), nullptr, 0));
514   ERR_clear_error();
515 
516   OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
517   EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), out1 /* in - 1 */, &out_len,
518                                  valid_encryption_len, nonce.data(), nonce_len,
519                                  in, valid_encryption_len, nullptr, 0));
520   EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), out2 /* in + 1 */, &out_len,
521                                  valid_encryption_len, nonce.data(), nonce_len,
522                                  in, valid_encryption_len, nullptr, 0));
523   ERR_clear_error();
524 
525   // Test with out == in, which we expect to work.
526   OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
527 
528   ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), in, &out_len,
529                                 sizeof(kPlaintext) + max_overhead, nonce.data(),
530                                 nonce_len, in, sizeof(kPlaintext), nullptr, 0));
531   EXPECT_EQ(Bytes(valid_encryption.data(), valid_encryption_len),
532             Bytes(in, out_len));
533 
534   OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
535   ASSERT_TRUE(EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len,
536                                 nonce.data(), nonce_len, in,
537                                 valid_encryption_len, nullptr, 0));
538   EXPECT_EQ(Bytes(kPlaintext), Bytes(in, out_len));
539 }
540 
TEST_P(PerAEADTest,UnalignedInput)541 TEST_P(PerAEADTest, UnalignedInput) {
542   alignas(64) uint8_t key[EVP_AEAD_MAX_KEY_LENGTH + 1];
543   alignas(64) uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH + 1];
544   alignas(64) uint8_t plaintext[32 + 1];
545   alignas(64) uint8_t ad[32 + 1];
546   OPENSSL_memset(key, 'K', sizeof(key));
547   OPENSSL_memset(nonce, 'N', sizeof(nonce));
548   OPENSSL_memset(plaintext, 'P', sizeof(plaintext));
549   OPENSSL_memset(ad, 'A', sizeof(ad));
550   const size_t key_len = EVP_AEAD_key_length(aead());
551   ASSERT_GE(sizeof(key) - 1, key_len);
552   const size_t nonce_len = EVP_AEAD_nonce_length(aead());
553   ASSERT_GE(sizeof(nonce) - 1, nonce_len);
554   const size_t ad_len =
555       GetParam().ad_len != 0 ? GetParam().ad_len : sizeof(ad) - 1;
556   ASSERT_GE(sizeof(ad) - 1, ad_len);
557 
558   // Encrypt some input.
559   bssl::ScopedEVP_AEAD_CTX ctx;
560   ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
561       ctx.get(), aead(), key + 1, key_len, EVP_AEAD_DEFAULT_TAG_LENGTH,
562       evp_aead_seal));
563   alignas(64) uint8_t ciphertext[sizeof(plaintext) + EVP_AEAD_MAX_OVERHEAD];
564   size_t ciphertext_len;
565   ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), ciphertext + 1, &ciphertext_len,
566                                 sizeof(ciphertext) - 1, nonce + 1, nonce_len,
567                                 plaintext + 1, sizeof(plaintext) - 1, ad + 1,
568                                 ad_len));
569 
570   // It must successfully decrypt.
571   alignas(64) uint8_t out[sizeof(ciphertext)];
572   ctx.Reset();
573   ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
574       ctx.get(), aead(), key + 1, key_len, EVP_AEAD_DEFAULT_TAG_LENGTH,
575       evp_aead_open));
576   size_t out_len;
577   ASSERT_TRUE(EVP_AEAD_CTX_open(ctx.get(), out + 1, &out_len, sizeof(out) - 1,
578                                 nonce + 1, nonce_len, ciphertext + 1,
579                                 ciphertext_len, ad + 1, ad_len));
580   EXPECT_EQ(Bytes(plaintext + 1, sizeof(plaintext) - 1),
581             Bytes(out + 1, out_len));
582 }
583 
TEST_P(PerAEADTest,Overflow)584 TEST_P(PerAEADTest, Overflow) {
585   alignas(64) uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
586   OPENSSL_memset(key, 'K', sizeof(key));
587 
588   bssl::ScopedEVP_AEAD_CTX ctx;
589   const size_t max_tag_len = EVP_AEAD_max_tag_len(aead());
590   ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(ctx.get(), aead(), key,
591                                                EVP_AEAD_key_length(aead()),
592                                                max_tag_len, evp_aead_seal));
593 
594   uint8_t plaintext[1] = {0};
595   uint8_t ciphertext[1024] = {0};
596   size_t ciphertext_len;
597   // The AEAD must not overflow when calculating the ciphertext length.
598   ASSERT_FALSE(EVP_AEAD_CTX_seal(
599       ctx.get(), ciphertext, &ciphertext_len, sizeof(ciphertext), nullptr, 0,
600       plaintext, std::numeric_limits<size_t>::max() - max_tag_len + 1, nullptr,
601       0));
602   ERR_clear_error();
603 
604   // (Can't test the scatter interface because it'll attempt to zero the output
605   // buffer on error and the primary output buffer is implicitly the same size
606   // as the input.)
607 }
608 
609 // Test that EVP_aead_aes_128_gcm and EVP_aead_aes_256_gcm reject empty nonces.
610 // AES-GCM is not defined for those.
TEST(AEADTest,AESGCMEmptyNonce)611 TEST(AEADTest, AESGCMEmptyNonce) {
612   static const uint8_t kZeros[32] = {0};
613 
614   // Test AES-128-GCM.
615   uint8_t buf[16];
616   size_t len;
617   bssl::ScopedEVP_AEAD_CTX ctx;
618   ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_gcm(), kZeros, 16,
619                                 EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
620 
621   EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
622                                  nullptr /* nonce */, 0, nullptr /* in */, 0,
623                                  nullptr /* ad */, 0));
624   uint32_t err = ERR_get_error();
625   EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
626   EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
627 
628   EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
629                                  nullptr /* nonce */, 0, kZeros /* in */,
630                                  sizeof(kZeros), nullptr /* ad */, 0));
631   err = ERR_get_error();
632   EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
633   EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
634 
635   // Test AES-256-GCM.
636   ctx.Reset();
637   ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_256_gcm(), kZeros, 32,
638                                 EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
639 
640   EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
641                                  nullptr /* nonce */, 0, nullptr /* in */, 0,
642                                  nullptr /* ad */, 0));
643   err = ERR_get_error();
644   EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
645   EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
646 
647   EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
648                                  nullptr /* nonce */, 0, kZeros /* in */,
649                                  sizeof(kZeros), nullptr /* ad */, 0));
650   err = ERR_get_error();
651   EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
652   EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
653 }
654