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