Run EVP_CIPHER tests in-place.
I had a bug that was only caught in ssl_test. This would have caught it
in crypto_test (although only via Wycheproof test vectors; our
EVP_CIPHER CBC test vectors are all short.)
Change-Id: I8dc1457796cb6a8c0be808639657ce74967225ad
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39205
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/cipher_extra/cipher_test.cc b/crypto/cipher_extra/cipher_test.cc
index a28e6e3..5ff308c 100644
--- a/crypto/cipher_extra/cipher_test.cc
+++ b/crypto/cipher_extra/cipher_test.cc
@@ -118,7 +118,8 @@
}
static bool DoCipher(EVP_CIPHER_CTX *ctx, std::vector<uint8_t> *out,
- bssl::Span<const uint8_t> in, size_t chunk) {
+ bssl::Span<const uint8_t> in, size_t chunk,
+ bool in_place) {
size_t max_out = in.size();
if ((EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_NO_PADDING) == 0 &&
EVP_CIPHER_CTX_encrypting(ctx)) {
@@ -126,6 +127,10 @@
max_out += block_size - (max_out % block_size);
}
out->resize(max_out);
+ if (in_place) {
+ std::copy(in.begin(), in.end(), out->begin());
+ in = bssl::MakeConstSpan(out->data(), in.size());
+ }
size_t total = 0;
int len;
@@ -150,7 +155,7 @@
}
static void TestOperation(FileTest *t, const EVP_CIPHER *cipher, bool encrypt,
- bool copy, size_t chunk_size,
+ bool copy, bool in_place, size_t chunk_size,
const std::vector<uint8_t> &key,
const std::vector<uint8_t> &iv,
const std::vector<uint8_t> &plaintext,
@@ -207,7 +212,7 @@
}
ASSERT_TRUE(EVP_CIPHER_CTX_set_padding(ctx, 0));
std::vector<uint8_t> result;
- ASSERT_TRUE(DoCipher(ctx, &result, *in, chunk_size));
+ ASSERT_TRUE(DoCipher(ctx, &result, *in, chunk_size, in_place));
EXPECT_EQ(Bytes(*out), Bytes(result));
if (encrypt && is_aead) {
uint8_t rtag[16];
@@ -257,21 +262,24 @@
for (size_t chunk_size : chunk_sizes) {
SCOPED_TRACE(chunk_size);
- // By default, both directions are run, unless overridden by the operation.
- if (operation != kDecrypt) {
- SCOPED_TRACE("encrypt");
- TestOperation(t, cipher, true /* encrypt */, false /* no copy */,
- chunk_size, key, iv, plaintext, ciphertext, aad, tag);
- TestOperation(t, cipher, true /* encrypt */, true /* copy */, chunk_size,
- key, iv, plaintext, ciphertext, aad, tag);
- }
+ for (bool copy : {false, true}) {
+ SCOPED_TRACE(copy);
+ for (bool in_place : {false, true}) {
+ SCOPED_TRACE(in_place);
+ // By default, both directions are run, unless overridden by the
+ // operation.
+ if (operation != kDecrypt) {
+ SCOPED_TRACE("encrypt");
+ TestOperation(t, cipher, true /* encrypt */, copy, in_place,
+ chunk_size, key, iv, plaintext, ciphertext, aad, tag);
+ }
- if (operation != kEncrypt) {
- SCOPED_TRACE("decrypt");
- TestOperation(t, cipher, false /* decrypt */, false /* no copy */,
- chunk_size, key, iv, plaintext, ciphertext, aad, tag);
- TestOperation(t, cipher, false /* decrypt */, true /* copy */, chunk_size,
- key, iv, plaintext, ciphertext, aad, tag);
+ if (operation != kEncrypt) {
+ SCOPED_TRACE("decrypt");
+ TestOperation(t, cipher, false /* decrypt */, copy, in_place,
+ chunk_size, key, iv, plaintext, ciphertext, aad, tag);
+ }
+ }
}
}
}
@@ -319,59 +327,63 @@
}
TEST(CipherTest, WycheproofAESCBC) {
- FileTestGTest("third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
- [](FileTest *t) {
- t->IgnoreInstruction("type");
- t->IgnoreInstruction("ivSize");
+ FileTestGTest(
+ "third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
+ [](FileTest *t) {
+ t->IgnoreInstruction("type");
+ t->IgnoreInstruction("ivSize");
- std::string key_size;
- ASSERT_TRUE(t->GetInstruction(&key_size, "keySize"));
- const EVP_CIPHER *cipher;
- switch (atoi(key_size.c_str())) {
- case 128:
- cipher = EVP_aes_128_cbc();
- break;
- case 192:
- cipher = EVP_aes_192_cbc();
- break;
- case 256:
- cipher = EVP_aes_256_cbc();
- break;
- default:
- FAIL() << "Unsupported key size: " << key_size;
- }
+ std::string key_size;
+ ASSERT_TRUE(t->GetInstruction(&key_size, "keySize"));
+ const EVP_CIPHER *cipher;
+ switch (atoi(key_size.c_str())) {
+ case 128:
+ cipher = EVP_aes_128_cbc();
+ break;
+ case 192:
+ cipher = EVP_aes_192_cbc();
+ break;
+ case 256:
+ cipher = EVP_aes_256_cbc();
+ break;
+ default:
+ FAIL() << "Unsupported key size: " << key_size;
+ }
- std::vector<uint8_t> key, iv, msg, ct;
- ASSERT_TRUE(t->GetBytes(&key, "key"));
- ASSERT_TRUE(t->GetBytes(&iv, "iv"));
- ASSERT_TRUE(t->GetBytes(&msg, "msg"));
- ASSERT_TRUE(t->GetBytes(&ct, "ct"));
- ASSERT_EQ(EVP_CIPHER_key_length(cipher), key.size());
- ASSERT_EQ(EVP_CIPHER_iv_length(cipher), iv.size());
- WycheproofResult result;
- ASSERT_TRUE(GetWycheproofResult(t, &result));
+ std::vector<uint8_t> key, iv, msg, ct;
+ ASSERT_TRUE(t->GetBytes(&key, "key"));
+ ASSERT_TRUE(t->GetBytes(&iv, "iv"));
+ ASSERT_TRUE(t->GetBytes(&msg, "msg"));
+ ASSERT_TRUE(t->GetBytes(&ct, "ct"));
+ ASSERT_EQ(EVP_CIPHER_key_length(cipher), key.size());
+ ASSERT_EQ(EVP_CIPHER_iv_length(cipher), iv.size());
+ WycheproofResult result;
+ ASSERT_TRUE(GetWycheproofResult(t, &result));
- bssl::ScopedEVP_CIPHER_CTX ctx;
- std::vector<uint8_t> out;
- const std::vector<size_t> chunk_sizes = {0, 1, 2, 5, 7, 8, 9, 15, 16,
- 17, 31, 32, 33, 63, 64, 65, 512};
- for (size_t chunk : chunk_sizes) {
- SCOPED_TRACE(chunk);
- if (result.IsValid()) {
- ASSERT_TRUE(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr, key.data(),
- iv.data()));
- ASSERT_TRUE(DoCipher(ctx.get(), &out, ct, chunk));
- EXPECT_EQ(Bytes(msg), Bytes(out));
+ bssl::ScopedEVP_CIPHER_CTX ctx;
+ std::vector<uint8_t> out;
+ const std::vector<size_t> chunk_sizes = {
+ 0, 1, 2, 5, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65, 512};
+ for (size_t chunk : chunk_sizes) {
+ SCOPED_TRACE(chunk);
+ for (bool in_place : {false, true}) {
+ SCOPED_TRACE(in_place);
+ if (result.IsValid()) {
+ ASSERT_TRUE(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr,
+ key.data(), iv.data()));
+ ASSERT_TRUE(DoCipher(ctx.get(), &out, ct, chunk, in_place));
+ EXPECT_EQ(Bytes(msg), Bytes(out));
- ASSERT_TRUE(EVP_EncryptInit_ex(ctx.get(), cipher, nullptr, key.data(),
- iv.data()));
- ASSERT_TRUE(DoCipher(ctx.get(), &out, msg, chunk));
- EXPECT_EQ(Bytes(ct), Bytes(out));
- } else {
- ASSERT_TRUE(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr, key.data(),
- iv.data()));
- EXPECT_FALSE(DoCipher(ctx.get(), &out, ct, chunk));
- }
- }
- });
+ ASSERT_TRUE(EVP_EncryptInit_ex(ctx.get(), cipher, nullptr,
+ key.data(), iv.data()));
+ ASSERT_TRUE(DoCipher(ctx.get(), &out, msg, chunk, in_place));
+ EXPECT_EQ(Bytes(ct), Bytes(out));
+ } else {
+ ASSERT_TRUE(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr,
+ key.data(), iv.data()));
+ EXPECT_FALSE(DoCipher(ctx.get(), &out, ct, chunk, in_place));
+ }
+ }
+ }
+ });
}