diff options
author | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2019-07-24 14:27:00 -0400 |
---|---|---|
committer | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2019-07-24 14:27:00 -0400 |
commit | 260a0ced5d3754f375fee6e220855e722c4b72b8 (patch) | |
tree | d683fd51d63973a3e6c74faca0a295d1f84912fb /src/mongo | |
parent | baaa7c25fadcbe4f544a885be4734a0d50ad20d2 (diff) | |
download | mongo-260a0ced5d3754f375fee6e220855e722c4b72b8.tar.gz |
SERVER-42318 Tighten bounds on AEAD Decrypt output length
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/crypto/aead_encryption.cpp | 21 | ||||
-rw-r--r-- | src/mongo/crypto/aead_encryption.h | 6 | ||||
-rw-r--r-- | src/mongo/crypto/aead_encryption_test.cpp | 4 | ||||
-rw-r--r-- | src/mongo/shell/encrypted_dbclient_base.cpp | 6 | ||||
-rw-r--r-- | src/mongo/shell/kms_local.cpp | 3 |
5 files changed, 30 insertions, 10 deletions
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<size_t> 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 @@ -53,6 +53,12 @@ size_t aeadCipherOutputLength(size_t plainTextLen); /** + * Returns the length of the plaintext output given the ciphertext length. Only for AEAD. + */ +StatusWith<size_t> 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<uint8_t, 192> plainText = {}; - size_t plainTextDecryptLen = 192; + std::array<uint8_t, 144> plainText = {}; + size_t plainTextDecryptLen = 144; ASSERT_OK(crypto::aeadDecrypt(key, cryptoBuffer.data(), cryptoBuffer.size(), diff --git a/src/mongo/shell/encrypted_dbclient_base.cpp b/src/mongo/shell/encrypted_dbclient_base.cpp index c8858f8a9f3..bec5bb8ae5e 100644 --- a/src/mongo/shell/encrypted_dbclient_base.cpp +++ b/src/mongo/shell/encrypted_dbclient_base.cpp @@ -188,7 +188,8 @@ void EncryptedDBClientBase::decryptPayload(ConstDataRange data, UUID uuid = UUID::fromCDR(uuidCdr); auto key = getDataKey(uuid); - std::vector<uint8_t> out(data.length() - kAssociatedDataLength); + std::vector<uint8_t> out(uassertStatusOK( + crypto::aeadGetMaximumPlainTextLength(data.length() - kAssociatedDataLength))); size_t outLen = out.size(); uassertStatusOK( @@ -499,7 +500,8 @@ void EncryptedDBClientBase::decrypt(mozjs::MozJSImplScope* scope, UUID uuid = UUID::fromCDR(uuidCdr); auto key = getDataKey(uuid); - std::vector<uint8_t> out(binData.size() - kAssociatedDataLength); + std::vector<uint8_t> out(uassertStatusOK( + crypto::aeadGetMaximumPlainTextLength(binData.size() - kAssociatedDataLength))); size_t outLen = out.size(); auto decryptStatus = crypto::aeadDecrypt(*key, diff --git a/src/mongo/shell/kms_local.cpp b/src/mongo/shell/kms_local.cpp index e7a090211b3..628ea9ed9c2 100644 --- a/src/mongo/shell/kms_local.cpp +++ b/src/mongo/shell/kms_local.cpp @@ -93,7 +93,8 @@ BSONObj LocalKMSService::encryptDataKey(ConstDataRange cdr, StringData keyId) { } SecureVector<uint8_t> LocalKMSService::decrypt(ConstDataRange cdr, BSONObj masterKey) { - SecureVector<uint8_t> plaintext(cdr.length()); + SecureVector<uint8_t> plaintext( + uassertStatusOK(crypto::aeadGetMaximumPlainTextLength(cdr.length()))); size_t outLen = plaintext->size(); uassertStatusOK(crypto::aeadDecrypt(_key, |