.\" 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) 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-2021, 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_ARGON2 3MONOCYPHER
.Os
.Sh NAME
.Nm crypto_argon2
.Nd password-based key derivation
.Sh SYNOPSIS
.In monocypher.h
.Ft void
.Fo crypto_argon2
.Fa "uint8_t *hash"
.Fa "uint32_t hash_size"
.Fa "void *work_area"
.Fa "crypto_argon2_config config"
.Fa "crypto_argon2_inputs inputs"
.Fa "crypto_argon2_extras extras"
.Fc
.Pp
.Fa "extern const crypto_argon2_extras crypto_argon2_no_extras;"
.Sh DESCRIPTION
Argon2 is a resource intensive password-based key derivation scheme
optimised for the typical x86-like processor.
It runs in constant time with respect to the contents of the password.
.Pp
Typical applications are password checking (for online services) and
key derivation (for encryption).
Derived keys can be used to encrypt, for example, private keys or
password databases.
.Pp
The version provided by Monocypher has no threading support, so the
degree of parallelism is limited to 1.
This is considered good enough for most purposes.
.Pp
The arguments to
.Fn crypto_argon2
are:
.Bl -tag -width Ds
.It Fa hash
The output hash.
If all parameters to
.Fn crypto_argon2
are identical between two calls,
then the output
.Fa hash
is also identical.
In other words, all input parameters passed to the function influence
the output value.
.It Fa hash_size
Length of
.Fa hash ,
in bytes.
This argument should be set to 32 or 64 for compatibility with the
.Xr crypto_verify32 3monocypher
or
.Xr crypto_verify64 3monocypher
constant time comparison functions.
.It Fa work_area
Temporary buffer for the algorithm, allocated by the caller.
It must be
.Fa config.nb_blocks
× 1024 bytes big and suitably aligned for 64-bit integers.
If you are not sure how to allocate that buffer, just use
.Xr malloc 3 .
.Pp
The work area is automatically wiped by
.Fn crypto_argon2 .
.It Fa config
A struct of type
.Vt crypto_argon2_config
that determines the base parameters of this particular
instance of Argon2.
These are domain parameters and remain constant between
multiple invocations of
.Fn crypto_argon2 .
.It Fa inputs
A struct of type
.Vt crypto_argon2_inputs
that contains the actual input parameters.
.It Fa extras
A struct of type
.Vt crypto_argon2_extras
that contains optional extra input parameters,
which are not commonly used.
.El
.Pp
The
.Vt crypto_argon2_config
struct is defined as follows:
.Bd -literal -offset indent
typedef struct {
    uint32_t algorithm;
    uint32_t nb_blocks;
    uint32_t nb_passes;
    uint32_t nb_lanes;
} crypto_argon2_config;
.Ed
.Pp
Its members are:
.Bl -tag -width Ds
.It Fa algorithm
This value determines which variant of Argon2 should be used.
.Dv CRYPTO_ARGON2_D
indicates Argon2d,
.Dv CRYPTO_ARGON2_I
indicates Argon2i,
.Dv CRYPTO_ARGON2_ID
indicates Argon2id.
.It Fa nb_blocks
The number of blocks for the work area.
Must be at least 8 ×
.Fa nb_lanes .
A value of 100000 (one hundred megabytes) is a good starting point.
If the computation takes too long, reduce this number.
If it is too fast, increase it.
If it is still too fast with all available memory, increase
.Fa nb_passes .
.It Fa nb_passes
The number of passes.
Must be at least 1.
A value of 3 is
.Em strongly
recommended when using Argon2i;
any value lower than 3 enables significantly more efficient attacks.
.It Fa nb_lanes
The level of parallelism.
Must be at least 1.
Since Monocypher does not support threads,
this does not actually increase the number of threads.
It is only provided for completeness to match the Argon2 specification.
Otherwise, leaving it to 1 is strongly recommended.
.Pp
Users who want to take actual advantage of parallelism should instead
call several instances of Argon2 in parallel.
The
.Fa extras
parameter may be used to differentiate the inputs and produce
independent digests that can be hashed together.
.El
.Pp
The
.Vt crypto_argon2_inputs
struct is defined as follows:
.Bd -literal -offset indent
typedef struct {
    const uint8_t *pass;
    const uint8_t *salt;
    uint32_t pass_size;
    uint32_t salt_size;
} crypto_argon2_inputs;
.Ed
.Pp
Its members are:
.Bl -tag -width Ds
.It Fa pass
The password to hash.
It should be wiped with
.Xr crypto_wipe 3monocypher
after being hashed.
.It Fa pass_size
Length of
.Fa pass ,
in bytes.
.It Fa salt
A password salt.
This should be filled with random bytes, generated separately for each
password to be hashed.
See
.Xr intro 3monocypher
for advice about generating random bytes (use the operating system's
random number generator).
.It Fa salt_size
Length of
.Fa salt ,
in bytes.
Must be at least 8.
16 is recommended.
.El
.Pp
The
.Vt crypto_argon2_extras
struct is defined as follows:
.Bd -literal -offset indent
typedef struct {
    const uint8_t *key;
    const uint8_t *ad;
    uint32_t key_size;
    uint32_t ad_size;
} crypto_argon2_extras;
.Ed
.Pp
Its members are:
.Bl -tag -width Ds
.It Fa key
A key to use in the hash.
May be
.Dv NULL
if
.Fa key_size
is zero.
The key is generally not needed, but it does have some uses.
In the context of password derivation, it would be stored separately
from the password database and would remain secret even if an
attacker were to steal the database.
Note that changing the key requires rehashing the user's password,
which can only be done when the user logs in.
.It Fa key_size
Length of
.Fa key ,
in bytes.
Must be zero if there is no key.
.It Fa ad
Additional data.
May be
.Dv NULL
if
.Fa ad_size
is zero.
This is additional data that goes into the hash, similar to the
authenticated encryption construction in
.Xr crypto_aead_lock 3monocypher .
Can be used to differentiate inputs when invoking several Argon2
instances in parallel:
each instance gets a different thread number as additional data,
generating as many independent digests as we need.
We can then hash those digests with
.Xr crypto_blake2b 3monocypher .
.It Fa ad_size
Length of
.Fa ad ,
in bytes.
Must be zero if there is no additional data.
.El
.Pp
The arguments in the
.Fa config
and
.Fa extras
structs may overlap or point at the same buffer.
.Pp
Use
.Xr crypto_verify16 3monocypher ,
.Xr crypto_verify32 3monocypher ,
or
.Xr crypto_verify64 3monocypher
to compare password hashes to prevent timing attacks.
.Pp
To select the
.Fa nb_blocks
and
.Fa nb_passes
parameters, it should first be decided how long the computation should
take.
For user authentication, values somewhere between half a second
(convenient) and several seconds (paranoid) are recommended.
The computation should use as much memory as can be spared.
.Pp
Since parameter selection depends on your hardware, some trial and error
will be required in order to determine the ideal settings.
Argon2i with three iterations and 100000 blocks
(one hundred megabytes of memory)
is a good starting point.
So is Argon2id with one iteration and 300000 blocks.
Adjust
.Fa nb_blocks
first.
If using all available memory is not slow enough, increase
.Fa nb_passes .
.Sh RETURN VALUES
.Fn crypto_argon2
returns nothing.
.Sh EXAMPLES
The following example assumes 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
This example shows how to hash a password with the recommended baseline
parameters:
.Bd -literal -offset indent
uint8_t              hash[32];               /* Output hash     */
uint8_t              salt[16];               /* Random salt     */
crypto_argon2_config config = {
    .algorithm = CRYPTO_ARGON2_I,            /* Argon2i         */
    .nb_blocks = 100000,                     /* 100 megabytes   */
    .nb_passes = 3,                          /* 3 iterations    */
    .nb_lanes  = 1                           /* Single-threaded */
};
uint8_t password[] = "Okay Password!";
crypto_argon2_inputs inputs = {
    .pass      = password,                   /* User password */
    .salt      = salt,                 /* Salt for the password */
    .pass_size = sizeof(password) - 1,       /* Password length */
    .salt_size = 16
};
crypto_argon2_extras extras = {0};   /* Extra parameters unused */

