.\" This file is dual-licensed.  Choose whichever you want.
.\"
.\" The first licence is a regular 2-clause BSD licence.  The second licence
.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
.\" to the public domain.  The BSD licence serves as a fallback option.
.\"
.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
.\"
.\" ----------------------------------------------------------------------------
.\"
.\" Copyright (c) 2017-2019, 2023 Loup Vaillant
.\" Copyright (c) 2017-2018 Michael Savage
.\" Copyright (c) 2017, 2019-2021, 2023 Fabio Scotoni
.\" All rights reserved.
.\"
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions are
.\" met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
.\"    notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\"    notice, this list of conditions and the following disclaimer in the
.\"    documentation and/or other materials provided with the
.\"    distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" ----------------------------------------------------------------------------
.\"
.\" Written in 2017-2023 by Loup Vaillant, Michael Savage and Fabio Scotoni
.\"
.\" To the extent possible under law, the author(s) have dedicated all copyright
.\" and related neighboring rights to this software to the public domain
.\" worldwide.  This software is distributed without any warranty.
.\"
.\" You should have received a copy of the CC0 Public Domain Dedication along
.\" with this software.  If not, see
.\" <https://creativecommons.org/publicdomain/zero/1.0/>
.\"
.Dd February 25, 2023
.Dt CRYPTO_CHACHA20 3MONOCYPHER
.Os
.Sh NAME
.Nm crypto_chacha20_djb ,
.Nm crypto_chacha20_ietf ,
.Nm crypto_chacha20_x ,
.Nm crypto_chacha20_h
.Nd ChaCha20 and XChaCha20 encryption functions
.Sh SYNOPSIS
.In monocypher.h
.Ft uint64_t
.Fo crypto_chacha20_djb
.Fa "uint8_t *cipher_text"
.Fa "const uint8_t *plain_text"
.Fa "size_t text_size"
.Fa "const uint8_t key[32]"
.Fa "const uint8_t nonce[8]"
.Fa "uint64_t ctr"
.Fc
.Ft uint32_t
.Fo crypto_chacha20_ietf
.Fa "uint8_t *cipher_text"
.Fa "const uint8_t *plain_text"
.Fa "size_t text_size"
.Fa "const uint8_t key[32]"
.Fa "const uint8_t nonce[12]"
.Fa "uint32_t ctr"
.Fc
.Ft uint64_t
.Fo crypto_chacha20_x
.Fa "uint8_t *cipher_text"
.Fa "const uint8_t *plain_text"
.Fa "size_t text_size"
.Fa "const uint8_t key[32]"
.Fa "const uint8_t nonce[24]"
.Fa "uint64_t ctr"
.Fc
.Ft void
.Fo crypto_chacha20_h
.Fa "uint8_t out[32]"
.Fa "const uint8_t key[32]"
.Fa "const uint8_t in[16]"
.Fc
.Sh DESCRIPTION
These functions provide an interface for the ChaCha20 encryption
primitive.
.Pp
ChaCha20 is a low-level primitive.
Consider using authenticated encryption, implemented by
.Xr crypto_aead_lock 3monocypher .
.Pp
The arguments are:
.Bl -tag -width Ds
.It Fa key
A 32-byte secret key.
.It Fa nonce
An 8-byte, 12-byte, or 24-byte number used only once with any given key.
It does not need to be secret or random, but it does have to be unique.
Repeating a nonce with the same key reveals the XOR of two different
messages, which allows decryption.
24-byte nonces can be selected at random.
8-byte and 12-byte nonces
.Em cannot
because they are too small and the same nonce may be selected twice by
accident.
See
.Xr intro 3monocypher
for advice about generating random numbers (use the operating system's
random number generator).
.It Fa plain_text
The message to encrypt.
It is allowed to be
.Dv NULL ,
in which case it will be interpreted as an all-zero input.
.Fa cipher_text
will then contain the raw ChaCha20 stream.
.It Fa cipher_text
The encrypted message.
.It Fa text_size
Length of both
.Fa plain_text
and
.Fa cipher_text ,
in bytes.
.It Fa ctr
The number of 64-byte blocks we skip from the beginning of the stream.
This can be used to encrypt (or decrypt) part of a long message or to
implement some AEAD constructions such as the one described in RFC
8439.
Should be zero by default.
When using this, be careful  not to accidentally reuse parts of the
random stream as that would destroy confidentiality.
The return value can help here.
.El
.Pp
The
.Fa key
and
.Fa nonce
buffers may overlap.
.Fa plain_text
and
.Fa cipher_text
must either be the same buffer (for in-place encryption) or
non-overlapping.
.Pp
.Fn crypto_chacha20_djb ,
.Fn crypto_chacha20_ietf ,
and
.Fn crypto_chacha20_x
perform a ChaCha20 operation.
Their main difference is the size of their nonce and counter.
.Fn crypto_chacha20_ietf
in particular implements RFC 8439,
and is provided strictly for compatibility with existing systems or
standards compliance.
.Pp
.Fn crypto_chacha20_x
Is the only function that uses a nonce long enough to be random.
This makes it easier to use securely,
and the performance hit of the extended nonce is often negligible in
practice.
Use it instead of
.Fn crypto_chacha20_djb
and
.Fn crypto_chacha20_ietf
if possible.
.Pp
The
.Fn crypto_chacha20_djb ,
.Fn crypto_chacha20_ietf ,
and
.Fn crypto_chacha20_x
encrypt
.Fa plain_text
by XORing it with a pseudo-random stream of
numbers, seeded by the provided
.Fa key
and
.Fa nonce .
.Pp
Since XOR is its own inverse, decryption is the same operation as
encryption.
To decrypt the cipher text,
.Dq encrypt
it again with the same key and nonce.
You will likely want to wipe the key when you are done with
encryption or decryption.
Use
.Xr crypto_wipe 3monocypher
to wipe them.
.Pp
The
.Fa plain_text
pointer is allowed to be
.Dv NULL ,
in which case it will be interpreted as an all-zero input.
This is useful as a user space random number generator.
While
.Sy this should not be used as a random number generator for secrets ,
for which the operating system random number generator should be
preferred,
it can be handy outside of a security context.
Deterministic procedural generation and reproducible property-based
tests come to mind.
Additionally, it
.Em can
be used to generate large amounts of random-looking data quickly
\(en for example to generate padding.
.Sh RETURN VALUES
.Fn crypto_chacha20_djb ,
.Fn crypto_chacha20_ietf ,
and
.Fn crypto_chacha20_x
return the next
.Fa ctr
to use with the same key and nonce values;
this is the previous
.Fa ctr ,
plus
.Fa text_size
divided by 64 (rounded up).
.Sh EXAMPLES
The following examples assume the existence of
.Fn arc4random_buf ,
which fills the given buffer with cryptographically secure random bytes.
If
.Fn arc4random_buf
does not exist on your system, see
.Xr intro 3monocypher
for advice about how to generate cryptographically secure random bytes.
.Pp
Simple encryption:
.Bd -literal -offset indent
uint8_t key        [ 32]; /* Secret random key              */
uint8_t nonce      [ 24]; /* Unique nonce (possibly random) */
uint8_t plain_text [500] = {1}; /* Secret message           */
uint8_t cipher_text[500]; /* Encrypted message              */
arc4random_buf(key,   32);
arc4random_buf(nonce, 24);
crypto_chacha20_x(cipher_text, plain_text, 500, key, nonce, 0);
/* Wipe secrets if they are no longer needed */
crypto_wipe(key,        32);
crypto_wipe(plain_text, 500);
.Ed
.Pp
To decrypt the above:
.Bd -literal -offset indent
uint8_t       key        [ 32]; /* Same key as above        */
const uint8_t nonce      [ 24]; /* Same nonce as above      */
uint8_t       cipher_text[500]; /* Message to decrypt       */
uint8_t       plain_text [500]; /* Secret message           */
crypto_chacha20_x(plain_text, cipher_text, 500, key, nonce, 0);
/* Wipe secrets if they are no longer needed */
crypto_wipe(key,        32);
/* The plaintext likely needs to be processed before you wipe it */
crypto_wipe(plain_text, 12);
.Ed
.Pp
Incremental encryption (in blocks of 64 bytes):
.Bd -literal -offset indent
uint8_t  key        [ 32]; /* Secret random key              */
uint8_t  nonce      [ 24]; /* Unique nonce (possibly random) */
uint8_t  plain_text [500]; /* Secret message                 */
uint8_t  cipher_text[500]; /* Encrypted message              */
uint64_t ctr = 0;          /* Block counter                  */
unsigned int i;
arc4random_buf(key,   32);
arc4random_buf(nonce, 24);
for(i = 0; i < 500; i += 64) {
    ctr = crypto_chacha20_x(cipher_text+i, plain_text+i, 64,
                            key, nonce, ctr);
}
/* Process data that didn't fit into 64-byte pieces */
crypto_chacha20_x(cipher_text+500-(i-64),
                  plain_text+500-(i-64),
                  500-(i-64),
                  key, nonce, ctr);
/* Wipe secrets if they are no longer needed */
crypto_wipe(key,        32);
crypto_wipe(plain_text, 500);
.Ed
.Pp
Encryption by jumping around (do not do this, this is only meant to show
how the counter works):
.Bd -literal -offset indent
uint8_t key        [ 32]; /* Secret random key              */
uint8_t nonce      [ 24]; /* Unique nonce (possibly random) */
uint8_t plain_text [500] = {1}; /* Message to be encrypted  */
uint8_t cipher_text[500]; /* Will be the encrypted message  */
arc4random_buf(key,   32);
arc4random_buf(nonce, 24);
/* Encrypt the second part of the message first... */
crypto_chacha20_x(cipher_text + (3 * 64),
                  plain_text  + (3 * 64),
                  500         - (3 * 64),
                  key, nonce, 3);
/* ...then encrypt the first part */
crypto_chacha20_x(cipher_text, plain_text, 3 * 64, key, nonce, 0);
/* Wipe secrets if they are no longer needed */
crypto_wipe(key,        32);
crypto_wipe(plain_text, 500);
.Ed
.Sh HCHACHA20
.Fn crypto_chacha20_h
provides a not-so-cryptographic hash.
.Sy This is not a general-purpose cryptographic hash function .
It may be used for some specific purposes such as X25519 key
derivation or XChaCha20 initialisation.
If in doubt, do not use directly.
Use
.Xr crypto_blake2b 3monocypher
instead.
.Pp
The arguments are:
.Bl -tag -width Ds
.It Fa key
A sufficiently random key, such as the output of
.Xr crypto_x25519 3monocypher .
.It Fa in
The space reserved for the ChaCha20 nonce and counter.
It does not have to be random.
.It Fa out
A cryptographically secure random number
.Em if
there is enough entropy in
.Fa key .
X25519 shared secrets have enough entropy.
.El
.Pp
For instance:
.Bd -literal -offset indent
uint8_t key[32]; /* Must have enough entropy           */
uint8_t in [16]; /* Does not have to be random         */
uint8_t out[32]; /* Will be random iff the above holds */
arc4random_buf(key, 32);
crypto_chacha20_h(out, key, in);
/* Wipe secrets if they are no longer needed */
crypto_wipe(key, 32);
crypto_wipe(in , 16);
.Ed
.Sh SEE ALSO
.Xr crypto_aead_lock 3monocypher ,
.Xr crypto_wipe 3monocypher ,
.Xr intro 3monocypher
.Sh STANDARDS
These functions implement ChaCha20, XChaCha20, and HChaCha20.
ChaCha20 is described in:
.Rs
.%A Daniel J. Bernstein
.%J SASC 2008 \(en The State of the Art of Stream Ciphers
.%P pp. 273\(en278
.%T ChaCha, a variant of Salsa20
.Re
The nonce and counter sizes were modified in RFC 8439.
XChaCha20 derives from ChaCha20 the same way XSalsa20 derives from
Salsa20 and benefits from the same security reduction (proven secure
as long as ChaCha20 itself is secure).
.Sh HISTORY
.Fn crypto_chacha20 ,
.Fn crypto_chacha20_ctr ,
.Fn crypto_ietf_chacha20 ,
.Fn crypto_ietf_chacha20_ctr ,
.Fn crypto_xchacha20 ,
and
.Fn crypto_xchacha20_ctr
were added in Monocypher 3.0.0.
They replace
.Fn crypto_chacha20_encrypt ,
.Fn crypto_chacha20_init ,
.Fn crypto_chacha20_stream ,
.Fn crypto_chacha20_x_init ,
and
.Fn crypto_chacha20_set_ctr
that were deprecated in Monocypher 3.0.0.
In Monocypher 4.0.0, only the ctr variants have been kept,
and were renamed
.Fn crypto_chacha20_djb ,
.Fn crypto_chacha20_ietf ,
and
.Fn crypto_chacha20_x
respectively.
.Pp
.Fn crypto_chacha20_h
function first appeared in Monocypher 0.1 as
.Fn crypto_chacha20_H .
It was renamed to
.Fn crypto_hchacha20
in Monocypher 3.0.0, then
.Fn crypto_chacha20_h
in Monocypher 4.0.0.
.Sh CAVEATS
Monocypher does not perform any input validation.
Any deviation from the specified input and output length ranges results
in
.Sy undefined behaviour .
Make sure your inputs are correct.
.Sh SECURITY CONSIDERATIONS
.Ss Encrypted does not mean secure
ChaCha20 only protects against eavesdropping, not forgeries.
Most applications need protection against forgeries to be properly
secure.
To ensure the integrity of a message, use BLAKE2b in keyed mode or
authenticated encryption; see
.Xr crypto_blake2b 3monocypher
and
.Xr crypto_aead_lock 3monocypher .
.Ss Nonce reuse
Repeating a nonce with the same key exposes the XOR of two or more
plaintext messages, effectively destroying confidentiality.
.Pp
For the same reason,
.Sy do not select small nonces at random .
The
.Fn crypto_chacha20_djb
nonce spans only 64 bits, which is small enough to trigger accidental
reuses.
A message counter should be used instead.
If multiple parties send out messages,
each can start with an initial nonce of 0, 1, 2 (...) n-1 respectively,
and increment them by n for each new message.
Make sure the counters never wrap around.
.Ss Secure random number generation
Do not use these functions as a cryptographic random number generator.
Always use the operating system's random number generator for
cryptographic purposes; see
.Xr intro 3monocypher .
.Ss Protection against side channels
Secrets should not dwell in memory longer than needed.
Use
.Xr crypto_wipe 3monocypher
to erase secrets you no longer need.
For ChaCha20, this means the key and in some cases the
plaintext itself.
