.\" 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 Loup Vaillant
.\" Copyright (c) 2018 Michael Savage
.\" Copyright (c) 2017, 2019-2020 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-2020 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 March 31, 2020
.Dt CRYPTO_CHACHA20 3MONOCYPHER
.Os
.Sh NAME
.Nm crypto_chacha20 ,
.Nm crypto_chacha20_ctr ,
.Nm crypto_xchacha20 ,
.Nm crypto_xchacha20_ctr
.Nd Chacha20 and XChacha20 encryption functions
.Sh SYNOPSIS
.In monocypher.h
.Ft void
.Fo crypto_chacha20
.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]"
.Fc
.Ft void
.Fo crypto_xchacha20
.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]"
.Fc
.Ft uint64_t
.Fo crypto_chacha20_ctr
.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 uint64_t
.Fo crypto_xchacha20_ctr
.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
.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_lock 3monocypher .
.Pp
The arguments are:
.Bl -tag -width Ds
.It Fa key
A 32-byte secret key.
.It Fa nonce
An 8-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 nonces
.Em cannot .
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 since the beginning of the stream.
.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
performs a Chacha20 operation.
It uses an 8-byte nonce, which is too small to be selected at random.
Use a message counter as a nonce instead.
.Pp
.Fn crypto_xchacha20
performs an XChacha20 operation.
It uses a 24-byte nonce, which is large enough to be selected at random.
.Pp
.Fn crypto_xchacha20
is recommended over
.Fn crypto_chacha20 .
The ability to use random nonces makes it easier to use securely, and
the performance hit is often negligible in practice.
.Pp
The
.Fn crypto_chacha20
and
.Fn crypto_xchacha20
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,
for example to generate padding.
.Pp
The
.Fn crypto_chacha20_ctr
and
.Fn crypto_xchacha20_ctr
perform a Chacha20 or XChacha20 encryption, respectively,
starting the stream at the block
.Fa ctr
(which is the byte
.Ql ctr \(mu 64 ) .
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.
Be careful when using this not to accidentally reuse parts of the
random stream as that would destroy confidentiality.
.Sh RETURN VALUES
.Fn crypto_chacha20
and
.Fn crypto_xchacha20
return nothing.
.Fn crypto_chacha20_ctr
and
.Fn crypto_xchacha20_ctr
functions return the next
.Fa ctr
to use with the same key and nonce values;
this is always
.Fa text_size
divided by 64;
plus one if there was a remainder.
.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_xchacha20(cipher_text, plain_text, 500, key, nonce);
/* 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       plain_text [500]; /* Message to decrypt       */
uint8_t       cipher_text[500]; /* Secret message           */
crypto_xchacha20(cipher_text, plain_text, 500, key, nonce);
/* Wipe secrets if they are no longer needed */
crypto_wipe(key,        32);
/* The plain text 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_xchacha20_ctr(cipher_text+i, plain_text+i, 64,
                               key, nonce, ctr);
}
/* Process data that didn't fit into 64 byte pieces */
crypto_xchacha20_ctr(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 that, this is only meant to show
how
.Fn crypto_xchacha20_ctr
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_xchacha20_ctr(cipher_text + (3 * 64),
                     plain_text  + (3 * 64),
                     500         - (3 * 64),
                     key, nonce, 3);
/* ...then encrypt the first part */
crypto_xchacha20_ctr(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 SEE ALSO
.Xr crypto_ietf_chacha20 3monocypher ,
.Xr crypto_lock 3monocypher ,
.Xr crypto_wipe 3monocypher ,
.Xr intro 3monocypher
.Sh STANDARDS
These functions implement Chacha20 and XChacha20.
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_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.
.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_lock 3monocypher .
.Ss Nonce reuse
Repeating a nonce with the same key exposes the XOR of two or more
plain text messages, effectively destroying confidentiality.
.Pp
For the same reason,
.Sy do not select small nonces at random .
The
.Fn crypto_chacha20
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 .. 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
plain text itself.