/* Allocate work area.
 * Note the conversion to size_t.
 * Without it we cannot allocate more than 4GiB.
 */
void *work_area = malloc((size_t)config.nb_blocks * 1024);
if (work_area == NULL) {
    /* Handle malloc() failure */
    /* Wipe secrets if they are no longer needed */
    crypto_wipe(password, sizeof(password));
} else {
    arc4random_buf(salt, 16);
    crypto_argon2(hash, 32, work_area,
                  config, inputs, extras);
    /* Wipe secrets if they are no longer needed */
    crypto_wipe(password, sizeof(password));
    free(work_area);
}


.Ed
.Sh SEE ALSO
.Xr crypto_aead_lock 3monocypher ,
.Xr crypto_verify16 3monocypher ,
.Xr crypto_wipe 3monocypher ,
.Xr intro 3monocypher
.Sh STANDARDS
.Fn crypto_argon2
implements Argon2 as described in RFC 9106,
but does not support actual parallelism.
.Sh HISTORY
In Monocypher 0.1,
.Fn crypto_argon2i
implemented Argon2i and had all extra parameters as input.
It was then split into a
.Fn crypto_argon2i_general
and a simplified
.Fn crypto_argon2i
function in Monocypher 1.1.0.
Both were replaced by
.Fn crypto_argon2
in Monocypher 4.0.0.
.Sh CAVEATS
Monocypher does not perform any input validation.
Any deviation from the algorithm constants,
specified input and output length ranges results
in
.Sy undefined behaviour .
Make sure your inputs are correct.
