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