# ChaCha stream cipher

This unit implements the ChaCha stream cipher which is suitable for
communication and secure random number generation.

As a stream cipher, ChaCha uses the same function for both encryption and
decryption of the given data stream. A stream cipher is a class of symmetric-key
algorithm. This means that both ends of the communication use the same key
which must be kept secret. The nonce can optionnally be secret.

## Security considerations

This implementation has not been reviewed nor audited by any competent authority.
It is provided purely as a best effort basis and only follows the indications
given by the IRTF's RFC 8349.

The ChaCha20 cipher is designed to provide 256-bit security. While 20 rounds
is the biggest usual round count, other round counts (8 or 12) are generally
considered good enough for most applications. The algorithm speed is
proportional to the round count, hence the possibility to use smaller ones.

Variant differences:
* The Legacy variant operates on a 64-bit nonce with a 64-bit counter.
* The IETF variant operates on a 96-bit nonce with a 32-bit counter.
* The XChaCha variant operates on a 192-bit nonce with a 64-bit counter.

The key length is always 32 bytes / 256 bits.

Note that the performance penalty of XChaCha is negligible, only occuring during
initialization. Use this variant if you have enough material for a bigger nonce.

## API

### Struct

struct ChaCha {
  +$00 [uint,16] wstate ; \ working state
  +$40 [uint,16] bstate ; \ base state
  +$70 uint cntlo cnthi ; \ counter
  +$74 [uint,3] nonce ;
  +$80 uchar rounds variant remaining void? ;
}

cntlo      The 32 lower bits of the counter.
cnthi      The 32 higher bits of the counter. Depending on the variant these are
           part of the nonce instead.
rounds     The number of rounds. It should be even and either 8, 12, or 20.
variant    The cipher variant. It must be either IETF, Legacy, or XChaCha.
remaining  The remaining bytes to be consumed before increasing the inner
           counter. This is used for implementation only.
void?      Whether to void (set to 0) the nonce and key on a call to ChaCha$.
           Zeroing memory reduces the possibility of a secret information
           getting compromised.

### Words

newChaCha20 ( -- chacha )
  Initialize a new ChaCha cipher with a count of 20 rounds.
  The counter is set to 1, the variant is IETF, and void? is set.

  To tweak the other parameters, set fields or use "to{" [doc/usage/to].
  These parameters must be changed before any call to ChaCha$.

ChaCha$ ( an ak chacha -- )
  Set the given key and nonce from addresses ak and an respectively to the
  ChaCha cipher. Depending on the variant the expected length of the nonce can
  differ and further calculation can happen.

apply ( a u chacha -- a' )
  Encrypt or decrypt the given range. Note that for a streaming cipher these two
  operations are the same. The returned address is the end of the range: a'=a+u.
  This operation can be called multiple times without issue so the data can be
  encrypted in a streaming manner.

discard ( chacha -- )
  Void the internal state of the ChaCha cipher as a security mean.
  Set back the "void?" field. The cipher can then be reused for other streams.

## Low-level API

loadstate ( chacha -- chacha )
  Load the base state into the working state, the working state is the one
  operated on.

blockfn ( chacha -- )
  Execute the "block function" over the working state, that is, apply n ChaCha
  rounds then sum with the base state.

counter1+ ( chacha -- chacha )
  Increment the counter by one. This takes care of handling a 64-bit counter
  depending on the ChaCha variant.
