diff options
Diffstat (limited to 'src/crypto/chacha20.cpp')
-rw-r--r-- | src/crypto/chacha20.cpp | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/crypto/chacha20.cpp b/src/crypto/chacha20.cpp index fafd783ab1..469b280494 100644 --- a/src/crypto/chacha20.cpp +++ b/src/crypto/chacha20.cpp @@ -7,6 +7,7 @@ #include <crypto/common.h> #include <crypto/chacha20.h> +#include <support/cleanse.h> #include <algorithm> #include <string.h> @@ -42,6 +43,11 @@ ChaCha20Aligned::ChaCha20Aligned() memset(input, 0, sizeof(input)); } +ChaCha20Aligned::~ChaCha20Aligned() +{ + memory_cleanse(input, sizeof(input)); +} + ChaCha20Aligned::ChaCha20Aligned(const unsigned char* key32) { SetKey32(key32); @@ -318,3 +324,38 @@ void ChaCha20::Crypt(const unsigned char* m, unsigned char* c, size_t bytes) m_bufleft = 64 - bytes; } } + +ChaCha20::~ChaCha20() +{ + memory_cleanse(m_buffer, sizeof(m_buffer)); +} + +FSChaCha20::FSChaCha20(Span<const std::byte> key, uint32_t rekey_interval) noexcept : + m_chacha20(UCharCast(key.data())), m_rekey_interval(rekey_interval) +{ + assert(key.size() == KEYLEN); +} + +void FSChaCha20::Crypt(Span<const std::byte> input, Span<std::byte> output) noexcept +{ + assert(input.size() == output.size()); + + // Invoke internal stream cipher for actual encryption/decryption. + m_chacha20.Crypt(UCharCast(input.data()), UCharCast(output.data()), input.size()); + + // Rekey after m_rekey_interval encryptions/decryptions. + if (++m_chunk_counter == m_rekey_interval) { + // Get new key from the stream cipher. + std::byte new_key[KEYLEN]; + m_chacha20.Keystream(UCharCast(new_key), sizeof(new_key)); + // Update its key. + m_chacha20.SetKey32(UCharCast(new_key)); + // Wipe the key (a copy remains inside m_chacha20, where it'll be wiped on the next rekey + // or on destruction). + memory_cleanse(new_key, sizeof(new_key)); + // Set the nonce for the new section of output. + m_chacha20.Seek64({0, ++m_rekey_counter}, 0); + // Reset the chunk counter. + m_chunk_counter = 0; + } +} |