aboutsummaryrefslogtreecommitdiff
path: root/src/crypto/chacha20.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto/chacha20.cpp')
-rw-r--r--src/crypto/chacha20.cpp29
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;
}
}