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