aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto')
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Cipher.cpp123
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoMaterial.cpp34
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoScheme.cpp61
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp348
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoStream.cpp52
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/EncryptionMaterials.cpp19
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/KeyWrapAlgorithm.cpp68
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/MD5.cpp31
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256.cpp30
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256HMAC.cpp34
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp895
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp987
12 files changed, 2682 insertions, 0 deletions
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Cipher.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Cipher.cpp
new file mode 100644
index 0000000000..1c844273f4
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Cipher.cpp
@@ -0,0 +1,123 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/utils/crypto/Cipher.h>
+#include <aws/core/utils/crypto/Factories.h>
+#include <aws/core/utils/crypto/SecureRandom.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <cstdlib>
+#include <climits>
+
+//if you are reading this, you are witnessing pure brilliance.
+#define IS_BIG_ENDIAN (*(uint16_t*)"\0\xff" < 0x100)
+
+using namespace Aws::Utils::Crypto;
+using namespace Aws::Utils;
+
+namespace Aws
+{
+ namespace Utils
+ {
+ namespace Crypto
+ {
+ static const char* LOG_TAG = "Cipher";
+
+ //swap byte ordering
+ template<class T>
+ typename std::enable_if<std::is_unsigned<T>::value, T>::type
+ bswap(T i, T j = 0u, std::size_t n = 0u)
+ {
+ return n == sizeof(T) ? j :
+ bswap<T>(i >> CHAR_BIT, (j << CHAR_BIT) | (i & (T)(unsigned char)(-1)), n + 1);
+ }
+
+ CryptoBuffer IncrementCTRCounter(const CryptoBuffer& counter, uint32_t numberOfBlocks)
+ {
+ // minium counter size is 12 bytes. This isn't a variable because some compilers
+ // are stupid and thing that variable is unused.
+ assert(counter.GetLength() >= 12);
+
+ CryptoBuffer incrementedCounter(counter);
+
+ //get the last 4 bytes and manipulate them as an integer.
+ uint32_t* ctrPtr = (uint32_t*)(incrementedCounter.GetUnderlyingData() + incrementedCounter.GetLength() - sizeof(int32_t));
+ if(IS_BIG_ENDIAN)
+ {
+ //you likely are not Big Endian, but
+ //if it's big endian, just go ahead and increment it... done
+ *ctrPtr += numberOfBlocks;
+ }
+ else
+ {
+ //otherwise, swap the byte ordering of the integer we loaded from the buffer (because it is backwards). However, the number of blocks is already properly
+ //aligned. Once we compute the new value, swap it back so that the mirroring operation goes back to the actual buffer.
+ *ctrPtr = bswap<uint32_t>(bswap<uint32_t>(*ctrPtr) + numberOfBlocks);
+ }
+
+ return incrementedCounter;
+ }
+
+ CryptoBuffer GenerateXRandomBytes(size_t lengthBytes, bool ctrMode)
+ {
+ std::shared_ptr<SecureRandomBytes> rng = CreateSecureRandomBytesImplementation();
+
+ CryptoBuffer bytes(lengthBytes);
+ size_t lengthToGenerate = ctrMode ? (3 * bytes.GetLength()) / 4 : bytes.GetLength();
+
+ rng->GetBytes(bytes.GetUnderlyingData(), lengthToGenerate);
+
+ if(!*rng)
+ {
+ AWS_LOGSTREAM_FATAL(LOG_TAG, "Random Number generation failed. Abort all crypto operations.");
+ assert(false);
+ abort();
+ }
+
+ return bytes;
+ }
+
+ /**
+ * Generate random number per 4 bytes and use each byte for the byte in the iv
+ */
+ CryptoBuffer SymmetricCipher::GenerateIV(size_t ivLengthBytes, bool ctrMode)
+ {
+ CryptoBuffer iv(GenerateXRandomBytes(ivLengthBytes, ctrMode));
+
+ if(iv.GetLength() == 0)
+ {
+ AWS_LOGSTREAM_ERROR(LOG_TAG, "Unable to generate iv of length " << ivLengthBytes);
+ return iv;
+ }
+
+ if(ctrMode)
+ {
+ //init the counter
+ size_t length = iv.GetLength();
+ //[ nonce 1/4] [ iv 1/2 ] [ ctr 1/4 ]
+ size_t ctrStart = (length / 2) + (length / 4);
+ for(; ctrStart < iv.GetLength() - 1; ++ ctrStart)
+ {
+ iv[ctrStart] = 0;
+ }
+ iv[length - 1] = 1;
+ }
+
+ return iv;
+ }
+
+ CryptoBuffer SymmetricCipher::GenerateKey(size_t keyLengthBytes)
+ {
+ CryptoBuffer const& key = GenerateXRandomBytes(keyLengthBytes, false);
+
+ if(key.GetLength() == 0)
+ {
+ AWS_LOGSTREAM_ERROR(LOG_TAG, "Unable to generate key of length " << keyLengthBytes);
+ }
+
+ return key;
+ }
+ }
+ }
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoMaterial.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoMaterial.cpp
new file mode 100644
index 0000000000..3036bd70eb
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoMaterial.cpp
@@ -0,0 +1,34 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+#include <aws/core/utils/crypto/ContentCryptoMaterial.h>
+#include <aws/core/utils/crypto/Cipher.h>
+
+using namespace Aws::Utils::Crypto;
+
+namespace Aws
+{
+ namespace Utils
+ {
+ namespace Crypto
+ {
+ ContentCryptoMaterial::ContentCryptoMaterial() :
+ m_cryptoTagLength(0), m_keyWrapAlgorithm(KeyWrapAlgorithm::NONE), m_contentCryptoScheme(ContentCryptoScheme::NONE)
+ {
+ }
+
+ ContentCryptoMaterial::ContentCryptoMaterial(ContentCryptoScheme contentCryptoScheme) :
+ m_contentEncryptionKey(SymmetricCipher::GenerateKey()), m_cryptoTagLength(0), m_keyWrapAlgorithm(KeyWrapAlgorithm::NONE), m_contentCryptoScheme(contentCryptoScheme)
+ {
+
+ }
+
+ ContentCryptoMaterial::ContentCryptoMaterial(const Aws::Utils::CryptoBuffer & cek, ContentCryptoScheme contentCryptoScheme) :
+ m_contentEncryptionKey(cek), m_cryptoTagLength(0), m_keyWrapAlgorithm(KeyWrapAlgorithm::NONE), m_contentCryptoScheme(contentCryptoScheme)
+ {
+
+ }
+ }
+ }
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoScheme.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoScheme.cpp
new file mode 100644
index 0000000000..f39a75df2c
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoScheme.cpp
@@ -0,0 +1,61 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+#include <aws/core/utils/crypto/ContentCryptoScheme.h>
+#include <aws/core/utils/HashingUtils.h>
+#include <aws/core/utils/EnumParseOverflowContainer.h>
+#include <aws/core/Globals.h>
+
+using namespace Aws::Utils;
+
+namespace Aws
+{
+ namespace Utils
+ {
+ namespace Crypto
+ {
+ namespace ContentCryptoSchemeMapper
+ {
+ static const int cryptoScheme_CBC_HASH = HashingUtils::HashString("AES/CBC/PKCS5Padding");
+ static const int cryptoScheme_CTR_HASH = HashingUtils::HashString("AES/CTR/NoPadding");
+ static const int cryptoScheme_GCM_HASH = HashingUtils::HashString("AES/GCM/NoPadding");
+
+ ContentCryptoScheme GetContentCryptoSchemeForName(const Aws::String& name)
+ {
+ int hashcode = HashingUtils::HashString(name.c_str());
+ if (hashcode == cryptoScheme_CBC_HASH)
+ {
+ return ContentCryptoScheme::CBC;
+ }
+ else if (hashcode == cryptoScheme_CTR_HASH)
+ {
+ return ContentCryptoScheme::CTR;
+ }
+ else if (hashcode == cryptoScheme_GCM_HASH)
+ {
+ return ContentCryptoScheme::GCM;
+ }
+ assert(0);
+ return ContentCryptoScheme::NONE;
+ }
+
+ Aws::String GetNameForContentCryptoScheme(ContentCryptoScheme enumValue)
+ {
+ switch (enumValue)
+ {
+ case ContentCryptoScheme::CBC:
+ return "AES/CBC/PKCS5Padding";
+ case ContentCryptoScheme::CTR:
+ return "AES/CTR/NoPadding";
+ case ContentCryptoScheme::GCM:
+ return "AES/GCM/NoPadding";
+ default:
+ assert(0);
+ return "";
+ }
+ }
+ }//namespace ContentCryptoSchemeMapper
+ } //namespace Crypto
+ }//namespace Utils
+}//namespace Aws \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp
new file mode 100644
index 0000000000..2b47097679
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp
@@ -0,0 +1,348 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/utils/crypto/CryptoBuf.h>
+
+namespace Aws
+{
+ namespace Utils
+ {
+ namespace Crypto
+ {
+ SymmetricCryptoBufSrc::SymmetricCryptoBufSrc(Aws::IStream& stream, SymmetricCipher& cipher, CipherMode cipherMode, size_t bufferSize)
+ :
+ m_isBuf(PUT_BACK_SIZE), m_cipher(cipher), m_stream(stream), m_cipherMode(cipherMode), m_isFinalized(false),
+ m_bufferSize(bufferSize), m_putBack(PUT_BACK_SIZE)
+ {
+ char* end = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData() + m_isBuf.GetLength());
+ setg(end, end, end);
+ }
+
+ SymmetricCryptoBufSrc::pos_type SymmetricCryptoBufSrc::seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which)
+ {
+ if(which == std::ios_base::in)
+ {
+ auto curPos = m_stream.tellg();
+ //error on seek we may have read past the end already. Try resetting and seeking to the end first
+ if (curPos == pos_type(-1))
+ {
+ m_stream.clear();
+ m_stream.seekg(0, std::ios_base::end);
+ curPos = m_stream.tellg();
+ }
+
+ auto absPosition = ComputeAbsSeekPosition(off, dir, curPos);
+ size_t seekTo = static_cast<size_t>(absPosition);
+ size_t index = static_cast<size_t>(curPos);
+
+ if(index == seekTo)
+ {
+ return curPos;
+ }
+ else if (seekTo < index)
+ {
+ m_cipher.Reset();
+ m_stream.clear();
+ m_stream.seekg(0);
+ m_isFinalized = false;
+ index = 0;
+ }
+
+ CryptoBuffer cryptoBuffer;
+ while (m_cipher && index < seekTo && !m_isFinalized)
+ {
+ size_t max_read = std::min<size_t>(static_cast<size_t>(seekTo - index), m_bufferSize);
+
+ Aws::Utils::Array<char> buf(max_read);
+ size_t readSize(0);
+ if(m_stream)
+ {
+ m_stream.read(buf.GetUnderlyingData(), max_read);
+ readSize = static_cast<size_t>(m_stream.gcount());
+ }
+
+ if (readSize > 0)
+ {
+ if (m_cipherMode == CipherMode::Encrypt)
+ {
+ cryptoBuffer = m_cipher.EncryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize));
+ }
+ else
+ {
+ cryptoBuffer = m_cipher.DecryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize));
+ }
+ }
+ else
+ {
+ if (m_cipherMode == CipherMode::Encrypt)
+ {
+ cryptoBuffer = m_cipher.FinalizeEncryption();
+ }
+ else
+ {
+ cryptoBuffer = m_cipher.FinalizeDecryption();
+ }
+
+ m_isFinalized = true;
+ }
+
+ index += cryptoBuffer.GetLength();
+ }
+
+ if (cryptoBuffer.GetLength() && m_cipher)
+ {
+ CryptoBuffer putBackArea(m_putBack);
+
+ m_isBuf = CryptoBuffer({&putBackArea, &cryptoBuffer});
+ //in the very unlikely case that the cipher had less output than the source stream.
+ assert(seekTo <= index);
+ size_t newBufferPos = index > seekTo ? cryptoBuffer.GetLength() - (index - seekTo) : cryptoBuffer.GetLength();
+ char* baseBufPtr = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData());
+ setg(baseBufPtr, baseBufPtr + m_putBack + newBufferPos, baseBufPtr + m_isBuf.GetLength());
+
+ return pos_type(seekTo);
+ }
+ else if (seekTo == 0)
+ {
+ m_isBuf = CryptoBuffer(m_putBack);
+ char* end = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData() + m_isBuf.GetLength());
+ setg(end, end, end);
+ return pos_type(seekTo);
+ }
+ }
+
+ return pos_type(off_type(-1));
+ }
+
+ SymmetricCryptoBufSrc::pos_type SymmetricCryptoBufSrc::seekpos(pos_type pos, std::ios_base::openmode which)
+ {
+ return seekoff(pos, std::ios_base::beg, which);
+ }
+
+ SymmetricCryptoBufSrc::int_type SymmetricCryptoBufSrc::underflow()
+ {
+ if (!m_cipher || (m_isFinalized && gptr() >= egptr()))
+ {
+ return traits_type::eof();
+ }
+
+ if (gptr() < egptr())
+ {
+ return traits_type::to_int_type(*gptr());
+ }
+
+ char* baseBufPtr = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData());
+ CryptoBuffer putBackArea(m_putBack);
+
+ //eback is properly set after the first fill. So this guarantees we are on the second or later fill.
+ if (eback() == baseBufPtr)
+ {
+ //just fill in the last bit of the previous buffer into the put back area so that it has some data in it
+ memcpy(putBackArea.GetUnderlyingData(), egptr() - m_putBack, m_putBack);
+ }
+
+ CryptoBuffer newDataBuf;
+
+ while(!newDataBuf.GetLength() && !m_isFinalized)
+ {
+ Aws::Utils::Array<char> buf(m_bufferSize);
+ m_stream.read(buf.GetUnderlyingData(), m_bufferSize);
+ size_t readSize = static_cast<size_t>(m_stream.gcount());
+
+ if (readSize > 0)
+ {
+ if (m_cipherMode == CipherMode::Encrypt)
+ {
+ newDataBuf = m_cipher.EncryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize));
+ }
+ else
+ {
+ newDataBuf = m_cipher.DecryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize));
+ }
+ }
+ else
+ {
+ if (m_cipherMode == CipherMode::Encrypt)
+ {
+ newDataBuf = m_cipher.FinalizeEncryption();
+ }
+ else
+ {
+ newDataBuf = m_cipher.FinalizeDecryption();
+ }
+
+ m_isFinalized = true;
+ }
+ }
+
+
+ if(newDataBuf.GetLength() > 0)
+ {
+ m_isBuf = CryptoBuffer({&putBackArea, &newDataBuf});
+
+ baseBufPtr = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData());
+ setg(baseBufPtr, baseBufPtr + m_putBack, baseBufPtr + m_isBuf.GetLength());
+
+ return traits_type::to_int_type(*gptr());
+ }
+
+ return traits_type::eof();
+ }
+
+ SymmetricCryptoBufSrc::off_type SymmetricCryptoBufSrc::ComputeAbsSeekPosition(off_type pos, std::ios_base::seekdir dir, std::fpos<FPOS_TYPE> curPos)
+ {
+ switch(dir)
+ {
+ case std::ios_base::beg:
+ return pos;
+ case std::ios_base::cur:
+ return m_stream.tellg() + pos;
+ case std::ios_base::end:
+ {
+ off_type absPos = m_stream.seekg(0, std::ios_base::end).tellg() - pos;
+ m_stream.seekg(curPos);
+ return absPos;
+ }
+ default:
+ assert(0);
+ return off_type(-1);
+ }
+ }
+
+ void SymmetricCryptoBufSrc::FinalizeCipher()
+ {
+ if(m_cipher && !m_isFinalized)
+ {
+ if(m_cipherMode == CipherMode::Encrypt)
+ {
+ m_cipher.FinalizeEncryption();
+ }
+ else
+ {
+ m_cipher.FinalizeDecryption();
+ }
+ }
+ }
+
+ SymmetricCryptoBufSink::SymmetricCryptoBufSink(Aws::OStream& stream, SymmetricCipher& cipher, CipherMode cipherMode, size_t bufferSize, int16_t blockOffset)
+ :
+ m_osBuf(bufferSize), m_cipher(cipher), m_stream(stream), m_cipherMode(cipherMode), m_isFinalized(false), m_blockOffset(blockOffset)
+ {
+ assert(m_blockOffset < 16 && m_blockOffset >= 0);
+ char* outputBase = reinterpret_cast<char*>(m_osBuf.GetUnderlyingData());
+ setp(outputBase, outputBase + bufferSize - 1);
+ }
+
+ SymmetricCryptoBufSink::~SymmetricCryptoBufSink()
+ {
+ FinalizeCiphersAndFlushSink();
+ }
+
+ void SymmetricCryptoBufSink::FinalizeCiphersAndFlushSink()
+ {
+ if(m_cipher && !m_isFinalized)
+ {
+ writeOutput(true);
+ }
+ }
+
+ bool SymmetricCryptoBufSink::writeOutput(bool finalize)
+ {
+ if(!m_isFinalized)
+ {
+ CryptoBuffer cryptoBuf;
+ if (pptr() > pbase())
+ {
+ if (m_cipherMode == CipherMode::Encrypt)
+ {
+ cryptoBuf = m_cipher.EncryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(pbase()), pptr() - pbase()));
+ }
+ else
+ {
+ cryptoBuf = m_cipher.DecryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(pbase()), pptr() - pbase()));
+ }
+
+ pbump(-(static_cast<int>(pptr() - pbase())));
+ }
+ if(finalize)
+ {
+ CryptoBuffer finalBuffer;
+ if (m_cipherMode == CipherMode::Encrypt)
+ {
+ finalBuffer = m_cipher.FinalizeEncryption();
+ }
+ else
+ {
+ finalBuffer = m_cipher.FinalizeDecryption();
+ }
+ if(cryptoBuf.GetLength())
+ {
+ cryptoBuf = CryptoBuffer({&cryptoBuf, &finalBuffer});
+ }
+ else
+ {
+ cryptoBuf = std::move(finalBuffer);
+ }
+
+ m_isFinalized = true;
+ }
+
+ if (m_cipher)
+ {
+ if(cryptoBuf.GetLength())
+ {
+ //allow mid block decryption. We have to decrypt it, but we don't have to write it to the stream.
+ //the assumption here is that tellp() will always be 0 or >= 16 bytes. The block offset should only
+ //be the offset of the first block read.
+ size_t len = cryptoBuf.GetLength();
+ size_t blockOffset = m_stream.tellp() > m_blockOffset ? 0 : m_blockOffset;
+ if (len > blockOffset)
+ {
+ m_stream.write(reinterpret_cast<char*>(cryptoBuf.GetUnderlyingData() + blockOffset), len - blockOffset);
+ m_blockOffset = 0;
+ }
+ else
+ {
+ m_blockOffset -= static_cast<int16_t>(len);
+ }
+ }
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ SymmetricCryptoBufSink::int_type SymmetricCryptoBufSink::overflow(int_type ch)
+ {
+ if(m_cipher && m_stream)
+ {
+ if(ch != traits_type::eof())
+ {
+ *pptr() = (char)ch;
+ pbump(1);
+ }
+
+ if(writeOutput(ch == traits_type::eof()))
+ {
+ return ch;
+ }
+ }
+
+ return traits_type::eof();
+ }
+
+ int SymmetricCryptoBufSink::sync()
+ {
+ if(m_cipher && m_stream)
+ {
+ return writeOutput(false) ? 0 : -1;
+ }
+
+ return -1;
+ }
+ }
+ }
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoStream.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoStream.cpp
new file mode 100644
index 0000000000..2d645f7427
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoStream.cpp
@@ -0,0 +1,52 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+#include <aws/core/utils/crypto/CryptoStream.h>
+
+namespace Aws
+{
+ namespace Utils
+ {
+ namespace Crypto
+ {
+ static const char* CLASS_TAG = "Aws::Utils::Crypto::SymmetricCryptoStream";
+
+ SymmetricCryptoStream::SymmetricCryptoStream(Aws::IStream& src, CipherMode mode, SymmetricCipher& cipher, size_t bufSize) :
+ Aws::IOStream(m_cryptoBuf = Aws::New<SymmetricCryptoBufSrc>(CLASS_TAG, src, cipher, mode, bufSize)), m_hasOwnership(true)
+ {
+ }
+
+ SymmetricCryptoStream::SymmetricCryptoStream(Aws::OStream& sink, CipherMode mode, SymmetricCipher& cipher, size_t bufSize, int16_t blockOffset) :
+ Aws::IOStream(m_cryptoBuf = Aws::New<SymmetricCryptoBufSink>(CLASS_TAG, sink, cipher, mode, bufSize, blockOffset)), m_hasOwnership(true)
+ {
+ }
+
+ SymmetricCryptoStream::SymmetricCryptoStream(Aws::Utils::Crypto::SymmetricCryptoBufSrc& bufSrc) :
+ Aws::IOStream(&bufSrc), m_cryptoBuf(&bufSrc), m_hasOwnership(false)
+ {
+ }
+
+ SymmetricCryptoStream::SymmetricCryptoStream(Aws::Utils::Crypto::SymmetricCryptoBufSink& bufSink) :
+ Aws::IOStream(&bufSink), m_cryptoBuf(&bufSink), m_hasOwnership(false)
+ {
+ }
+
+ SymmetricCryptoStream::~SymmetricCryptoStream()
+ {
+ Finalize();
+
+ if(m_hasOwnership && m_cryptoBuf)
+ {
+ Aws::Delete(m_cryptoBuf);
+ }
+ }
+
+ void SymmetricCryptoStream::Finalize()
+ {
+ assert(m_cryptoBuf);
+ m_cryptoBuf->Finalize();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/EncryptionMaterials.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/EncryptionMaterials.cpp
new file mode 100644
index 0000000000..d000c86baa
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/EncryptionMaterials.cpp
@@ -0,0 +1,19 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+#include <aws/core/utils/crypto/EncryptionMaterials.h>
+
+namespace Aws
+{
+ namespace Utils
+ {
+ namespace Crypto
+ {
+ //this is here to force the linker to behave correctly since this is an interface that will need to cross the dll
+ //boundary.
+ EncryptionMaterials::~EncryptionMaterials()
+ {}
+ }
+ }
+} \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/KeyWrapAlgorithm.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/KeyWrapAlgorithm.cpp
new file mode 100644
index 0000000000..b9e098775c
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/KeyWrapAlgorithm.cpp
@@ -0,0 +1,68 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+#include <aws/core/utils/crypto/KeyWrapAlgorithm.h>
+#include <aws/core/utils/HashingUtils.h>
+#include <aws/core/utils/EnumParseOverflowContainer.h>
+#include <aws/core/Globals.h>
+
+using namespace Aws::Utils;
+
+namespace Aws
+{
+ namespace Utils
+ {
+ namespace Crypto
+ {
+ namespace KeyWrapAlgorithmMapper
+ {
+ static const int keyWrapAlgorithm_KMS_HASH = HashingUtils::HashString("kms");
+ static const int keyWrapAlgorithm_KMS_CONTEXT_HASH = HashingUtils::HashString("kms+context");
+ static const int keyWrapAlgorithm_KeyWrap_HASH = HashingUtils::HashString("AESWrap");
+ static const int keyWrapAlgorithm_AES_GCM_HASH = HashingUtils::HashString("AES/GCM");
+
+ KeyWrapAlgorithm GetKeyWrapAlgorithmForName(const Aws::String& name)
+ {
+ int hashcode = HashingUtils::HashString(name.c_str());
+ if (hashcode == keyWrapAlgorithm_KMS_HASH)
+ {
+ return KeyWrapAlgorithm::KMS;
+ }
+ else if (hashcode == keyWrapAlgorithm_KMS_CONTEXT_HASH)
+ {
+ return KeyWrapAlgorithm::KMS_CONTEXT;
+ }
+ else if (hashcode == keyWrapAlgorithm_KeyWrap_HASH)
+ {
+ return KeyWrapAlgorithm::AES_KEY_WRAP;
+ }
+ else if (hashcode == keyWrapAlgorithm_AES_GCM_HASH)
+ {
+ return KeyWrapAlgorithm::AES_GCM;
+ }
+ assert(0);
+ return KeyWrapAlgorithm::NONE;
+ }
+
+ Aws::String GetNameForKeyWrapAlgorithm(KeyWrapAlgorithm enumValue)
+ {
+ switch (enumValue)
+ {
+ case KeyWrapAlgorithm::KMS:
+ return "kms";
+ case KeyWrapAlgorithm::KMS_CONTEXT:
+ return "kms+context";
+ case KeyWrapAlgorithm::AES_KEY_WRAP:
+ return "AESWrap";
+ case KeyWrapAlgorithm::AES_GCM:
+ return "AES/GCM";
+ default:
+ assert(0);
+ }
+ return "";
+ }
+ }//namespace KeyWrapAlgorithmMapper
+ }//namespace Crypto
+ }//namespace Utils
+}//namespace Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/MD5.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/MD5.cpp
new file mode 100644
index 0000000000..bf14ace1ad
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/MD5.cpp
@@ -0,0 +1,31 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+
+#include <aws/core/utils/crypto/MD5.h>
+#include <aws/core/utils/Outcome.h>
+#include <aws/core/utils/crypto/Factories.h>
+
+using namespace Aws::Utils::Crypto;
+
+
+MD5::MD5() :
+ m_hashImpl(CreateMD5Implementation())
+{
+}
+
+MD5::~MD5()
+{
+}
+
+HashResult MD5::Calculate(const Aws::String& str)
+{
+ return m_hashImpl->Calculate(str);
+}
+
+HashResult MD5::Calculate(Aws::IStream& stream)
+{
+ return m_hashImpl->Calculate(stream);
+} \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256.cpp
new file mode 100644
index 0000000000..178df00d37
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256.cpp
@@ -0,0 +1,30 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+
+#include <aws/core/utils/crypto/Sha256.h>
+#include <aws/core/utils/Outcome.h>
+#include <aws/core/utils/crypto/Factories.h>
+
+using namespace Aws::Utils::Crypto;
+
+Sha256::Sha256() :
+ m_hashImpl(CreateSha256Implementation())
+{
+}
+
+Sha256::~Sha256()
+{
+}
+
+HashResult Sha256::Calculate(const Aws::String& str)
+{
+ return m_hashImpl->Calculate(str);
+}
+
+HashResult Sha256::Calculate(Aws::IStream& stream)
+{
+ return m_hashImpl->Calculate(stream);
+} \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256HMAC.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256HMAC.cpp
new file mode 100644
index 0000000000..ecc1f06529
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256HMAC.cpp
@@ -0,0 +1,34 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+
+#include <aws/core/utils/crypto/Sha256HMAC.h>
+#include <aws/core/utils/crypto/Factories.h>
+#include <aws/core/utils/Outcome.h>
+
+namespace Aws
+{
+namespace Utils
+{
+namespace Crypto
+{
+
+Sha256HMAC::Sha256HMAC() :
+ m_hmacImpl(CreateSha256HMACImplementation())
+{
+}
+
+Sha256HMAC::~Sha256HMAC()
+{
+}
+
+HashResult Sha256HMAC::Calculate(const Aws::Utils::ByteBuffer& toSign, const Aws::Utils::ByteBuffer& secret)
+{
+ return m_hmacImpl->Calculate(toSign, secret);
+}
+
+} // namespace Crypto
+} // namespace Utils
+} // namespace Aws \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp
new file mode 100644
index 0000000000..bff0382241
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp
@@ -0,0 +1,895 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+
+#include <aws/core/utils/crypto/Factories.h>
+#include <aws/core/utils/crypto/Hash.h>
+#include <aws/core/utils/crypto/HMAC.h>
+
+#if ENABLE_BCRYPT_ENCRYPTION
+ #error #include <aws/core/utils/crypto/bcrypt/CryptoImpl.h>
+#elif ENABLE_OPENSSL_ENCRYPTION
+ #include <aws/core/utils/crypto/openssl/CryptoImpl.h>
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ #error #include <aws/core/utils/crypto/commoncrypto/CryptoImpl.h>
+ #include <aws/core/utils/logging/LogMacros.h>
+#else
+ // if you don't have any encryption you still need to pull in the interface definitions
+ #include <aws/core/utils/crypto/Hash.h>
+ #include <aws/core/utils/crypto/HMAC.h>
+ #include <aws/core/utils/crypto/Cipher.h>
+ #include <aws/core/utils/crypto/SecureRandom.h>
+ #define NO_ENCRYPTION
+#endif
+
+using namespace Aws::Utils;
+using namespace Aws::Utils::Crypto;
+
+static const char *s_allocationTag = "CryptoFactory";
+
+static std::shared_ptr<HashFactory>& GetMD5Factory()
+{
+ static std::shared_ptr<HashFactory> s_MD5Factory(nullptr);
+ return s_MD5Factory;
+}
+
+static std::shared_ptr<HashFactory>& GetSha256Factory()
+{
+ static std::shared_ptr<HashFactory> s_Sha256Factory(nullptr);
+ return s_Sha256Factory;
+}
+
+static std::shared_ptr<HMACFactory>& GetSha256HMACFactory()
+{
+ static std::shared_ptr<HMACFactory> s_Sha256HMACFactory(nullptr);
+ return s_Sha256HMACFactory;
+}
+
+static std::shared_ptr<SymmetricCipherFactory>& GetAES_CBCFactory()
+{
+ static std::shared_ptr<SymmetricCipherFactory> s_AES_CBCFactory(nullptr);
+ return s_AES_CBCFactory;
+}
+
+static std::shared_ptr<SymmetricCipherFactory>& GetAES_CTRFactory()
+{
+ static std::shared_ptr<SymmetricCipherFactory> s_AES_CTRFactory(nullptr);
+ return s_AES_CTRFactory;
+}
+
+static std::shared_ptr<SymmetricCipherFactory>& GetAES_GCMFactory()
+{
+ static std::shared_ptr<SymmetricCipherFactory> s_AES_GCMFactory(nullptr);
+ return s_AES_GCMFactory;
+}
+
+static std::shared_ptr<SymmetricCipherFactory>& GetAES_KeyWrapFactory()
+{
+ static std::shared_ptr<SymmetricCipherFactory> s_AES_KeyWrapFactory(nullptr);
+ return s_AES_KeyWrapFactory;
+}
+
+static std::shared_ptr<SecureRandomFactory>& GetSecureRandomFactory()
+{
+ static std::shared_ptr<SecureRandomFactory> s_SecureRandomFactory(nullptr);
+ return s_SecureRandomFactory;
+}
+
+static std::shared_ptr<SecureRandomBytes>& GetSecureRandom()
+{
+ static std::shared_ptr<SecureRandomBytes> s_SecureRandom(nullptr);
+ return s_SecureRandom;
+}
+
+static bool s_InitCleanupOpenSSLFlag(false);
+
+class DefaultMD5Factory : public HashFactory
+{
+public:
+ std::shared_ptr<Hash> CreateImplementation() const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<MD5BcryptImpl>(s_allocationTag);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<MD5OpenSSLImpl>(s_allocationTag);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<MD5CommonCryptoImpl>(s_allocationTag);
+#else
+ return nullptr;
+#endif
+ }
+
+ /**
+ * Opportunity to make any static initialization calls you need to make.
+ * Will only be called once.
+ */
+ void InitStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state);
+ }
+#endif
+ }
+
+ /**
+ * Opportunity to make any static cleanup calls you need to make.
+ * will only be called at the end of the application.
+ */
+ void CleanupStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state);
+ }
+#endif
+ }
+};
+
+class DefaultSHA256Factory : public HashFactory
+{
+public:
+ std::shared_ptr<Hash> CreateImplementation() const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<Sha256BcryptImpl>(s_allocationTag);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<Sha256OpenSSLImpl>(s_allocationTag);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<Sha256CommonCryptoImpl>(s_allocationTag);
+#else
+ return nullptr;
+#endif
+ }
+
+ /**
+ * Opportunity to make any static initialization calls you need to make.
+ * Will only be called once.
+ */
+ void InitStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state);
+ }
+#endif
+ }
+
+ /**
+ * Opportunity to make any static cleanup calls you need to make.
+ * will only be called at the end of the application.
+ */
+ void CleanupStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state);
+ }
+#endif
+ }
+};
+
+class DefaultSHA256HmacFactory : public HMACFactory
+{
+public:
+ std::shared_ptr<Aws::Utils::Crypto::HMAC> CreateImplementation() const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<Sha256HMACBcryptImpl>(s_allocationTag);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<Sha256HMACOpenSSLImpl>(s_allocationTag);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<Sha256HMACCommonCryptoImpl>(s_allocationTag);
+#else
+ return nullptr;
+#endif
+ }
+
+ /**
+ * Opportunity to make any static initialization calls you need to make.
+ * Will only be called once.
+ */
+ void InitStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state);
+ }
+#endif
+ }
+
+ /**
+ * Opportunity to make any static cleanup calls you need to make.
+ * will only be called at the end of the application.
+ */
+ void CleanupStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state);
+ }
+#endif
+ }
+};
+
+
+class DefaultAES_CBCFactory : public SymmetricCipherFactory
+{
+public:
+ std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key) const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<AES_CBC_Cipher_BCrypt>(s_allocationTag, key);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<AES_CBC_Cipher_OpenSSL>(s_allocationTag, key);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<AES_CBC_Cipher_CommonCrypto>(s_allocationTag, key);
+#else
+ AWS_UNREFERENCED_PARAM(key);
+ return nullptr;
+#endif
+ }
+ /**
+ * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details.
+ */
+ std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key, const CryptoBuffer& iv, const CryptoBuffer&, const CryptoBuffer&) const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<AES_CBC_Cipher_BCrypt>(s_allocationTag, key, iv);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<AES_CBC_Cipher_OpenSSL>(s_allocationTag, key, iv);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<AES_CBC_Cipher_CommonCrypto>(s_allocationTag, key, iv);
+#else
+ AWS_UNREFERENCED_PARAM(key);
+ AWS_UNREFERENCED_PARAM(iv);
+
+ return nullptr;
+#endif
+ }
+ /**
+ * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details.
+ */
+ std::shared_ptr<SymmetricCipher> CreateImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&&, CryptoBuffer&&) const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<AES_CBC_Cipher_BCrypt>(s_allocationTag, key, iv);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<AES_CBC_Cipher_OpenSSL>(s_allocationTag, key, iv);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<AES_CBC_Cipher_CommonCrypto>(s_allocationTag, key, iv);
+#else
+ AWS_UNREFERENCED_PARAM(key);
+ AWS_UNREFERENCED_PARAM(iv);
+
+ return nullptr;
+#endif
+ }
+
+ /**
+ * Opportunity to make any static initialization calls you need to make.
+ * Will only be called once.
+ */
+ void InitStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state);
+ }
+#endif
+ }
+
+ /**
+ * Opportunity to make any static cleanup calls you need to make.
+ * will only be called at the end of the application.
+ */
+ void CleanupStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state);
+ }
+#endif
+ }
+};
+
+class DefaultAES_CTRFactory : public SymmetricCipherFactory
+{
+public:
+ std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key) const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<AES_CTR_Cipher_BCrypt>(s_allocationTag, key);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<AES_CTR_Cipher_OpenSSL>(s_allocationTag, key);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<AES_CTR_Cipher_CommonCrypto>(s_allocationTag, key);
+#else
+ AWS_UNREFERENCED_PARAM(key);
+ return nullptr;
+#endif
+ }
+ /**
+ * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details.
+ */
+ std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key, const CryptoBuffer& iv, const CryptoBuffer&, const CryptoBuffer&) const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<AES_CTR_Cipher_BCrypt>(s_allocationTag, key, iv);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<AES_CTR_Cipher_OpenSSL>(s_allocationTag, key, iv);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<AES_CTR_Cipher_CommonCrypto>(s_allocationTag, key, iv);
+#else
+ AWS_UNREFERENCED_PARAM(key);
+ AWS_UNREFERENCED_PARAM(iv);
+
+ return nullptr;
+#endif
+ }
+ /**
+ * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details.
+ */
+ std::shared_ptr<SymmetricCipher> CreateImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&&, CryptoBuffer&&) const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<AES_CTR_Cipher_BCrypt>(s_allocationTag, key, iv);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<AES_CTR_Cipher_OpenSSL>(s_allocationTag, key, iv);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<AES_CTR_Cipher_CommonCrypto>(s_allocationTag, key, iv);
+#else
+ AWS_UNREFERENCED_PARAM(key);
+ AWS_UNREFERENCED_PARAM(iv);
+
+ return nullptr;
+#endif
+ }
+
+ /**
+ * Opportunity to make any static initialization calls you need to make.
+ * Will only be called once.
+ */
+ void InitStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state);
+ }
+#endif
+ }
+
+ /**
+ * Opportunity to make any static cleanup calls you need to make.
+ * will only be called at the end of the application.
+ */
+ void CleanupStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state);
+ }
+#endif
+ }
+};
+
+class DefaultAES_GCMFactory : public SymmetricCipherFactory
+{
+public:
+ std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key) const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<AES_GCM_Cipher_BCrypt>(s_allocationTag, key);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<AES_GCM_Cipher_OpenSSL>(s_allocationTag, key);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<AES_GCM_Cipher_CommonCrypto>(s_allocationTag, key);
+#else
+ AWS_UNREFERENCED_PARAM(key);
+
+ return nullptr;
+#endif
+ }
+
+ std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key, const CryptoBuffer* aad) const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<AES_GCM_Cipher_BCrypt>(s_allocationTag, key, aad);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<AES_GCM_Cipher_OpenSSL>(s_allocationTag, key, aad);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<AES_GCM_Cipher_CommonCrypto>(s_allocationTag, key, aad);
+#else
+ AWS_UNREFERENCED_PARAM(key);
+ AWS_UNREFERENCED_PARAM(aad);
+ return nullptr;
+#endif
+ }
+
+ /**
+ * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details.
+ */
+ std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key, const CryptoBuffer& iv, const CryptoBuffer& tag, const CryptoBuffer& aad) const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<AES_GCM_Cipher_BCrypt>(s_allocationTag, key, iv, tag, aad);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<AES_GCM_Cipher_OpenSSL>(s_allocationTag, key, iv, tag, aad);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<AES_GCM_Cipher_CommonCrypto>(s_allocationTag, key, iv, tag, aad);
+#else
+ AWS_UNREFERENCED_PARAM(key);
+ AWS_UNREFERENCED_PARAM(iv);
+ AWS_UNREFERENCED_PARAM(tag);
+ AWS_UNREFERENCED_PARAM(aad);
+ return nullptr;
+#endif
+ }
+ /**
+ * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details.
+ */
+ std::shared_ptr<SymmetricCipher> CreateImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&& tag, CryptoBuffer&& aad) const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<AES_GCM_Cipher_BCrypt>(s_allocationTag, std::move(key), std::move(iv), std::move(tag), std::move(aad));
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<AES_GCM_Cipher_OpenSSL>(s_allocationTag, std::move(key), std::move(iv), std::move(tag), std::move(aad));
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<AES_GCM_Cipher_CommonCrypto>(s_allocationTag, std::move(key), std::move(iv), std::move(tag), std::move(aad));
+#else
+ AWS_UNREFERENCED_PARAM(key);
+ AWS_UNREFERENCED_PARAM(iv);
+ AWS_UNREFERENCED_PARAM(tag);
+ AWS_UNREFERENCED_PARAM(aad);
+ return nullptr;
+#endif
+ }
+
+ /**
+ * Opportunity to make any static initialization calls you need to make.
+ * Will only be called once.
+ */
+ void InitStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state);
+ }
+#endif
+ }
+
+ /**
+ * Opportunity to make any static cleanup calls you need to make.
+ * will only be called at the end of the application.
+ */
+ void CleanupStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state);
+ }
+#endif
+ }
+};
+
+class DefaultAES_KeyWrapFactory : public SymmetricCipherFactory
+{
+public:
+ std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key) const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<AES_KeyWrap_Cipher_BCrypt>(s_allocationTag, key);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<AES_KeyWrap_Cipher_OpenSSL>(s_allocationTag, key);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<AES_KeyWrap_Cipher_CommonCrypto>(s_allocationTag, key);
+#else
+ AWS_UNREFERENCED_PARAM(key);
+ return nullptr;
+#endif
+ }
+ /**
+ * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details.
+ */
+ std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key, const CryptoBuffer& iv, const CryptoBuffer& tag, const CryptoBuffer&) const override
+ {
+ AWS_UNREFERENCED_PARAM(key);
+ AWS_UNREFERENCED_PARAM(iv);
+ AWS_UNREFERENCED_PARAM(tag);
+ return nullptr;
+ }
+ /**
+ * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details.
+ */
+ std::shared_ptr<SymmetricCipher> CreateImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&& tag, CryptoBuffer&&) const override
+ {
+ AWS_UNREFERENCED_PARAM(key);
+ AWS_UNREFERENCED_PARAM(iv);
+ AWS_UNREFERENCED_PARAM(tag);
+ return nullptr;
+ }
+
+ /**
+ * Opportunity to make any static initialization calls you need to make.
+ * Will only be called once.
+ */
+ void InitStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if (s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state);
+ }
+#endif
+ }
+
+ /**
+ * Opportunity to make any static cleanup calls you need to make.
+ * will only be called at the end of the application.
+ */
+ void CleanupStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if (s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state);
+ }
+#endif
+ }
+};
+
+class DefaultSecureRandFactory : public SecureRandomFactory
+{
+ /**
+ * Factory method. Returns SecureRandom implementation.
+ */
+ std::shared_ptr<SecureRandomBytes> CreateImplementation() const override
+ {
+#if ENABLE_BCRYPT_ENCRYPTION
+ return Aws::MakeShared<SecureRandomBytes_BCrypt>(s_allocationTag);
+#elif ENABLE_OPENSSL_ENCRYPTION
+ return Aws::MakeShared<SecureRandomBytes_OpenSSLImpl>(s_allocationTag);
+#elif ENABLE_COMMONCRYPTO_ENCRYPTION
+ return Aws::MakeShared<SecureRandomBytes_CommonCrypto>(s_allocationTag);
+#else
+ return nullptr;
+#endif
+ }
+
+ /**
+ * Opportunity to make any static initialization calls you need to make.
+ * Will only be called once.
+ */
+ void InitStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state);
+ }
+#endif
+ }
+
+ /**
+ * Opportunity to make any static cleanup calls you need to make.
+ * will only be called at the end of the application.
+ */
+ void CleanupStaticState() override
+ {
+#if ENABLE_OPENSSL_ENCRYPTION
+ if(s_InitCleanupOpenSSLFlag)
+ {
+ OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state);
+ }
+#endif
+ }
+};
+
+void Aws::Utils::Crypto::SetInitCleanupOpenSSLFlag(bool initCleanupFlag)
+{
+ s_InitCleanupOpenSSLFlag = initCleanupFlag;
+}
+
+void Aws::Utils::Crypto::InitCrypto()
+{
+ if(GetMD5Factory())
+ {
+ GetMD5Factory()->InitStaticState();
+ }
+ else
+ {
+ GetMD5Factory() = Aws::MakeShared<DefaultMD5Factory>(s_allocationTag);
+ GetMD5Factory()->InitStaticState();
+ }
+
+ if(GetSha256Factory())
+ {
+ GetSha256Factory()->InitStaticState();
+ }
+ else
+ {
+ GetSha256Factory() = Aws::MakeShared<DefaultSHA256Factory>(s_allocationTag);
+ GetSha256Factory()->InitStaticState();
+ }
+
+ if(GetSha256HMACFactory())
+ {
+ GetSha256HMACFactory()->InitStaticState();
+ }
+ else
+ {
+ GetSha256HMACFactory() = Aws::MakeShared<DefaultSHA256HmacFactory>(s_allocationTag);
+ GetSha256HMACFactory()->InitStaticState();
+ }
+
+ if(GetAES_CBCFactory())
+ {
+ GetAES_CBCFactory()->InitStaticState();
+ }
+ else
+ {
+ GetAES_CBCFactory() = Aws::MakeShared<DefaultAES_CBCFactory>(s_allocationTag);
+ GetAES_CBCFactory()->InitStaticState();
+ }
+
+ if(GetAES_CTRFactory())
+ {
+ GetAES_CTRFactory()->InitStaticState();
+ }
+ else
+ {
+ GetAES_CTRFactory() = Aws::MakeShared<DefaultAES_CTRFactory>(s_allocationTag);
+ GetAES_CTRFactory()->InitStaticState();
+ }
+
+ if(GetAES_GCMFactory())
+ {
+ GetAES_GCMFactory()->InitStaticState();
+ }
+ else
+ {
+ GetAES_GCMFactory() = Aws::MakeShared<DefaultAES_GCMFactory>(s_allocationTag);
+ GetAES_GCMFactory()->InitStaticState();
+ }
+
+ if (!GetAES_KeyWrapFactory())
+ {
+ GetAES_KeyWrapFactory() = Aws::MakeShared<DefaultAES_KeyWrapFactory>(s_allocationTag);
+ }
+ GetAES_KeyWrapFactory()->InitStaticState();
+
+ if(GetSecureRandomFactory())
+ {
+ GetSecureRandomFactory()->InitStaticState();
+ }
+ else
+ {
+ GetSecureRandomFactory() = Aws::MakeShared<DefaultSecureRandFactory>(s_allocationTag);
+ GetSecureRandomFactory()->InitStaticState();
+ }
+
+ GetSecureRandom() = GetSecureRandomFactory()->CreateImplementation();
+}
+
+void Aws::Utils::Crypto::CleanupCrypto()
+{
+ if(GetMD5Factory())
+ {
+ GetMD5Factory()->CleanupStaticState();
+ GetMD5Factory() = nullptr;
+ }
+
+ if(GetSha256Factory())
+ {
+ GetSha256Factory()->CleanupStaticState();
+ GetSha256Factory() = nullptr;
+ }
+
+ if(GetSha256HMACFactory())
+ {
+ GetSha256HMACFactory()->CleanupStaticState();
+ GetSha256HMACFactory() = nullptr;
+ }
+
+ if(GetAES_CBCFactory())
+ {
+ GetAES_CBCFactory()->CleanupStaticState();
+ GetAES_CBCFactory() = nullptr;
+ }
+
+ if(GetAES_CTRFactory())
+ {
+ GetAES_CTRFactory()->CleanupStaticState();
+ GetAES_CTRFactory() = nullptr;
+ }
+
+ if(GetAES_GCMFactory())
+ {
+ GetAES_GCMFactory()->CleanupStaticState();
+ GetAES_GCMFactory() = nullptr;
+ }
+
+ if(GetAES_KeyWrapFactory())
+ {
+ GetAES_KeyWrapFactory()->CleanupStaticState();
+ GetAES_KeyWrapFactory() = nullptr;
+ }
+
+ if(GetSecureRandomFactory())
+ {
+ GetSecureRandom() = nullptr;
+ GetSecureRandomFactory()->CleanupStaticState();
+ GetSecureRandomFactory() = nullptr;
+ }
+}
+
+void Aws::Utils::Crypto::SetMD5Factory(const std::shared_ptr<HashFactory>& factory)
+{
+ GetMD5Factory() = factory;
+}
+
+void Aws::Utils::Crypto::SetSha256Factory(const std::shared_ptr<HashFactory>& factory)
+{
+ GetSha256Factory() = factory;
+}
+
+void Aws::Utils::Crypto::SetSha256HMACFactory(const std::shared_ptr<HMACFactory>& factory)
+{
+ GetSha256HMACFactory() = factory;
+}
+
+void Aws::Utils::Crypto::SetAES_CBCFactory(const std::shared_ptr<SymmetricCipherFactory>& factory)
+{
+ GetAES_CBCFactory() = factory;
+}
+
+void Aws::Utils::Crypto::SetAES_CTRFactory(const std::shared_ptr<SymmetricCipherFactory>& factory)
+{
+ GetAES_CTRFactory() = factory;
+}
+
+void Aws::Utils::Crypto::SetAES_GCMFactory(const std::shared_ptr<SymmetricCipherFactory>& factory)
+{
+ GetAES_GCMFactory() = factory;
+}
+
+void Aws::Utils::Crypto::SetAES_KeyWrapFactory(const std::shared_ptr<SymmetricCipherFactory>& factory)
+{
+ GetAES_KeyWrapFactory() = factory;
+}
+
+void Aws::Utils::Crypto::SetSecureRandomFactory(const std::shared_ptr<SecureRandomFactory>& factory)
+{
+ GetSecureRandomFactory() = factory;
+}
+
+std::shared_ptr<Hash> Aws::Utils::Crypto::CreateMD5Implementation()
+{
+ return GetMD5Factory()->CreateImplementation();
+}
+
+std::shared_ptr<Hash> Aws::Utils::Crypto::CreateSha256Implementation()
+{
+ return GetSha256Factory()->CreateImplementation();
+}
+
+std::shared_ptr<Aws::Utils::Crypto::HMAC> Aws::Utils::Crypto::CreateSha256HMACImplementation()
+{
+ return GetSha256HMACFactory()->CreateImplementation();
+}
+
+#ifdef _WIN32
+#pragma warning( push )
+#pragma warning( disable : 4702 )
+#endif
+
+std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CBCImplementation(const CryptoBuffer& key)
+{
+#ifdef NO_SYMMETRIC_ENCRYPTION
+ return nullptr;
+#endif
+ return GetAES_CBCFactory()->CreateImplementation(key);
+}
+
+std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CBCImplementation(const CryptoBuffer& key, const CryptoBuffer& iv)
+{
+#ifdef NO_SYMMETRIC_ENCRYPTION
+ return nullptr;
+#endif
+ return GetAES_CBCFactory()->CreateImplementation(key, iv);
+}
+
+std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CBCImplementation(CryptoBuffer&& key, CryptoBuffer&& iv)
+{
+#ifdef NO_SYMMETRIC_ENCRYPTION
+ return nullptr;
+#endif
+ return GetAES_CBCFactory()->CreateImplementation(std::move(key), std::move(iv));
+}
+
+std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CTRImplementation(const CryptoBuffer& key)
+{
+#ifdef NO_SYMMETRIC_ENCRYPTION
+ return nullptr;
+#endif
+ return GetAES_CTRFactory()->CreateImplementation(key);
+}
+
+std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CTRImplementation(const CryptoBuffer& key, const CryptoBuffer& iv)
+{
+#ifdef NO_SYMMETRIC_ENCRYPTION
+ return nullptr;
+#endif
+ return GetAES_CTRFactory()->CreateImplementation(key, iv);
+}
+
+std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CTRImplementation(CryptoBuffer&& key, CryptoBuffer&& iv)
+{
+#ifdef NO_SYMMETRIC_ENCRYPTION
+ return nullptr;
+#endif
+ return GetAES_CTRFactory()->CreateImplementation(std::move(key), std::move(iv));
+}
+
+std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_GCMImplementation(const CryptoBuffer& key)
+{
+#ifdef NO_SYMMETRIC_ENCRYPTION
+ return nullptr;
+#endif
+ return GetAES_GCMFactory()->CreateImplementation(key);
+}
+
+std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_GCMImplementation(const CryptoBuffer& key, const CryptoBuffer* aad)
+{
+#ifdef NO_SYMMETRIC_ENCRYPTION
+ return nullptr;
+#endif
+ return GetAES_GCMFactory()->CreateImplementation(key, aad);
+}
+
+std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_GCMImplementation(const CryptoBuffer& key, const CryptoBuffer& iv, const CryptoBuffer& tag, const CryptoBuffer& aad)
+{
+#ifdef NO_SYMMETRIC_ENCRYPTION
+ return nullptr;
+#endif
+ return GetAES_GCMFactory()->CreateImplementation(key, iv, tag, aad);
+}
+
+std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_GCMImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&& tag, CryptoBuffer&& aad)
+{
+#ifdef NO_SYMMETRIC_ENCRYPTION
+ return nullptr;
+#endif
+ return GetAES_GCMFactory()->CreateImplementation(std::move(key), std::move(iv), std::move(tag), std::move(aad));
+}
+
+std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_KeyWrapImplementation(const CryptoBuffer& key)
+{
+#ifdef NO_SYMMETRIC_ENCRYPTION
+ return nullptr;
+#endif
+ return GetAES_KeyWrapFactory()->CreateImplementation(key);
+}
+
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+
+std::shared_ptr<SecureRandomBytes> Aws::Utils::Crypto::CreateSecureRandomBytesImplementation()
+{
+ return GetSecureRandom();
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp
new file mode 100644
index 0000000000..911838864b
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp
@@ -0,0 +1,987 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <cstring>
+
+#include <aws/core/utils/memory/AWSMemory.h>
+#include <aws/core/utils/crypto/openssl/CryptoImpl.h>
+#include <aws/core/utils/Outcome.h>
+#include <openssl/md5.h>
+
+#ifdef OPENSSL_IS_BORINGSSL
+#ifdef _MSC_VER
+AWS_SUPPRESS_WARNING_PUSH(4201)
+#else
+AWS_SUPPRESS_WARNING_PUSH("-Wpedantic")
+#endif
+#endif
+
+#include <openssl/sha.h>
+
+#ifdef OPENSSL_IS_BORINGSSL
+AWS_SUPPRESS_WARNING_POP
+#endif
+
+#include <openssl/err.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <thread>
+
+using namespace Aws::Utils;
+using namespace Aws::Utils::Crypto;
+
+namespace Aws
+{
+ namespace Utils
+ {
+ namespace Crypto
+ {
+ namespace OpenSSL
+ {
+/**
+ * openssl with OPENSSL_VERSION_NUMBER < 0x10100003L made data type details unavailable
+ * libressl use openssl with data type details available, but mandatorily set
+ * OPENSSL_VERSION_NUMBER = 0x20000000L, insane!
+ * https://github.com/aws/aws-sdk-cpp/pull/507/commits/2c99f1fe0c4b4683280caeb161538d4724d6a179
+ */
+#if defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER == 0x20000000L)
+#undef OPENSSL_VERSION_NUMBER
+#define OPENSSL_VERSION_NUMBER 0x1000107fL
+#endif
+#define OPENSSL_VERSION_LESS_1_1 (OPENSSL_VERSION_NUMBER < 0x10100003L)
+
+#if OPENSSL_VERSION_LESS_1_1
+ static const char* OPENSSL_INTERNALS_TAG = "OpenSSLCallbackState";
+ static std::mutex* locks(nullptr);
+#endif
+
+ GetTheLights getTheLights;
+
+ void init_static_state()
+ {
+#if OPENSSL_VERSION_LESS_1_1 || defined(OPENSSL_IS_BORINGSSL)
+ ERR_load_crypto_strings();
+#else
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS /*options*/ ,NULL /* OpenSSL init settings*/ );
+#endif
+#if !defined(OPENSSL_IS_BORINGSSL)
+ OPENSSL_add_all_algorithms_noconf();
+#endif
+#if OPENSSL_VERSION_LESS_1_1
+ if (!CRYPTO_get_locking_callback())
+ {
+ locks = Aws::NewArray<std::mutex>(static_cast<size_t>(CRYPTO_num_locks()),
+ OPENSSL_INTERNALS_TAG);
+ CRYPTO_set_locking_callback(&locking_fn);
+ }
+
+ if (!CRYPTO_get_id_callback())
+ {
+ CRYPTO_set_id_callback(&id_fn);
+ }
+#endif
+ RAND_poll();
+ }
+
+ void cleanup_static_state()
+ {
+#if OPENSSL_VERSION_LESS_1_1
+ if (CRYPTO_get_locking_callback() == &locking_fn)
+ {
+ CRYPTO_set_locking_callback(nullptr);
+ assert(locks);
+ Aws::DeleteArray(locks);
+ locks = nullptr;
+ }
+
+ if (CRYPTO_get_id_callback() == &id_fn)
+ {
+ CRYPTO_set_id_callback(nullptr);
+ }
+#endif
+ }
+
+#if OPENSSL_VERSION_LESS_1_1
+ void locking_fn(int mode, int n, const char*, int)
+ {
+ if (mode & CRYPTO_LOCK)
+ {
+ locks[n].lock();
+ }
+ else
+ {
+ locks[n].unlock();
+ }
+ }
+
+ unsigned long id_fn()
+ {
+ return static_cast<unsigned long>(std::hash<std::thread::id>()(std::this_thread::get_id()));
+ }
+#endif
+ }
+
+ static const char* OPENSSL_LOG_TAG = "OpenSSLCipher";
+
+ void SecureRandomBytes_OpenSSLImpl::GetBytes(unsigned char* buffer, size_t bufferSize)
+ {
+ if (!bufferSize)
+ {
+ return;
+ }
+
+ if (!buffer)
+ {
+ AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Secure Random Bytes generator can't generate: " << bufferSize << " bytes with nullptr buffer.");
+ assert(buffer);
+ return;
+ }
+
+ int success = RAND_bytes(buffer, static_cast<int>(bufferSize));
+ if (success != 1)
+ {
+ m_failure = true;
+ }
+ }
+
+ class OpensslCtxRAIIGuard
+ {
+ public:
+ OpensslCtxRAIIGuard()
+ {
+ m_ctx = EVP_MD_CTX_create();
+ assert(m_ctx != nullptr);
+ }
+
+ ~OpensslCtxRAIIGuard()
+ {
+ EVP_MD_CTX_destroy(m_ctx);
+ m_ctx = nullptr;
+ }
+
+ EVP_MD_CTX* getResource()
+ {
+ return m_ctx;
+ }
+ private:
+ EVP_MD_CTX *m_ctx;
+ };
+
+ HashResult MD5OpenSSLImpl::Calculate(const Aws::String& str)
+ {
+ OpensslCtxRAIIGuard guard;
+ auto ctx = guard.getResource();
+#if !defined(OPENSSL_IS_BORINGSSL)
+ EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+#endif
+ EVP_DigestInit_ex(ctx, EVP_md5(), nullptr);
+ EVP_DigestUpdate(ctx, str.c_str(), str.size());
+
+ ByteBuffer hash(EVP_MD_size(EVP_md5()));
+ EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr);
+
+ return HashResult(std::move(hash));
+ }
+
+ HashResult MD5OpenSSLImpl::Calculate(Aws::IStream& stream)
+ {
+ OpensslCtxRAIIGuard guard;
+ auto ctx = guard.getResource();
+#if !defined(OPENSSL_IS_BORINGSSL)
+ EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+#endif
+ EVP_DigestInit_ex(ctx, EVP_md5(), nullptr);
+
+ auto currentPos = stream.tellg();
+ if (currentPos == -1)
+ {
+ currentPos = 0;
+ stream.clear();
+ }
+ stream.seekg(0, stream.beg);
+
+ char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE];
+ while (stream.good())
+ {
+ stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE);
+ auto bytesRead = stream.gcount();
+
+ if (bytesRead > 0)
+ {
+ EVP_DigestUpdate(ctx, streamBuffer, static_cast<size_t>(bytesRead));
+ }
+ }
+
+ stream.clear();
+ stream.seekg(currentPos, stream.beg);
+
+ ByteBuffer hash(EVP_MD_size(EVP_md5()));
+ EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr);
+
+ return HashResult(std::move(hash));
+ }
+
+ HashResult Sha256OpenSSLImpl::Calculate(const Aws::String& str)
+ {
+ OpensslCtxRAIIGuard guard;
+ auto ctx = guard.getResource();
+ EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr);
+ EVP_DigestUpdate(ctx, str.c_str(), str.size());
+
+ ByteBuffer hash(EVP_MD_size(EVP_sha256()));
+ EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr);
+
+ return HashResult(std::move(hash));
+ }
+
+ HashResult Sha256OpenSSLImpl::Calculate(Aws::IStream& stream)
+ {
+ OpensslCtxRAIIGuard guard;
+ auto ctx = guard.getResource();
+
+ EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr);
+
+ auto currentPos = stream.tellg();
+ if (currentPos == -1)
+ {
+ currentPos = 0;
+ stream.clear();
+ }
+
+ stream.seekg(0, stream.beg);
+
+ char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE];
+ while (stream.good())
+ {
+ stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE);
+ auto bytesRead = stream.gcount();
+
+ if (bytesRead > 0)
+ {
+ EVP_DigestUpdate(ctx, streamBuffer, static_cast<size_t>(bytesRead));
+ }
+ }
+
+ stream.clear();
+ stream.seekg(currentPos, stream.beg);
+
+ ByteBuffer hash(EVP_MD_size(EVP_sha256()));
+ EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr);
+
+ return HashResult(std::move(hash));
+ }
+
+ class HMACRAIIGuard {
+ public:
+ HMACRAIIGuard() {
+#if OPENSSL_VERSION_LESS_1_1
+ m_ctx = Aws::New<HMAC_CTX>("AllocSha256HAMCOpenSSLContext");
+#else
+ m_ctx = HMAC_CTX_new();
+#endif
+ assert(m_ctx != nullptr);
+ }
+
+ ~HMACRAIIGuard() {
+#if OPENSSL_VERSION_LESS_1_1
+ Aws::Delete<HMAC_CTX>(m_ctx);
+#else
+ HMAC_CTX_free(m_ctx);
+#endif
+ m_ctx = nullptr;
+ }
+
+ HMAC_CTX* getResource() {
+ return m_ctx;
+ }
+ private:
+ HMAC_CTX *m_ctx;
+ };
+
+ HashResult Sha256HMACOpenSSLImpl::Calculate(const ByteBuffer& toSign, const ByteBuffer& secret)
+ {
+ unsigned int length = SHA256_DIGEST_LENGTH;
+ ByteBuffer digest(length);
+ memset(digest.GetUnderlyingData(), 0, length);
+
+ HMACRAIIGuard guard;
+ HMAC_CTX* m_ctx = guard.getResource();
+
+#if OPENSSL_VERSION_LESS_1_1
+ HMAC_CTX_init(m_ctx);
+#endif
+
+ HMAC_Init_ex(m_ctx, secret.GetUnderlyingData(), static_cast<int>(secret.GetLength()), EVP_sha256(),
+ NULL);
+ HMAC_Update(m_ctx, toSign.GetUnderlyingData(), toSign.GetLength());
+ HMAC_Final(m_ctx, digest.GetUnderlyingData(), &length);
+
+#if OPENSSL_VERSION_LESS_1_1
+ HMAC_CTX_cleanup(m_ctx);
+#else
+ HMAC_CTX_reset(m_ctx);
+#endif
+ return HashResult(std::move(digest));
+ }
+
+ void LogErrors(const char* logTag = OPENSSL_LOG_TAG)
+ {
+ unsigned long errorCode = ERR_get_error();
+ char errStr[256];
+ ERR_error_string_n(errorCode, errStr, 256);
+
+ AWS_LOGSTREAM_ERROR(logTag, errStr);
+ }
+
+ OpenSSLCipher::OpenSSLCipher(const CryptoBuffer& key, size_t blockSizeBytes, bool ctrMode) :
+ SymmetricCipher(key, blockSizeBytes, ctrMode), m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr)
+ {
+ Init();
+ }
+
+ OpenSSLCipher::OpenSSLCipher(OpenSSLCipher&& toMove) : SymmetricCipher(std::move(toMove)),
+ m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr)
+ {
+ Init();
+ EVP_CIPHER_CTX_copy(m_encryptor_ctx, toMove.m_encryptor_ctx);
+ EVP_CIPHER_CTX_copy(m_decryptor_ctx, toMove.m_decryptor_ctx);
+ EVP_CIPHER_CTX_cleanup(toMove.m_encryptor_ctx);
+ EVP_CIPHER_CTX_cleanup(toMove.m_decryptor_ctx);
+ }
+
+ OpenSSLCipher::OpenSSLCipher(CryptoBuffer&& key, CryptoBuffer&& initializationVector, CryptoBuffer&& tag) :
+ SymmetricCipher(std::move(key), std::move(initializationVector), std::move(tag)),
+ m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr)
+ {
+ Init();
+ }
+
+ OpenSSLCipher::OpenSSLCipher(const CryptoBuffer& key, const CryptoBuffer& initializationVector,
+ const CryptoBuffer& tag) :
+ SymmetricCipher(key, initializationVector, tag), m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr)
+ {
+ Init();
+ }
+
+ OpenSSLCipher::~OpenSSLCipher()
+ {
+ Cleanup();
+ if (m_encryptor_ctx)
+ {
+ EVP_CIPHER_CTX_free(m_encryptor_ctx);
+ m_encryptor_ctx = nullptr;
+ }
+ if (m_decryptor_ctx)
+ {
+ EVP_CIPHER_CTX_free(m_decryptor_ctx);
+ m_decryptor_ctx = nullptr;
+ }
+ }
+
+ void OpenSSLCipher::Init()
+ {
+ if (m_failure)
+ {
+ return;
+ }
+
+ if (!m_encryptor_ctx)
+ {
+ // EVP_CIPHER_CTX_init() will be called inside EVP_CIPHER_CTX_new().
+ m_encryptor_ctx = EVP_CIPHER_CTX_new();
+ assert(m_encryptor_ctx != nullptr);
+ }
+ else
+ { // _init is the same as _reset after openssl 1.1
+ EVP_CIPHER_CTX_init(m_encryptor_ctx);
+ }
+ if (!m_decryptor_ctx)
+ {
+ // EVP_CIPHER_CTX_init() will be called inside EVP_CIPHER_CTX_new().
+ m_decryptor_ctx = EVP_CIPHER_CTX_new();
+ assert(m_decryptor_ctx != nullptr);
+ }
+ else
+ { // _init is the same as _reset after openssl 1.1
+ EVP_CIPHER_CTX_init(m_decryptor_ctx);
+ }
+ m_emptyPlaintext = false;
+ }
+
+ CryptoBuffer OpenSSLCipher::EncryptBuffer(const CryptoBuffer& unEncryptedData)
+ {
+ if (m_failure)
+ {
+ AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for encryption. Aborting");
+ return CryptoBuffer();
+ }
+
+ int lengthWritten = static_cast<int>(unEncryptedData.GetLength() + (GetBlockSizeBytes() - 1));
+ CryptoBuffer encryptedText(static_cast<size_t>( lengthWritten + (GetBlockSizeBytes() - 1)));
+
+ if (!EVP_EncryptUpdate(m_encryptor_ctx, encryptedText.GetUnderlyingData(), &lengthWritten,
+ unEncryptedData.GetUnderlyingData(),
+ static_cast<int>(unEncryptedData.GetLength())))
+ {
+ m_failure = true;
+ LogErrors();
+ return CryptoBuffer();
+ }
+
+ if (static_cast<size_t>(lengthWritten) < encryptedText.GetLength())
+ {
+ return CryptoBuffer(encryptedText.GetUnderlyingData(), static_cast<size_t>(lengthWritten));
+ }
+ return encryptedText;
+ }
+
+ CryptoBuffer OpenSSLCipher::FinalizeEncryption()
+ {
+ if (m_failure)
+ {
+ AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for encryption finalization. Aborting");
+ return CryptoBuffer();
+ }
+
+ CryptoBuffer finalBlock(GetBlockSizeBytes());
+ int writtenSize = 0;
+ if (!EVP_EncryptFinal_ex(m_encryptor_ctx, finalBlock.GetUnderlyingData(), &writtenSize))
+ {
+ m_failure = true;
+ LogErrors();
+ return CryptoBuffer();
+ }
+ return CryptoBuffer(finalBlock.GetUnderlyingData(), static_cast<size_t>(writtenSize));
+ }
+
+ CryptoBuffer OpenSSLCipher::DecryptBuffer(const CryptoBuffer& encryptedData)
+ {
+ if (m_failure)
+ {
+ AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for decryption. Aborting");
+ return CryptoBuffer();
+ }
+
+ int lengthWritten = static_cast<int>(encryptedData.GetLength() + (GetBlockSizeBytes() - 1));
+ CryptoBuffer decryptedText(static_cast<size_t>(lengthWritten));
+
+ if (!EVP_DecryptUpdate(m_decryptor_ctx, decryptedText.GetUnderlyingData(), &lengthWritten,
+ encryptedData.GetUnderlyingData(),
+ static_cast<int>(encryptedData.GetLength())))
+ {
+ m_failure = true;
+ LogErrors();
+ return CryptoBuffer();
+ }
+
+ if (lengthWritten == 0)
+ {
+ m_emptyPlaintext = true;
+ }
+ if (static_cast<size_t>(lengthWritten) < decryptedText.GetLength())
+ {
+ return CryptoBuffer(decryptedText.GetUnderlyingData(), static_cast<size_t>(lengthWritten));
+ }
+ return decryptedText;
+ }
+
+ CryptoBuffer OpenSSLCipher::FinalizeDecryption()
+ {
+ if (m_failure)
+ {
+ AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for decryption finalization. Aborting");
+ return CryptoBuffer();
+ }
+
+ CryptoBuffer finalBlock(GetBlockSizeBytes());
+ int writtenSize = static_cast<int>(finalBlock.GetLength());
+ int ret = EVP_DecryptFinal_ex(m_decryptor_ctx, finalBlock.GetUnderlyingData(), &writtenSize);
+#if OPENSSL_VERSION_NUMBER > 0x1010104fL //1.1.1d
+ if (ret <= 0)
+#else
+ if (ret <= 0 && !m_emptyPlaintext) // see details why making exception for empty string at: https://github.com/aws/aws-sdk-cpp/issues/1413
+#endif
+ {
+ m_failure = true;
+ LogErrors();
+ return CryptoBuffer();
+ }
+ return CryptoBuffer(finalBlock.GetUnderlyingData(), static_cast<size_t>(writtenSize));
+ }
+
+ void OpenSSLCipher::Reset()
+ {
+ Cleanup();
+ Init();
+ }
+
+ void OpenSSLCipher::Cleanup()
+ {
+ m_failure = false;
+ if (m_encryptor_ctx) EVP_CIPHER_CTX_cleanup(m_encryptor_ctx);
+ if (m_decryptor_ctx) EVP_CIPHER_CTX_cleanup(m_decryptor_ctx);
+ }
+
+ bool OpenSSLCipher::CheckKeyAndIVLength(size_t expectedKeyLength, size_t expectedIVLength)
+ {
+ if (!m_failure && ((m_key.GetLength() != expectedKeyLength) || m_initializationVector.GetLength() != expectedIVLength))
+ {
+ AWS_LOGSTREAM_ERROR(OPENSSL_LOG_TAG, "Expected Key size is: " << expectedKeyLength << " and expected IV size is: " << expectedIVLength);
+ m_failure = true;
+ }
+ return !m_failure;
+ }
+
+ size_t AES_CBC_Cipher_OpenSSL::BlockSizeBytes = 16;
+ size_t AES_CBC_Cipher_OpenSSL::KeyLengthBits = 256;
+ static const char* CBC_LOG_TAG = "AES_CBC_Cipher_OpenSSL";
+
+ AES_CBC_Cipher_OpenSSL::AES_CBC_Cipher_OpenSSL(const CryptoBuffer& key) : OpenSSLCipher(key, BlockSizeBytes)
+ {
+ InitCipher();
+ }
+
+ AES_CBC_Cipher_OpenSSL::AES_CBC_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector) :
+ OpenSSLCipher(std::move(key), std::move(initializationVector))
+ {
+ InitCipher();
+ }
+
+ AES_CBC_Cipher_OpenSSL::AES_CBC_Cipher_OpenSSL(const CryptoBuffer& key,
+ const CryptoBuffer& initializationVector) :
+ OpenSSLCipher(key, initializationVector)
+ {
+ InitCipher();
+ }
+
+ void AES_CBC_Cipher_OpenSSL::InitCipher()
+ {
+ if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, BlockSizeBytes))
+ {
+ return;
+ }
+
+ if (!EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_cbc(), nullptr, m_key.GetUnderlyingData(),
+ m_initializationVector.GetUnderlyingData()) ||
+ !EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_cbc(), nullptr, m_key.GetUnderlyingData(),
+ m_initializationVector.GetUnderlyingData()))
+ {
+ m_failure = true;
+ LogErrors(CBC_LOG_TAG);
+ }
+ }
+
+ size_t AES_CBC_Cipher_OpenSSL::GetBlockSizeBytes() const
+ {
+ return BlockSizeBytes;
+ }
+
+ size_t AES_CBC_Cipher_OpenSSL::GetKeyLengthBits() const
+ {
+ return KeyLengthBits;
+ }
+
+ void AES_CBC_Cipher_OpenSSL::Reset()
+ {
+ OpenSSLCipher::Reset();
+ InitCipher();
+ }
+
+ size_t AES_CTR_Cipher_OpenSSL::BlockSizeBytes = 16;
+ size_t AES_CTR_Cipher_OpenSSL::KeyLengthBits = 256;
+ static const char* CTR_LOG_TAG = "AES_CTR_Cipher_OpenSSL";
+
+ AES_CTR_Cipher_OpenSSL::AES_CTR_Cipher_OpenSSL(const CryptoBuffer& key) : OpenSSLCipher(key, BlockSizeBytes,
+ true)
+ {
+ InitCipher();
+ }
+
+ AES_CTR_Cipher_OpenSSL::AES_CTR_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector) :
+ OpenSSLCipher(std::move(key), std::move(initializationVector))
+ {
+ InitCipher();
+ }
+
+ AES_CTR_Cipher_OpenSSL::AES_CTR_Cipher_OpenSSL(const CryptoBuffer& key,
+ const CryptoBuffer& initializationVector) :
+ OpenSSLCipher(key, initializationVector)
+ {
+ InitCipher();
+ }
+
+ void AES_CTR_Cipher_OpenSSL::InitCipher()
+ {
+ if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, BlockSizeBytes))
+ {
+ return;
+ }
+
+ if (!(EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_ctr(), nullptr, m_key.GetUnderlyingData(),
+ m_initializationVector.GetUnderlyingData())
+ && EVP_CIPHER_CTX_set_padding(m_encryptor_ctx, 0)) ||
+ !(EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_ctr(), nullptr, m_key.GetUnderlyingData(),
+ m_initializationVector.GetUnderlyingData())
+ && EVP_CIPHER_CTX_set_padding(m_decryptor_ctx, 0)))
+ {
+ m_failure = true;
+ LogErrors(CTR_LOG_TAG);
+ }
+ }
+
+ size_t AES_CTR_Cipher_OpenSSL::GetBlockSizeBytes() const
+ {
+ return BlockSizeBytes;
+ }
+
+ size_t AES_CTR_Cipher_OpenSSL::GetKeyLengthBits() const
+ {
+ return KeyLengthBits;
+ }
+
+ void AES_CTR_Cipher_OpenSSL::Reset()
+ {
+ OpenSSLCipher::Reset();
+ InitCipher();
+ }
+
+ size_t AES_GCM_Cipher_OpenSSL::BlockSizeBytes = 16;
+ size_t AES_GCM_Cipher_OpenSSL::KeyLengthBits = 256;
+ size_t AES_GCM_Cipher_OpenSSL::IVLengthBytes = 12;
+ size_t AES_GCM_Cipher_OpenSSL::TagLengthBytes = 16;
+
+ static const char* GCM_LOG_TAG = "AES_GCM_Cipher_OpenSSL";
+
+ AES_GCM_Cipher_OpenSSL::AES_GCM_Cipher_OpenSSL(const CryptoBuffer& key)
+ : OpenSSLCipher(key, IVLengthBytes)
+ {
+ InitCipher();
+ }
+
+ AES_GCM_Cipher_OpenSSL::AES_GCM_Cipher_OpenSSL(const CryptoBuffer& key, const CryptoBuffer* aad)
+ : OpenSSLCipher(key, IVLengthBytes), m_aad(*aad)
+ {
+ InitCipher();
+ }
+
+ AES_GCM_Cipher_OpenSSL::AES_GCM_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector,
+ CryptoBuffer&& tag, CryptoBuffer&& aad) :
+ OpenSSLCipher(std::move(key), std::move(initializationVector), std::move(tag)), m_aad(std::move(aad))
+ {
+ InitCipher();
+ }
+
+ AES_GCM_Cipher_OpenSSL::AES_GCM_Cipher_OpenSSL(const CryptoBuffer& key, const CryptoBuffer& initializationVector,
+ const CryptoBuffer& tag, const CryptoBuffer& aad) :
+ OpenSSLCipher(key, initializationVector, tag), m_aad(std::move(aad))
+ {
+ InitCipher();
+ }
+
+ CryptoBuffer AES_GCM_Cipher_OpenSSL::FinalizeEncryption()
+ {
+ if (m_failure)
+ {
+ AWS_LOGSTREAM_FATAL(GCM_LOG_TAG, "Cipher not properly initialized for encryption finalization. Aborting");
+ return CryptoBuffer();
+ }
+
+ int writtenSize = 0;
+ CryptoBuffer finalBlock(GetBlockSizeBytes());
+ EVP_EncryptFinal_ex(m_encryptor_ctx, finalBlock.GetUnderlyingData(), &writtenSize);
+
+ m_tag = CryptoBuffer(TagLengthBytes);
+ if (!EVP_CIPHER_CTX_ctrl(m_encryptor_ctx, EVP_CTRL_GCM_GET_TAG, static_cast<int>(m_tag.GetLength()),
+ m_tag.GetUnderlyingData()))
+ {
+ m_failure = true;
+ LogErrors(GCM_LOG_TAG);
+ }
+
+ return CryptoBuffer();
+ }
+
+ void AES_GCM_Cipher_OpenSSL::InitCipher()
+ {
+ if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, IVLengthBytes))
+ {
+ return;
+ }
+
+ if (!(EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr) &&
+ EVP_EncryptInit_ex(m_encryptor_ctx, nullptr, nullptr, m_key.GetUnderlyingData(),
+ m_initializationVector.GetUnderlyingData()) &&
+ EVP_CIPHER_CTX_set_padding(m_encryptor_ctx, 0)) ||
+ !(EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr) &&
+ EVP_DecryptInit_ex(m_decryptor_ctx, nullptr, nullptr, m_key.GetUnderlyingData(),
+ m_initializationVector.GetUnderlyingData()) &&
+ EVP_CIPHER_CTX_set_padding(m_decryptor_ctx, 0)))
+ {
+ m_failure = true;
+ LogErrors(GCM_LOG_TAG);
+ return;
+ }
+
+ if (m_aad.GetLength() > 0)
+ {
+ int outLen = 0;
+ if(!EVP_EncryptUpdate(m_encryptor_ctx, nullptr, &outLen, m_aad.GetUnderlyingData(), m_aad.GetLength())
+ || !EVP_DecryptUpdate(m_decryptor_ctx, nullptr, &outLen, m_aad.GetUnderlyingData(), m_aad.GetLength()))
+ {
+ m_failure = true;
+ LogErrors(GCM_LOG_TAG);
+ return;
+ }
+ }
+
+ //tag should always be set in GCM decrypt mode
+ if (m_tag.GetLength() > 0)
+ {
+ if (m_tag.GetLength() < TagLengthBytes)
+ {
+ AWS_LOGSTREAM_ERROR(GCM_LOG_TAG, "Illegal attempt to decrypt an AES GCM payload without a valid tag set: tag length=" << m_tag.GetLength());
+ m_failure = true;
+ return;
+ }
+
+ if (!EVP_CIPHER_CTX_ctrl(m_decryptor_ctx, EVP_CTRL_GCM_SET_TAG, static_cast<int>(m_tag.GetLength()), m_tag.GetUnderlyingData()))
+ {
+ m_failure = true;
+ LogErrors(GCM_LOG_TAG);
+ }
+ }
+ }
+
+ size_t AES_GCM_Cipher_OpenSSL::GetBlockSizeBytes() const
+ {
+ return BlockSizeBytes;
+ }
+
+ size_t AES_GCM_Cipher_OpenSSL::GetKeyLengthBits() const
+ {
+ return KeyLengthBits;
+ }
+
+ size_t AES_GCM_Cipher_OpenSSL::GetTagLengthBytes() const
+ {
+ return TagLengthBytes;
+ }
+
+ void AES_GCM_Cipher_OpenSSL::Reset()
+ {
+ OpenSSLCipher::Reset();
+ InitCipher();
+ }
+
+ size_t AES_KeyWrap_Cipher_OpenSSL::KeyLengthBits = 256;
+ size_t AES_KeyWrap_Cipher_OpenSSL::BlockSizeBytes = 8;
+ static const unsigned char INTEGRITY_VALUE = 0xA6;
+ static const size_t MIN_CEK_LENGTH_BYTES = 128 / 8;
+
+ static const char* KEY_WRAP_TAG = "AES_KeyWrap_Cipher_OpenSSL";
+
+ AES_KeyWrap_Cipher_OpenSSL::AES_KeyWrap_Cipher_OpenSSL(const CryptoBuffer& key) : OpenSSLCipher(key, 0)
+ {
+ InitCipher();
+ }
+
+ CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::EncryptBuffer(const CryptoBuffer& plainText)
+ {
+ if (!m_failure)
+ {
+ m_workingKeyBuffer = CryptoBuffer({&m_workingKeyBuffer, (CryptoBuffer*) &plainText});
+ }
+ return CryptoBuffer();
+ }
+
+ CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::FinalizeEncryption()
+ {
+ if (m_failure)
+ {
+ AWS_LOGSTREAM_FATAL(KEY_WRAP_TAG, "Cipher not properly initialized for encryption finalization. Aborting");
+ return CryptoBuffer();
+ }
+
+ if (m_workingKeyBuffer.GetLength() < MIN_CEK_LENGTH_BYTES)
+ {
+ AWS_LOGSTREAM_ERROR(KEY_WRAP_TAG, "Incorrect input length of " << m_workingKeyBuffer.GetLength());
+ m_failure = true;
+ return CryptoBuffer();
+ }
+
+ //the following is an in place implementation of
+ //RFC 3394 using the alternate in-place implementation.
+ //we use one in-place buffer instead of the copy at the end.
+ //the one letter variable names are meant to directly reflect the variables in the RFC
+ CryptoBuffer cipherText(m_workingKeyBuffer.GetLength() + BlockSizeBytes);
+
+ //put the integrity check register in the first 8 bytes of the final buffer.
+ memset(cipherText.GetUnderlyingData(), INTEGRITY_VALUE, BlockSizeBytes);
+ unsigned char* a = cipherText.GetUnderlyingData();
+
+ //put the register buffer after the integrity check register
+ memcpy(cipherText.GetUnderlyingData() + BlockSizeBytes, m_workingKeyBuffer.GetUnderlyingData(),
+ m_workingKeyBuffer.GetLength());
+ unsigned char* r = cipherText.GetUnderlyingData() + BlockSizeBytes;
+
+ int n = static_cast<int>(m_workingKeyBuffer.GetLength() / BlockSizeBytes);
+
+ //temporary encryption buffer
+ CryptoBuffer b(BlockSizeBytes * 2);
+ int outLen = static_cast<int>(b.GetLength());
+
+ //concatenation buffer
+ CryptoBuffer tempInput(BlockSizeBytes * 2);
+
+ for (int j = 0; j <= 5; ++j)
+ {
+ for (int i = 1; i <= n; ++i)
+ {
+ //concat A and R[i], A should be most significant and then R[i] should be least significant.
+ memcpy(tempInput.GetUnderlyingData(), a, BlockSizeBytes);
+ memcpy(tempInput.GetUnderlyingData() + BlockSizeBytes, r, BlockSizeBytes);
+
+ //encrypt the concatenated A and R[I] and store it in B
+ if (!EVP_EncryptUpdate(m_encryptor_ctx, b.GetUnderlyingData(), &outLen,
+ tempInput.GetUnderlyingData(), static_cast<int>(tempInput.GetLength())))
+ {
+ LogErrors(KEY_WRAP_TAG);
+ m_failure = true;
+ return CryptoBuffer();
+ }
+
+ unsigned char t = static_cast<unsigned char>((n * j) + i);
+ //put the 64 MSB ^ T into A
+ memcpy(a, b.GetUnderlyingData(), BlockSizeBytes);
+ a[7] ^= t;
+ //put the 64 LSB into R[i]
+ memcpy(r, b.GetUnderlyingData() + BlockSizeBytes, BlockSizeBytes);
+ //increment i -> R[i]
+ r += BlockSizeBytes;
+ }
+ //reset R
+ r = cipherText.GetUnderlyingData() + BlockSizeBytes;
+ }
+
+ return cipherText;
+ }
+
+ CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::DecryptBuffer(const CryptoBuffer& cipherText)
+ {
+ if (!m_failure)
+ {
+ m_workingKeyBuffer = CryptoBuffer({&m_workingKeyBuffer, (CryptoBuffer*)&cipherText});
+ }
+ return CryptoBuffer();
+ }
+
+ CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::FinalizeDecryption()
+ {
+ if (m_failure)
+ {
+ AWS_LOGSTREAM_FATAL(KEY_WRAP_TAG, "Cipher not properly initialized for decryption finalization. Aborting");
+ return CryptoBuffer();
+ }
+
+ if (m_workingKeyBuffer.GetLength() < MIN_CEK_LENGTH_BYTES + BlockSizeBytes)
+ {
+ AWS_LOGSTREAM_ERROR(KEY_WRAP_TAG, "Incorrect input length of " << m_workingKeyBuffer.GetLength());
+ m_failure = true;
+ return CryptoBuffer();
+ }
+
+ //the following is an in place implementation of
+ //RFC 3394 using the alternate in-place implementation.
+ //we use one in-place buffer instead of the copy at the end.
+ //the one letter variable names are meant to directly reflect the variables in the RFC
+ CryptoBuffer plainText(m_workingKeyBuffer.GetLength() - BlockSizeBytes);
+ memcpy(plainText.GetUnderlyingData(), m_workingKeyBuffer.GetUnderlyingData() + BlockSizeBytes, plainText.GetLength());
+
+ //integrity register should be the first 8 bytes of the cipher text
+ unsigned char* a = m_workingKeyBuffer.GetUnderlyingData();
+
+ //in-place register is the plaintext. For decryption, start at the last array position (8 bytes before the end);
+ unsigned char* r = plainText.GetUnderlyingData() + plainText.GetLength() - BlockSizeBytes;
+
+ int n = static_cast<int>(plainText.GetLength() / BlockSizeBytes);
+
+ //temporary encryption buffer
+ CryptoBuffer b(BlockSizeBytes * 10);
+ int outLen = static_cast<int>(b.GetLength());
+
+ //concatenation buffer
+ CryptoBuffer tempInput(BlockSizeBytes * 2);
+
+ for(int j = 5; j >= 0; --j)
+ {
+ for(int i = n; i >= 1; --i)
+ {
+ //concat
+ //A ^ t
+ memcpy(tempInput.GetUnderlyingData(), a, BlockSizeBytes);
+ unsigned char t = static_cast<unsigned char>((n * j) + i);
+ tempInput[7] ^= t;
+ //R[i]
+ memcpy(tempInput.GetUnderlyingData() + BlockSizeBytes, r, BlockSizeBytes);
+
+ //Decrypt the concatenated buffer
+ if(!EVP_DecryptUpdate(m_decryptor_ctx, b.GetUnderlyingData(), &outLen,
+ tempInput.GetUnderlyingData(), static_cast<int>(tempInput.GetLength())))
+ {
+ m_failure = true;
+ LogErrors(KEY_WRAP_TAG);
+ return CryptoBuffer();
+ }
+
+ //set A to MSB 64 bits of decrypted result
+ memcpy(a, b.GetUnderlyingData(), BlockSizeBytes);
+ //set R[i] to LSB 64 bits of decrypted result
+ memcpy(r, b.GetUnderlyingData() + BlockSizeBytes, BlockSizeBytes);
+ //decrement i -> R[i]
+ r -= BlockSizeBytes;
+ }
+
+ r = plainText.GetUnderlyingData() + plainText.GetLength() - BlockSizeBytes;
+ }
+
+ //here we perform the integrity check to make sure A == 0xA6A6A6A6A6A6A6A6
+ for(size_t i = 0; i < BlockSizeBytes; ++i)
+ {
+ if(a[i] != INTEGRITY_VALUE)
+ {
+ m_failure = true;
+ AWS_LOGSTREAM_ERROR(KEY_WRAP_TAG, "Integrity check failed for key wrap decryption.");
+ return CryptoBuffer();
+ }
+ }
+
+ return plainText;
+ }
+
+ void AES_KeyWrap_Cipher_OpenSSL::InitCipher()
+ {
+ if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, 0))
+ {
+ return;
+ }
+
+ if (!(EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_ecb(), nullptr, m_key.GetUnderlyingData(), nullptr) &&
+ EVP_CIPHER_CTX_set_padding(m_encryptor_ctx, 0)) ||
+ !(EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_ecb(), nullptr, m_key.GetUnderlyingData(), nullptr) &&
+ EVP_CIPHER_CTX_set_padding(m_decryptor_ctx, 0)))
+ {
+ m_failure = true;
+ LogErrors(KEY_WRAP_TAG);
+ }
+ }
+
+ void AES_KeyWrap_Cipher_OpenSSL::Reset()
+ {
+ m_workingKeyBuffer = CryptoBuffer();
+ OpenSSLCipher::Reset();
+ InitCipher();
+ }
+ }
+ }
+}