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> ¶ms)
__anon9fbfe1db0102(const testing::TestParamInfo<KnownAEAD> ¶ms) 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