diff options
author | Spencer Jackson <spencer.jackson@mongodb.com> | 2021-10-18 19:14:32 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-10-18 20:43:06 +0000 |
commit | 838a9ac7510e6169b6af748e994b315eecd94c52 (patch) | |
tree | 37a30199692eba8872d6b0e7c3d319d777278c57 | |
parent | 0992b4dc9440efa979b73e88566c906459ba0f40 (diff) | |
download | mongo-838a9ac7510e6169b6af748e994b315eecd94c52.tar.gz |
SERVER-60568 Add tests with official GCM test vectors
-rw-r--r-- | src/mongo/crypto/symmetric_crypto_test.cpp | 147 | ||||
-rw-r--r-- | src/mongo/crypto/symmetric_crypto_windows.cpp | 6 |
2 files changed, 153 insertions, 0 deletions
diff --git a/src/mongo/crypto/symmetric_crypto_test.cpp b/src/mongo/crypto/symmetric_crypto_test.cpp index eb154520e84..47834b77770 100644 --- a/src/mongo/crypto/symmetric_crypto_test.cpp +++ b/src/mongo/crypto/symmetric_crypto_test.cpp @@ -35,6 +35,7 @@ #include "mongo/crypto/block_packer.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/hex.h" namespace mongo { namespace crypto { @@ -478,5 +479,151 @@ TEST(AES, GCMAdditionalAuthenticatedData) { GCMAdditionalAuthenticatedDataHelper(false); } +class AESGCMTestVectors : public unittest::Test { +public: + class GCMTestVector { + public: + GCMTestVector(StringData key, + StringData plaintext, + StringData a, + StringData iv, + StringData ciphertext, + StringData tag) { + this->key = hexblob::decode(key); + this->plaintext = hexblob::decode(plaintext); + this->a = hexblob::decode(a); + this->iv = hexblob::decode(iv); + this->ciphertext = hexblob::decode(ciphertext); + this->tag = hexblob::decode(tag); + } + + std::string key; + std::string plaintext; + std::string a; + std::string iv; + std::string ciphertext; + std::string tag; + }; + + void evaluate(GCMTestVector test) { + constexpr auto mode = crypto::aesMode::gcm; + + if (getSupportedSymmetricAlgorithms().count(getStringFromCipherMode(mode)) == 0) { + return; + } + + SymmetricKey key = aesGeneratePredictableKey256(test.key, "testID"); + + // Validate encryption + auto encryptor = uassertStatusOK(crypto::SymmetricEncryptor::create( + key, mode, asUint8(test.iv.c_str()), test.iv.size())); + + ASSERT_OK(encryptor->addAuthenticatedData(asUint8(test.a.c_str()), test.a.size())); + + const size_t kBufferSize = test.plaintext.size(); + { + std::vector<uint8_t> encryptionResult(kBufferSize); + auto cipherLen = uassertStatusOK(encryptor->update(asUint8(test.plaintext.c_str()), + test.plaintext.size(), + encryptionResult.data(), + encryptionResult.size())); + cipherLen += uassertStatusOK(encryptor->finalize(encryptionResult.data() + cipherLen, + encryptionResult.size() - cipherLen)); + + ASSERT_EQ(test.ciphertext.size(), cipherLen); + ASSERT_EQ(hexblob::encode(StringData(test.ciphertext.data(), test.ciphertext.size())), + hexblob::encode( + StringData(asChar(encryptionResult.data()), encryptionResult.size()))); + + std::array<std::uint8_t, 12> tag; + const auto taglen = uassertStatusOK(encryptor->finalizeTag(tag.data(), tag.size())); + ASSERT_EQ(tag.size(), taglen); + ASSERT_EQ(hexblob::encode(StringData(test.tag.data(), test.tag.size())).substr(0, 24), + hexblob::encode(StringData(asChar(tag.data()), tag.size()))); + } + { + // Validate decryption + auto decryptor = uassertStatusOK(crypto::SymmetricDecryptor::create( + key, mode, asUint8(test.iv.c_str()), test.iv.size())); + uassertStatusOK(decryptor->updateTag(asUint8(test.tag.data()), 12)); + + ASSERT_OK(decryptor->addAuthenticatedData(asUint8(test.a.c_str()), test.a.size())); + std::vector<uint8_t> decryptionResult(kBufferSize); + auto decipherLen = uassertStatusOK(decryptor->update(asUint8(test.ciphertext.c_str()), + test.ciphertext.size(), + decryptionResult.data(), + decryptionResult.size())); + decipherLen += uassertStatusOK(decryptor->finalize( + decryptionResult.data() + decipherLen, decryptionResult.size() - decipherLen)); + + ASSERT_EQ(test.plaintext.size(), decipherLen); + ASSERT_EQ(hexblob::encode(StringData(test.plaintext.data(), test.plaintext.size())), + hexblob::encode( + StringData(asChar(decryptionResult.data()), decryptionResult.size()))); + } + } +}; + +/** Test vectors drawn from + * https://csrc.nist.rip/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf + */ +TEST_F(AESGCMTestVectors, TestCase13) { + evaluate( + GCMTestVector("00000000000000000000000000000000" + "00000000000000000000000000000000"_sd, + ""_sd, + ""_sd, + "000000000000000000000000"_sd, + ""_sd, + "530f8afbc74536b9a963b4f1c4cb738b"_sd)); +} + +TEST_F(AESGCMTestVectors, TestCase14) { + evaluate( + GCMTestVector("00000000000000000000000000000000" + "00000000000000000000000000000000"_sd, + "00000000000000000000000000000000"_sd, + ""_sd, + "000000000000000000000000"_sd, + "cea7403d4d606b6e074ec5d3baf39d18"_sd, + "d0d1c8a799996bf0265b98b5d48ab919"_sd)); +} + +TEST_F(AESGCMTestVectors, TestCase15) { + evaluate( + GCMTestVector("feffe9928665731c6d6a8f9467308308" + "feffe9928665731c6d6a8f9467308308"_sd, + "d9313225f88406e5a55909c5aff5269a" + "86a7a9531534f7da2e4c303d8a318a72" + "1c3c0c95956809532fcf0e2449a6b525" + "b16aedf5aa0de657ba637b391aafd255"_sd, + ""_sd, + "cafebabefacedbaddecaf888"_sd, + "522dc1f099567d07f47f37a32a84427d" + "643a8cdcbfe5c0c97598a2bd2555d1aa" + "8cb08e48590dbb3da7b08b1056828838" + "c5f61e6393ba7a0abcc9f662898015ad"_sd, + "b094dac5d93471bdec1a502270e3cc6c"_sd)); +} + +TEST_F(AESGCMTestVectors, TestCase16) { + evaluate( + GCMTestVector("feffe9928665731c6d6a8f9467308308" + "feffe9928665731c6d6a8f9467308308"_sd, + "d9313225f88406e5a55909c5aff5269a" + "86a7a9531534f7da2e4c303d8a318a72" + "1c3c0c95956809532fcf0e2449a6b525" + "b16aedf5aa0de657ba637b39"_sd, + "feedfacedeadbeeffeedfacedeadbeef" + "abaddad2"_sd, + "cafebabefacedbaddecaf888"_sd, + "522dc1f099567d07f47f37a32a84427d" + "643a8cdcbfe5c0c97598a2bd2555d1aa" + "8cb08e48590dbb3da7b08b1056828838" + "c5f61e6393ba7a0abcc9f662"_sd, + "76fc6ece0f4e1768cddf8853bb2d551b"_sd)); +} + + } // namespace crypto } // namespace mongo diff --git a/src/mongo/crypto/symmetric_crypto_windows.cpp b/src/mongo/crypto/symmetric_crypto_windows.cpp index e2e88cc5d23..fc621f4bcb0 100644 --- a/src/mongo/crypto/symmetric_crypto_windows.cpp +++ b/src/mongo/crypto/symmetric_crypto_windows.cpp @@ -338,6 +338,12 @@ public: _paddingInfo->cbAuthData = 0; } + // BCryptEncrypt may refuse to process GCM tags if no output buffer is provided. + uint8_t dummyOut; + if (!out) { + out = &dummyOut; + } + auto remainder = _packer.getBlock(); // if there is any data left over in the block buffer, we will encrypt it with padding ULONG len = 0; |