diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2022-02-01 18:26:15 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-02-08 17:50:18 +0000 |
commit | 05bfa1650c360c08da127095961b8fa22d8402f0 (patch) | |
tree | 2e620cb91f6bf94ee3651e66daaccf4e3ca29ccd /src | |
parent | f985a4968d8c7da13c65bbe43f8215d71ceb2ebb (diff) | |
download | mongo-05bfa1650c360c08da127095961b8fa22d8402f0.tar.gz |
SERVER-63192 Add slice, split, and sliceAndAdvance APIs to CDRC
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/base/data_range.h | 65 | ||||
-rw-r--r-- | src/mongo/base/data_range_cursor.h | 22 | ||||
-rw-r--r-- | src/mongo/base/data_range_cursor_test.cpp | 57 | ||||
-rw-r--r-- | src/mongo/base/data_range_test.cpp | 92 | ||||
-rw-r--r-- | src/mongo/base/data_type_terminated_test.cpp | 2 | ||||
-rw-r--r-- | src/mongo/crypto/aead_encryption.cpp | 28 | ||||
-rw-r--r-- | src/mongo/crypto/symmetric_crypto_apple.cpp | 13 | ||||
-rw-r--r-- | src/mongo/crypto/symmetric_crypto_openssl.cpp | 20 | ||||
-rw-r--r-- | src/mongo/crypto/symmetric_crypto_test.cpp | 4 |
9 files changed, 259 insertions, 44 deletions
diff --git a/src/mongo/base/data_range.h b/src/mongo/base/data_range.h index d8b50807fbd..a366513ce3d 100644 --- a/src/mongo/base/data_range.h +++ b/src/mongo/base/data_range.h @@ -32,6 +32,7 @@ #include <cstring> #include <tuple> #include <type_traits> +#include <utility> #include "mongo/base/data_type.h" #include "mongo/base/error_codes.h" @@ -162,6 +163,24 @@ public: return uassertStatusOK(readNoThrow<T>(offset)); } + /** + * Split this ConstDataRange into two parts at `splitPoint`. + * May provide either a pointer within the range or an offset from the beginning. + */ + template <typename T> + auto split(const T& splitPoint) const { + return doSplit<ConstDataRange>(splitPoint); + } + + /** + * Create a smaller chunk of the original ConstDataRange. + * May provide either a pointer within the range or an offset from the beginning. + */ + template <typename T> + auto slice(const T& splitPoint) const { + return doSlice<ConstDataRange>(splitPoint); + } + friend bool operator==(const ConstDataRange& lhs, const ConstDataRange& rhs) { return std::tie(lhs._begin, lhs._end) == std::tie(rhs._begin, rhs._end); } @@ -170,6 +189,34 @@ public: return !(lhs == rhs); } +protected: + // Shared implementation of split() logic between DataRange and ConstDataRange. + template <typename RangeT, + typename ByteLike, + typename std::enable_if_t<isByteV<ByteLike>, int> = 0> + std::pair<RangeT, RangeT> doSplit(const ByteLike* splitPoint) const { + const auto* typedPoint = reinterpret_cast<const byte_type*>(splitPoint); + uassert(ErrorCodes::BadValue, + "Invalid split point", + (typedPoint >= _begin) && (typedPoint <= _end)); + // RangeT will enforce constness, so use common-denominator for args to ctor. + auto* begin = const_cast<byte_type*>(_begin); + auto* split = const_cast<byte_type*>(typedPoint); + auto* end = const_cast<byte_type*>(_end); + return {{begin, split}, {split, end}}; + } + + template <typename RangeT> + auto doSplit(std::size_t splitPoint) const { + return doSplit<RangeT>(data() + splitPoint); + } + + // Convenience wrapper to just grab the first half of a split. + template <typename RangeT, typename T> + RangeT doSlice(const T& splitPoint) const { + auto parts = doSplit<RangeT>(splitPoint); + return parts.first; + } protected: const byte_type* _begin; @@ -246,6 +293,24 @@ public: void write(const T& value, std::size_t offset = 0) { uassertStatusOK(writeNoThrow(value, offset)); } + + using ConstDataRange::data; + template <typename ByteLike = byte_type> + ByteLike* data() noexcept { + return reinterpret_cast<ByteLike*>(const_cast<byte_type*>(_begin)); + } + + using ConstDataRange::split; + template <typename T> + auto split(const T& splitPoint) { + return doSplit<DataRange>(splitPoint); + } + + using ConstDataRange::slice; + template <typename T> + auto slice(const T& splitPoint) { + return doSlice<DataRange>(splitPoint); + } }; struct DataRangeTypeHelper { diff --git a/src/mongo/base/data_range_cursor.h b/src/mongo/base/data_range_cursor.h index 89dff93eb43..b11797c1a73 100644 --- a/src/mongo/base/data_range_cursor.h +++ b/src/mongo/base/data_range_cursor.h @@ -117,6 +117,17 @@ public: return uassertStatusOK(readAndAdvanceNoThrow<T>()); } + /** + * Return a ConstDataRange based on `splitPoint` + * and advance the cursor past there. + */ + template <typename ByteLike> + ConstDataRange sliceAndAdvance(const ByteLike& splitPoint) { + auto ret = slice(splitPoint); + advance(ret.length()); + return ret; + } + private: Status makeAdvanceStatus(size_t advance) const; }; @@ -220,6 +231,17 @@ public: uassertStatusOK(writeAndAdvanceNoThrow(value)); } + /** + * Return a DataRange based on `splitPoint` + * and advance the cursor past there. + */ + template <typename ByteLike> + DataRange sliceAndAdvance(const ByteLike& splitPoint) { + auto ret = slice(splitPoint); + advance(ret.length()); + return ret; + } + private: Status makeAdvanceStatus(size_t advance) const; }; diff --git a/src/mongo/base/data_range_cursor_test.cpp b/src/mongo/base/data_range_cursor_test.cpp index 60543c6af6a..a91bf708d28 100644 --- a/src/mongo/base/data_range_cursor_test.cpp +++ b/src/mongo/base/data_range_cursor_test.cpp @@ -34,6 +34,26 @@ #include "mongo/unittest/unittest.h" namespace mongo { +namespace { +// ConstDataRange::operator==() requires that the pointers +// refer to the same memory addresses. +// So just promote to a string that we can do direct comparisons on. +std::string toString(ConstDataRange cdr) { + return std::string(cdr.data(), cdr.length()); +} + +// The ASSERT macro can't handle template specialization, +// so work out the value external to the macro call. +template <typename T> +bool isConstDataRange(const T& val) { + return std::is_same_v<T, ConstDataRange>; +} + +template <typename T> +bool isDataRange(const T& val) { + return std::is_same_v<T, DataRange>; +} +} // namespace TEST(DataRangeCursor, ConstDataRangeCursor) { char buf[14]; @@ -102,4 +122,41 @@ TEST(DataRangeCursor, DataRangeCursorType) { ASSERT_EQUALS(std::string("fooZ"), buf2); } + +TEST(DataRangeCursor, sliceAndAdvance) { + std::string buffer = "Hello World"; + ConstDataRangeCursor bufferCDRC(buffer.c_str(), buffer.size()); + + // Split by position in range [0..length) + auto helloCDR = bufferCDRC.sliceAndAdvance(5); + ASSERT_EQ(toString(helloCDR), "Hello"); + ASSERT_EQ(toString(bufferCDRC), " World"); + + // Split by pointer + auto spaceCDR = bufferCDRC.sliceAndAdvance(bufferCDRC.data() + 1); + ASSERT_EQ(toString(spaceCDR), " "); + ASSERT_EQ(toString(bufferCDRC), "World"); + + // Get DataRange from a DataRangeCursor if original was non-const. + DataRangeCursor mutableDRC(const_cast<char*>(buffer.c_str()), buffer.size()); + auto mutableByLen = mutableDRC.sliceAndAdvance(1); + ASSERT_TRUE(isDataRange(mutableByLen)); + + // Get ConstDataRange from a DataRangeCursor if original was const. + const DataRange nonmutableDRC = mutableDRC; + auto nonmutableCDR = nonmutableDRC.slice(2); + ASSERT_TRUE(isConstDataRange(nonmutableCDR)); +} + +TEST(DataRange, sliceAndAdvanceThrow) { + std::string buffer("Hello World"); + ConstDataRangeCursor bufferCDRC(buffer.c_str(), buffer.size()); + + // Split point is out of range. + ASSERT_THROWS(bufferCDRC.sliceAndAdvance(bufferCDRC.length() + 1), AssertionException); + ASSERT_THROWS(bufferCDRC.sliceAndAdvance(bufferCDRC.data() + bufferCDRC.length() + 1), + AssertionException); + ASSERT_THROWS(bufferCDRC.sliceAndAdvance(bufferCDRC.data() - 1), AssertionException); +} + } // namespace mongo diff --git a/src/mongo/base/data_range_test.cpp b/src/mongo/base/data_range_test.cpp index f45c6e26bbf..9d121406ed8 100644 --- a/src/mongo/base/data_range_test.cpp +++ b/src/mongo/base/data_range_test.cpp @@ -36,6 +36,26 @@ #include "mongo/unittest/unittest.h" namespace mongo { +namespace { +// ConstDataRange::operator==() requires that the pointers +// refer to the same memory addresses. +// So just promote to a string that we can do direct comparisons on. +std::string toString(ConstDataRange cdr) { + return std::string(cdr.data(), cdr.length()); +} + +// The ASSERT macro can't handle template specialization, +// so work out the value external to the macro call. +template <typename T> +bool isConstDataRange(const T& val) { + return std::is_same_v<T, ConstDataRange>; +} + +template <typename T> +bool isDataRange(const T& val) { + return std::is_same_v<T, DataRange>; +} +} // namespace TEST(DataRange, ConstDataRange) { unsigned char buf[sizeof(uint32_t) * 3]; @@ -128,4 +148,76 @@ TEST(DataRange, InitFromContainer) { ASSERT_EQUALS(status, ErrorCodes::Overflow); } +TEST(DataRange, slice) { + std::string buffer("Hello World"); + ConstDataRange bufferCDR(buffer.c_str(), buffer.size()); + + // Split by position in range [0..length) + auto helloByLen = bufferCDR.slice(5); + ASSERT_EQ(helloByLen.length(), 5); + ASSERT_EQ(toString(helloByLen), "Hello"); + + // Split by pointer within range + auto helloByPtr = bufferCDR.slice(bufferCDR.data() + 4); + ASSERT_EQ(helloByPtr.length(), 4); + ASSERT_EQ(toString(helloByPtr), "Hell"); + + // Get DataRange from a DataRange if original was non-const. + DataRange mutableDR(const_cast<char*>(buffer.c_str()), buffer.size()); + auto mutableByLen = mutableDR.slice(1); + ASSERT_TRUE(isDataRange(mutableByLen)); + + // Get ConstDataRange from a DataRange if original was const. + const DataRange nonmutableDR = mutableDR; + auto nonmutableCDR = nonmutableDR.slice(2); + ASSERT_TRUE(isConstDataRange(nonmutableCDR)); +} + +TEST(DataRange, sliceThrow) { + std::string buffer("Hello World"); + ConstDataRange bufferCDR(buffer.c_str(), buffer.size()); + + // Split point is out of range. + ASSERT_THROWS(bufferCDR.slice(bufferCDR.length() + 1), AssertionException); + ASSERT_THROWS(bufferCDR.slice(bufferCDR.data() + bufferCDR.length() + 1), AssertionException); + ASSERT_THROWS(bufferCDR.slice(bufferCDR.data() - 1), AssertionException); +} + +TEST(DataRange, split) { + std::string buffer("Hello World"); + ConstDataRange bufferCDR(buffer.c_str(), buffer.size()); + + // Split by position in range [0..length) + auto [hello, world] = bufferCDR.split(6); + ASSERT_EQ(toString(hello), "Hello "); + ASSERT_EQ(toString(world), "World"); + + // Split by pointer within range + auto [hell, oWorld] = bufferCDR.split(bufferCDR.data() + 4); + ASSERT_EQ(toString(hell), "Hell"); + ASSERT_EQ(toString(oWorld), "o World"); + + // Get DataRange from a DataRange if original was non-const. + DataRange bufferDR(const_cast<char*>(buffer.c_str()), buffer.size()); + auto [dr1, dr2] = bufferDR.split(6); + ASSERT_TRUE(isDataRange(dr1)); + ASSERT_TRUE(isDataRange(dr2)); + + // Get ConstDataRange from a DataRange if original was const. + const DataRange constBufferDR = bufferDR; + auto [cdr1, cdr2] = constBufferDR.split(6); + ASSERT_TRUE(isConstDataRange(cdr1)); + ASSERT_TRUE(isConstDataRange(cdr2)); +} + +TEST(DataRange, splitThrow) { + std::string buffer("Hello World"); + ConstDataRange bufferCDR(buffer.c_str(), buffer.size()); + + // Split point is out of range. + ASSERT_THROWS(bufferCDR.split(bufferCDR.length() + 1), AssertionException); + ASSERT_THROWS(bufferCDR.split(bufferCDR.data() + bufferCDR.length() + 1), AssertionException); + ASSERT_THROWS(bufferCDR.split(bufferCDR.data() - 1), AssertionException); +} + } // namespace mongo diff --git a/src/mongo/base/data_type_terminated_test.cpp b/src/mongo/base/data_type_terminated_test.cpp index d516626e3b9..fdc5d1a6ef7 100644 --- a/src/mongo/base/data_type_terminated_test.cpp +++ b/src/mongo/base/data_type_terminated_test.cpp @@ -230,7 +230,7 @@ TEST(DataTypeTerminated, ThroughDataRangeCursor) { Terminated<'\0', ConstDataRange> tcdr(ConstDataRange(s.data(), s.data() + s.size())); ASSERT_OK(buf_writer.writeAndAdvanceNoThrow(tcdr)); } - const auto written = std::string(static_cast<const char*>(buf), buf_writer.data()); + const auto written = std::string(static_cast<char*>(buf), buf_writer.data()); ASSERT_EQUALS(written, serialized); } { diff --git a/src/mongo/crypto/aead_encryption.cpp b/src/mongo/crypto/aead_encryption.cpp index e57dd03edc8..aea4939f417 100644 --- a/src/mongo/crypto/aead_encryption.cpp +++ b/src/mongo/crypto/aead_encryption.cpp @@ -47,10 +47,6 @@ constexpr size_t kIVSize = 16; // object, a value of 1<<16 was decided to cap the maximum size of AssociatedData. constexpr int kMaxAssociatedDataLength = 1 << 16; -std::uint8_t* asUint8(DataRange buffer) { - return const_cast<std::uint8_t*>(buffer.data<std::uint8_t>()); -} - size_t aesCBCCipherOutputLength(size_t plainTextLen) { return aesBlockSize * (1 + plainTextLen / aesBlockSize); } @@ -64,7 +60,7 @@ void aeadGenerateIV(const SymmetricKey* key, DataRange buffer) { fassert(51235, "IV buffer is too small for selected mode"); } - auto status = engineRandBytes({asUint8(buffer), aesCBCIVSize}); + auto status = engineRandBytes(buffer.slice(aesCBCIVSize)); if (!status.isOK()) { fassert(51236, status); } @@ -79,8 +75,7 @@ StatusWith<std::size_t> _aesEncrypt(const SymmetricKey& key, } DataRangeCursor out(outRange); - DataRange iv(asUint8(out), aesCBCIVSize); - out.advance(aesCBCIVSize); + DataRange iv = out.sliceAndAdvance(aesCBCIVSize); auto encryptor = uassertStatusOK(SymmetricEncryptor::create(key, aesMode::cbc, iv)); @@ -122,8 +117,7 @@ StatusWith<std::size_t> _aesDecrypt(const SymmetricKey& key, ConstDataRangeCursor in(inRange); - ConstDataRange iv(inRange.data(), aesCBCIVSize); - in.advance(aesCBCIVSize); + auto iv = in.sliceAndAdvance(aesCBCIVSize); auto decryptor = uassertStatusOK(SymmetricDecryptor::create(key, aesMode::cbc, iv)); @@ -294,7 +288,7 @@ Status aeadEncryptWithIV(ConstDataRange key, SymmetricKey symEncKey(encKey, sym256KeySize, aesAlgorithm, "aesKey", 1); std::size_t aesOutLen = out.length() - kHmacOutSize; - auto swEncrypt = _aesEncrypt(symEncKey, in, {asUint8(out), aesOutLen}, ivProvided); + auto swEncrypt = _aesEncrypt(symEncKey, in, {out.data(), aesOutLen}, ivProvided); if (!swEncrypt.isOK()) { return swEncrypt.getStatus(); } @@ -302,15 +296,16 @@ Status aeadEncryptWithIV(ConstDataRange key, // Split `out` into two separate ranges. // One for the just written ciphertext, // and another for the HMAC signature on the end. - ConstDataRange cipherTextRange(out.data(), swEncrypt.getValue()); - DataRange hmacRange(asUint8(out) + cipherTextRange.length(), kHmacOutSize); + DataRangeCursor outCursor(out); + auto cipherTextRange = outCursor.sliceAndAdvance(swEncrypt.getValue()); SHA512Block hmacOutput = SHA512Block::computeHmac( macKey, sym256KeySize, {associatedData, cipherTextRange, dataLenBitsEncoded}); // We intentionally only write the first 256 bits of the digest produced by SHA512. ConstDataRange truncatedHash(hmacOutput.data(), kHmacOutSize); - hmacRange.write(truncatedHash); + outCursor.writeAndAdvance(truncatedHash); + return Status::OK(); } @@ -347,10 +342,7 @@ StatusWith<std::size_t> aeadDecrypt(const SymmetricKey& key, const uint8_t* encKey = key.getKey() + sym256KeySize; // Split input into actual ciphertext, and the HMAC bit at the end. - const auto* inEnd = in.data() + in.length(); - const auto* hmacStart = inEnd - kHmacOutSize; - ConstDataRange cipherText(in.data(), hmacStart); - ConstDataRange hmacRange(hmacStart, inEnd); + auto [cipherText, hmacRange] = in.split(in.length() - kHmacOutSize); // According to the rfc on AES encryption, the associatedDataLength is defined as the // number of bits in associatedData in BigEndian format. This is what the code segment @@ -365,7 +357,7 @@ StatusWith<std::size_t> aeadDecrypt(const SymmetricKey& key, // Note that while we produce a 512bit digest with SHA512, // we only store and validate the first 256 bits (32 bytes). if (consttimeMemEqual(reinterpret_cast<const unsigned char*>(hmacOutput.data()), - reinterpret_cast<const unsigned char*>(hmacRange.data()), + hmacRange.data<unsigned char>(), kHmacOutSize) == false) { return Status(ErrorCodes::BadValue, "HMAC data authentication failed."); } diff --git a/src/mongo/crypto/symmetric_crypto_apple.cpp b/src/mongo/crypto/symmetric_crypto_apple.cpp index a99df2f1cb0..e3864e84dbe 100644 --- a/src/mongo/crypto/symmetric_crypto_apple.cpp +++ b/src/mongo/crypto/symmetric_crypto_apple.cpp @@ -46,11 +46,6 @@ namespace mongo { namespace crypto { namespace { -// Convenience wrapper for getting mutable pointer from DataRange. -std::uint8_t* asUint8(DataRange out) { - return const_cast<std::uint8_t*>(out.data<std::uint8_t>()); -} - template <typename Parent> class SymmetricImplApple : public Parent { public: @@ -93,7 +88,7 @@ public: StatusWith<std::size_t> update(ConstDataRange in, DataRange out) final { std::size_t outUsed = 0; const auto status = CCCryptorUpdate( - _ctx.get(), in.data(), in.length(), asUint8(out), out.length(), &outUsed); + _ctx.get(), in.data(), in.length(), out.data<std::uint8_t>(), out.length(), &outUsed); if (status != kCCSuccess) { return Status(ErrorCodes::UnknownError, str::stream() << "Unable to perform CCCryptorUpdate: " << status); @@ -108,7 +103,8 @@ public: StatusWith<size_t> finalize(DataRange out) final { size_t outUsed = 0; - const auto status = CCCryptorFinal(_ctx.get(), asUint8(out), out.length(), &outUsed); + const auto status = + CCCryptorFinal(_ctx.get(), out.data<std::uint8_t>(), out.length(), &outUsed); if (status != kCCSuccess) { return Status(ErrorCodes::UnknownError, str::stream() << "Unable to perform CCCryptorFinal: " << status); @@ -151,7 +147,8 @@ std::set<std::string> getSupportedSymmetricAlgorithms() { } Status engineRandBytes(DataRange buffer) { - auto result = SecRandomCopyBytes(kSecRandomDefault, buffer.length(), asUint8(buffer)); + auto result = + SecRandomCopyBytes(kSecRandomDefault, buffer.length(), buffer.data<std::uint8_t>()); if (result != errSecSuccess) { return {ErrorCodes::UnknownError, str::stream() << "Failed generating random bytes: " << result}; diff --git a/src/mongo/crypto/symmetric_crypto_openssl.cpp b/src/mongo/crypto/symmetric_crypto_openssl.cpp index 96f4e3c4622..bdf01cf5bb1 100644 --- a/src/mongo/crypto/symmetric_crypto_openssl.cpp +++ b/src/mongo/crypto/symmetric_crypto_openssl.cpp @@ -49,13 +49,6 @@ namespace mongo { namespace crypto { namespace { -// Convenience wrapper to get a mutable uint8_t* -// since DataRange returns a const pointer, -// and all those casts get ugly. -std::uint8_t* asUint8(DataRange dr) { - return const_cast<std::uint8_t*>(dr.data<std::uint8_t>()); -} - template <typename Init> void initCipherContext( EVP_CIPHER_CTX* ctx, const SymmetricKey& key, aesMode mode, ConstDataRange iv, Init init) { @@ -90,7 +83,7 @@ public: int len = 0; if (1 != EVP_EncryptUpdate( - _ctx.get(), asUint8(out), &len, in.data<std::uint8_t>(), in.length())) { + _ctx.get(), out.data<std::uint8_t>(), &len, in.data<std::uint8_t>(), in.length())) { return Status(ErrorCodes::UnknownError, str::stream() << SSLManagerInterface::getSSLErrorMessage(ERR_get_error())); @@ -118,7 +111,7 @@ public: StatusWith<std::size_t> finalize(DataRange out) final { int len = 0; - if (1 != EVP_EncryptFinal_ex(_ctx.get(), asUint8(out), &len)) { + if (1 != EVP_EncryptFinal_ex(_ctx.get(), out.data<std::uint8_t>(), &len)) { return Status(ErrorCodes::UnknownError, str::stream() << SSLManagerInterface::getSSLErrorMessage(ERR_get_error())); @@ -130,7 +123,8 @@ public: if (_mode == aesMode::gcm) { #ifdef EVP_CTRL_GCM_GET_TAG if (1 != - EVP_CIPHER_CTX_ctrl(_ctx.get(), EVP_CTRL_GCM_GET_TAG, out.length(), asUint8(out))) { + EVP_CIPHER_CTX_ctrl( + _ctx.get(), EVP_CTRL_GCM_GET_TAG, out.length(), out.data<std::uint8_t>())) { return Status(ErrorCodes::UnknownError, str::stream() << SSLManagerInterface::getSSLErrorMessage(ERR_get_error())); @@ -161,7 +155,7 @@ public: int len = 0; if (1 != EVP_DecryptUpdate( - _ctx.get(), asUint8(out), &len, in.data<std::uint8_t>(), in.length())) { + _ctx.get(), out.data<std::uint8_t>(), &len, in.data<std::uint8_t>(), in.length())) { return Status(ErrorCodes::UnknownError, str::stream() << SSLManagerInterface::getSSLErrorMessage(ERR_get_error())); @@ -189,7 +183,7 @@ public: StatusWith<std::size_t> finalize(DataRange out) final { int len = 0; - if (1 != EVP_DecryptFinal_ex(_ctx.get(), asUint8(out), &len)) { + if (1 != EVP_DecryptFinal_ex(_ctx.get(), out.data<std::uint8_t>(), &len)) { return Status(ErrorCodes::UnknownError, str::stream() << SSLManagerInterface::getSSLErrorMessage(ERR_get_error())); @@ -237,7 +231,7 @@ std::set<std::string> getSupportedSymmetricAlgorithms() { } Status engineRandBytes(DataRange buffer) { - if (RAND_bytes(asUint8(buffer), buffer.length()) == 1) { + if (RAND_bytes(buffer.data<std::uint8_t>(), buffer.length()) == 1) { return Status::OK(); } return {ErrorCodes::UnknownError, diff --git a/src/mongo/crypto/symmetric_crypto_test.cpp b/src/mongo/crypto/symmetric_crypto_test.cpp index faa9016b07f..14c89d12eda 100644 --- a/src/mongo/crypto/symmetric_crypto_test.cpp +++ b/src/mongo/crypto/symmetric_crypto_test.cpp @@ -386,10 +386,6 @@ SymmetricKey aesGeneratePredictableKey256(StringData stringKey, StringData keyId } // Convenience wrappers to avoid line-wraps later. -const std::uint8_t* asUint8(const char* str) { - return reinterpret_cast<const std::uint8_t*>(str); -}; - const char* asChar(const std::uint8_t* data) { return reinterpret_cast<const char*>(data); }; |