From 20ee8f6ac0208f5ba4e77f70b18b2d726782d0f8 Mon Sep 17 00:00:00 2001 From: Mark Benvenuto Date: Wed, 24 Jul 2019 14:27:00 -0400 Subject: SERVER-42318 Tighten bounds on AEAD Decrypt output length (cherry picked from commit 260a0ced5d3754f375fee6e220855e722c4b72b8) --- src/mongo/crypto/aead_encryption.cpp | 21 ++++++++++++++++----- src/mongo/crypto/aead_encryption.h | 6 ++++++ src/mongo/crypto/aead_encryption_test.cpp | 4 ++-- 3 files changed, 24 insertions(+), 7 deletions(-) (limited to 'src/mongo/crypto') diff --git a/src/mongo/crypto/aead_encryption.cpp b/src/mongo/crypto/aead_encryption.cpp index 3f898c48ff1..030758850c1 100644 --- a/src/mongo/crypto/aead_encryption.cpp +++ b/src/mongo/crypto/aead_encryption.cpp @@ -191,6 +191,14 @@ size_t aeadCipherOutputLength(size_t plainTextLen) { return aesOutLen + kHmacOutSize; } +StatusWith aeadGetMaximumPlainTextLength(size_t cipherTextLen) { + if (cipherTextLen > (aesCBCIVSize + kHmacOutSize)) { + return cipherTextLen - aesCBCIVSize - kHmacOutSize; + } + + return Status(ErrorCodes::BadValue, "Invalid cipher text length"); +} + Status aeadEncrypt(const SymmetricKey& key, const uint8_t* in, const size_t inLen, @@ -336,7 +344,12 @@ Status aeadDecrypt(const SymmetricKey& key, return Status(ErrorCodes::BadValue, "Invalid AEAD parameters."); } - if ((*outLen) != cipherLen) { + if (cipherLen < kHmacOutSize) { + return Status(ErrorCodes::BadValue, "Ciphertext is not long enough."); + } + + size_t expectedMaximumPlainTextSize = uassertStatusOK(aeadGetMaximumPlainTextLength(cipherLen)); + if ((*outLen) != expectedMaximumPlainTextSize) { return Status(ErrorCodes::BadValue, "Output buffer must be as long as the cipherText."); } @@ -351,9 +364,6 @@ Status aeadDecrypt(const SymmetricKey& key, const uint8_t* macKey = key.getKey(); const uint8_t* encKey = key.getKey() + sym256KeySize; - if (cipherLen < kHmacOutSize) { - return Status(ErrorCodes::BadValue, "Ciphertext is not long enough."); - } size_t aesLen = cipherLen - kHmacOutSize; // According to the rfc on AES encryption, the associatedDataLength is defined as the @@ -378,7 +388,8 @@ Status aeadDecrypt(const SymmetricKey& key, SymmetricKey symEncKey(encKey, sym256KeySize, aesAlgorithm, key.getKeyId(), 1); - auto sDecrypt = _aesDecrypt(symEncKey, ConstDataRange(cipherText, aesLen), out, aesLen, outLen); + auto sDecrypt = + _aesDecrypt(symEncKey, ConstDataRange(cipherText, aesLen), out, *outLen, outLen); if (!sDecrypt.isOK()) { return sDecrypt; } diff --git a/src/mongo/crypto/aead_encryption.h b/src/mongo/crypto/aead_encryption.h index c5fb79479e6..134e83bff08 100644 --- a/src/mongo/crypto/aead_encryption.h +++ b/src/mongo/crypto/aead_encryption.h @@ -52,6 +52,12 @@ constexpr size_t kAeadAesHmacKeySize = 64; size_t aeadCipherOutputLength(size_t plainTextLen); +/** + * Returns the length of the plaintext output given the ciphertext length. Only for AEAD. + */ +StatusWith aeadGetMaximumPlainTextLength(size_t cipherTextLen); + + /** * Encrypts the plaintext using following the AEAD_AES_256_CBC_HMAC_SHA_512 encryption * algorithm. Writes output to out. diff --git a/src/mongo/crypto/aead_encryption_test.cpp b/src/mongo/crypto/aead_encryption_test.cpp index febc8d137c0..f0417cec23e 100644 --- a/src/mongo/crypto/aead_encryption_test.cpp +++ b/src/mongo/crypto/aead_encryption_test.cpp @@ -136,8 +136,8 @@ TEST(AEAD, EncryptAndDecrypt) { ASSERT_EQ(0, std::memcmp(cryptoBuffer.data(), cryptoBufferTest.data(), 192)); - std::array plainText = {}; - size_t plainTextDecryptLen = 192; + std::array plainText = {}; + size_t plainTextDecryptLen = 144; ASSERT_OK(crypto::aeadDecrypt(key, cryptoBuffer.data(), cryptoBuffer.size(), -- cgit v1.2.1