16#define QUARTERROUND(a,b,c,d) \
17 a += b; d = std::rotl(d ^ a, 16); \
18 c += d; b = std::rotl(b ^ c, 12); \
19 a += b; d = std::rotl(d ^ a, 8); \
20 c += d; b = std::rotl(b ^ c, 7);
22#define REPEAT10(a) do { {a}; {a}; {a}; {a}; {a}; {a}; {a}; {a}; {a}; {a}; } while(0)
53 input[8] = block_counter;
61 std::byte* c = output.data();
62 size_t blocks = output.size() /
BLOCKLEN;
65 uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
66 uint32_t j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
162 assert(in_bytes.size() == out_bytes.size());
163 const std::byte*
m = in_bytes.data();
164 std::byte* c = out_bytes.data();
165 size_t blocks = out_bytes.size() /
BLOCKLEN;
168 uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
169 uint32_t j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
283 if (out.empty())
return;
285 unsigned reuse = std::min<size_t>(
m_bufleft, out.size());
288 out = out.subspan(reuse);
291 size_t blocks = out.size() /
m_aligned.BLOCKLEN;
293 out = out.subspan(blocks *
m_aligned.BLOCKLEN);
302void ChaCha20::Crypt(std::span<const std::byte> input, std::span<std::byte> output)
noexcept
304 assert(input.size() == output.size());
306 if (!input.size())
return;
308 unsigned reuse = std::min<size_t>(
m_bufleft, input.size());
309 for (
unsigned i = 0; i < reuse; i++) {
313 output = output.subspan(reuse);
314 input = input.subspan(reuse);
316 if (input.size() >=
m_aligned.BLOCKLEN) {
317 size_t blocks = input.size() /
m_aligned.BLOCKLEN;
319 output = output.subspan(blocks *
m_aligned.BLOCKLEN);
320 input = input.subspan(blocks *
m_aligned.BLOCKLEN);
322 if (!input.empty()) {
324 for (
unsigned i = 0; i < input.size(); i++) {
351 assert(input.size() == output.size());
359 std::byte new_key[
KEYLEN];
void Keystream(std::span< std::byte > out) noexcept
outputs the keystream into out, whose length must be a multiple of BLOCKLEN.
void Crypt(std::span< const std::byte > input, std::span< std::byte > output) noexcept
en/deciphers the message <input> and write the result into <output>
ChaCha20Aligned() noexcept=delete
For safety, disallow initialization without key.
std::pair< uint32_t, uint64_t > Nonce96
Type for 96-bit nonces used by the Set function below.
void Seek(Nonce96 nonce, uint32_t block_counter) noexcept
Set the 96-bit nonce and 32-bit block counter.
static constexpr unsigned BLOCKLEN
Block size (inputs/outputs to Keystream / Crypt should be multiples of this).
static constexpr unsigned KEYLEN
Expected key length in constructor and SetKey.
void SetKey(std::span< const std::byte > key) noexcept
Set 32-byte key, and seek to nonce 0 and block position 0.
~ChaCha20Aligned()
Destructor to clean up private memory.
void SetKey(std::span< const std::byte > key) noexcept
Set 32-byte key, and seek to nonce 0 and block position 0.
std::array< std::byte, ChaCha20Aligned::BLOCKLEN > m_buffer
~ChaCha20()
Destructor to clean up private memory.
void Keystream(std::span< std::byte > out) noexcept
outputs the keystream to out.
void Crypt(std::span< const std::byte > in_bytes, std::span< std::byte > out_bytes) noexcept
en/deciphers the message <in_bytes> and write the result into <out_bytes>
ChaCha20Aligned m_aligned
ChaCha20 m_chacha20
Internal stream cipher.
uint32_t m_chunk_counter
The number of encryptions/decryptions since the last rekey.
static constexpr unsigned KEYLEN
Length of keys expected by the constructor.
const uint32_t m_rekey_interval
The number of encryptions/decryptions before a rekey happens.
FSChaCha20(const FSChaCha20 &)=delete
void Crypt(std::span< const std::byte > input, std::span< std::byte > output) noexcept
Encrypt or decrypt a chunk.
uint64_t m_rekey_counter
The number of rekey operations that have happened.
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
#define QUARTERROUND(a, b, c, d)
void WriteLE32(B *ptr, uint32_t x)
uint32_t ReadLE32(const B *ptr)