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