Skip to content

Commit 1a39c7b

Browse files
author
eroman@chromium.org
committed
Prevent invalid memory read when AES-CBC decrypting.
The issue happens when the ciphertext is not a multiple of the block size. BUG=300681 Review URL: https://codereview.chromium.org/25164002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@226199 0039d316-1c4b-4281-b951-d872f2087c98
1 parent 987422f commit 1a39c7b

File tree

2 files changed

+38
-3
lines changed

2 files changed

+38
-3
lines changed

crypto/encryptor_nss.cc

+12-3
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,18 @@ bool Encryptor::Decrypt(const base::StringPiece& ciphertext,
9595
if (!context.get())
9696
return false;
9797

98-
return (mode_ == CTR) ?
99-
CryptCTR(context.get(), ciphertext, plaintext) :
100-
Crypt(context.get(), ciphertext, plaintext);
98+
if (mode_ == CTR)
99+
return CryptCTR(context.get(), ciphertext, plaintext);
100+
101+
if (ciphertext.size() % AES_BLOCK_SIZE != 0) {
102+
// Decryption will fail if the input is not a multiple of the block size.
103+
// PK11_CipherOp has a bug where it will do an invalid memory access before
104+
// the start of the input, so avoid calling it. (Possibly NSS bug 921687).
105+
plaintext->clear();
106+
return false;
107+
}
108+
109+
return Crypt(context.get(), ciphertext, plaintext);
101110
}
102111

103112
bool Encryptor::Crypt(PK11Context* context,

crypto/encryptor_unittest.cc

+26
Original file line numberDiff line numberDiff line change
@@ -530,3 +530,29 @@ TEST(EncryptorTest, EmptyEncrypt) {
530530
EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(),
531531
ciphertext.size()));
532532
}
533+
534+
TEST(EncryptorTest, CipherTextNotMultipleOfBlockSize) {
535+
std::string key = "128=SixteenBytes";
536+
std::string iv = "Sweet Sixteen IV";
537+
538+
scoped_ptr<crypto::SymmetricKey> sym_key(crypto::SymmetricKey::Import(
539+
crypto::SymmetricKey::AES, key));
540+
ASSERT_TRUE(sym_key.get());
541+
542+
crypto::Encryptor encryptor;
543+
// The IV must be exactly as long a the cipher block size.
544+
EXPECT_EQ(16U, iv.size());
545+
EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv));
546+
547+
// Use a separately allocated array to improve the odds of the memory tools
548+
// catching invalid accesses.
549+
//
550+
// Otherwise when using std::string as the other tests do, accesses several
551+
// bytes off the end of the buffer may fall inside the reservation of
552+
// the string and not be detected.
553+
scoped_ptr<char[]> ciphertext(new char[1]);
554+
555+
std::string plaintext;
556+
EXPECT_FALSE(
557+
encryptor.Decrypt(base::StringPiece(ciphertext.get(), 1), &plaintext));
558+
}

0 commit comments

Comments
 (0)