diff options
Diffstat (limited to 'src/crypto/chacha20.cpp')
-rw-r--r-- | src/crypto/chacha20.cpp | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/src/crypto/chacha20.cpp b/src/crypto/chacha20.cpp index c72ccccc65..80db0a3a83 100644 --- a/src/crypto/chacha20.cpp +++ b/src/crypto/chacha20.cpp @@ -297,6 +297,13 @@ inline void ChaCha20Aligned::Crypt64(const unsigned char* m, unsigned char* c, s void ChaCha20::Keystream(unsigned char* c, size_t bytes) { if (!bytes) return; + if (m_bufleft) { + unsigned reuse = std::min<size_t>(m_bufleft, bytes); + memcpy(c, m_buffer + 64 - m_bufleft, reuse); + m_bufleft -= reuse; + bytes -= reuse; + c += reuse; + } if (bytes >= 64) { size_t blocks = bytes / 64; m_aligned.Keystream64(c, blocks); @@ -304,15 +311,25 @@ void ChaCha20::Keystream(unsigned char* c, size_t bytes) bytes -= blocks * 64; } if (bytes) { - unsigned char buffer[64]; - m_aligned.Keystream64(buffer, 1); - memcpy(c, buffer, bytes); + m_aligned.Keystream64(m_buffer, 1); + memcpy(c, m_buffer, bytes); + m_bufleft = 64 - bytes; } } void ChaCha20::Crypt(const unsigned char* m, unsigned char* c, size_t bytes) { if (!bytes) return; + if (m_bufleft) { + unsigned reuse = std::min<size_t>(m_bufleft, bytes); + for (unsigned i = 0; i < reuse; i++) { + c[i] = m[i] ^ m_buffer[64 - m_bufleft + i]; + } + m_bufleft -= reuse; + bytes -= reuse; + c += reuse; + m += reuse; + } if (bytes >= 64) { size_t blocks = bytes / 64; m_aligned.Crypt64(m, c, blocks); @@ -321,10 +338,10 @@ void ChaCha20::Crypt(const unsigned char* m, unsigned char* c, size_t bytes) bytes -= blocks * 64; } if (bytes) { - unsigned char buffer[64]; - m_aligned.Keystream64(buffer, 1); + m_aligned.Keystream64(m_buffer, 1); for (unsigned i = 0; i < bytes; i++) { - c[i] = m[i] ^ buffer[i]; + c[i] = m[i] ^ m_buffer[i]; } + m_bufleft = 64 - bytes; } } |