in src/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp [23:117]
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));
}