aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Makefile8
-rw-r--r--README14
-rw-r--r--libar2.728
-rw-r--r--libar2.h28
-rw-r--r--libar2_decode_base64.3108
-rw-r--r--libar2_decode_params.3194
-rw-r--r--libar2_encode_base64.3103
-rw-r--r--libar2_encode_params.3163
-rw-r--r--libar2_erase.351
-rw-r--r--libar2_hash.3482
-rw-r--r--libar2_latest_argon2_version.336
-rw-r--r--libar2_string_to_type.379
-rw-r--r--libar2_string_to_version.378
-rw-r--r--libar2_type_to_string.382
-rw-r--r--libar2_validate_params.3162
-rw-r--r--libar2_version_to_string.366
-rw-r--r--libar2_version_to_string_proper.358
17 files changed, 1729 insertions, 11 deletions
diff --git a/Makefile b/Makefile
index 346de0e..b7275cd 100644
--- a/Makefile
+++ b/Makefile
@@ -36,6 +36,8 @@ HDR =\
common.h
LOBJ = $(OBJ:.o=.lo)
+MAN3 = $(OBJ:.o=.3)
+MAN7 = libar2.7
all: libar2.a libar2.$(LIBEXT) test
@@ -65,11 +67,15 @@ check: test
install: libar2.a libar2.$(LIBEXT)
mkdir -p -- "$(DESTDIR)$(PREFIX)/lib"
mkdir -p -- "$(DESTDIR)$(PREFIX)/include"
+ mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man3"
+ mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man7"
cp -- libar2.a "$(DESTDIR)$(PREFIX)/lib/"
cp -- libar2.$(LIBEXT) "$(DESTDIR)$(PREFIX)/lib/libar2.$(LIBMINOREXT)"
ln -sf -- libar2.$(LIBMINOREXT) "$(DESTDIR)$(PREFIX)/lib/libar2.$(LIBMAJOREXT)"
ln -sf -- libar2.$(LIBMAJOREXT) "$(DESTDIR)$(PREFIX)/lib/libar2.$(LIBEXT)"
cp -- libar2.h "$(DESTDIR)$(PREFIX)/include/"
+ cp -- $(MAN3) "$(DESTDIR)$(MANPREFIX)/man3/"
+ cp -- $(MAN7) "$(DESTDIR)$(MANPREFIX)/man7/"
uninstall:
-rm -f -- "$(DESTDIR)$(PREFIX)/lib/libar2.a"
@@ -77,6 +83,8 @@ uninstall:
-rm -f -- "$(DESTDIR)$(PREFIX)/lib/libar2.$(LIBMINOREXT)"
-rm -f -- "$(DESTDIR)$(PREFIX)/lib/libar2.$(LIBEXT)"
-rm -f -- "$(DESTDIR)$(PREFIX)/include/libar2.h"
+ -cd -- "$(DESTDIR)$(MANPREFIX)/man3/" && rm -f -- $(MAN3)
+ -cd -- "$(DESTDIR)$(MANPREFIX)/man7/" && rm -f -- $(MAN7)
clean:
-rm -f -- *.o *.a *.lo *.su *.so *.so.* *.dll *.dylib
diff --git a/README b/README
new file mode 100644
index 0000000..0072ebd
--- /dev/null
+++ b/README
@@ -0,0 +1,14 @@
+NAME
+ libar2 - Library for the Argon2-family of hashing functions
+
+DESCRIPTION
+ libar2 is a C library that implements the family of Argon2
+ key derivation function, including Argon2d, Argon2i, and
+ Argon2id, as well as Argon2ds which was not part of the
+ submission to the Password Hashing Competition of 2013,
+ which Argon2 won in 2015. As a key derivation function,
+ Argon2 is well-suited for cryptographically hashing
+ (one-way encrypting) passwords.
+
+SEE ALSO
+ crypt(3)
diff --git a/libar2.7 b/libar2.7
new file mode 100644
index 0000000..7b772be
--- /dev/null
+++ b/libar2.7
@@ -0,0 +1,28 @@
+.TH LIBAR2 7 LIBAR2
+.SH NAME
+libar2 - Library for the Argon2-family of hashing functions
+
+.SH DESCRIPTION
+.BR libar2
+is a C library that implements the family of Argon2
+key derivation function, including Argon2d, Argon2i,
+and Argon2id, as well as Argon2ds which was not part
+of the submission to the Password Hashing Competition
+of 2013, which Argon2 won in 2015. As a key derivation
+function, Argon2 is well-suited for cryptographically
+hashing (one-way encrypting) passwords.
+
+.SH SEE ALSO
+.BR libar2_decode_base64 (3),
+.BR libar2_decode_params (3),
+.BR libar2_encode_base64 (3),
+.BR libar2_encode_params (3),
+.BR libar2_erase (3),
+.BR libar2_hash (3),
+.BR libar2_latest_argon2_version (3),
+.BR libar2_string_to_type (3),
+.BR libar2_string_to_version (3),
+.BR libar2_type_to_string (3),
+.BR libar2_validate_params (3),
+.BR libar2_version_to_string (3),
+.BR libar2_version_to_string_proper (3)
diff --git a/libar2.h b/libar2.h
index dc0e3f3..f4f3412 100644
--- a/libar2.h
+++ b/libar2.h
@@ -12,6 +12,12 @@
/* for internal use { */
+#if defined(__GNUC__)
+# define LIBAR2_NONNULL__(...) __attribute__((nonnull(__VA_ARGS__)))
+#else
+# define LIBAR2_NONNULL__(...)
+#endif
+
#ifndef LIBAR2_PUBLIC__
# if defined(_MSC_VER)
# define LIBAR2_PUBLIC__ __declspec(dllexport)
@@ -119,7 +125,7 @@ enum libar2_argon2_type {
/**
* Secret-dependent hashing
*
- * Only for side-channel-free environment!
+ * Only for side-channel-free environments!
*/
LIBAR2_ARGON2D = 0,
@@ -134,7 +140,7 @@ enum libar2_argon2_type {
/**
* Hybrid construction
*
- * OK against side channels and better with
+ * OK against side-channels and better with
* respect to tradeoff attacks
*/
LIBAR2_ARGON2ID = 2,
@@ -454,7 +460,7 @@ struct libar2_context {
/**
- * The latest versions of Argon2 that is supported
+ * The latest version of Argon2 that is supported
*/
extern const enum libar2_argon2_version libar2_latest_argon2_version;
@@ -477,7 +483,7 @@ const char *libar2_type_to_string(enum libar2_argon2_type type, enum libar2_casi
* @param typep Output parameter for the primitive type
* @return 0 on success, -1 (with `errno` set to EINVAL) if `str` is invalid
*/
-LIBAR2_PUBLIC__
+LIBAR2_PUBLIC__ LIBAR2_NONNULL__(1, 2)
int libar2_string_to_type(const char *str, enum libar2_argon2_type *typep);
/**
@@ -509,7 +515,7 @@ const char *libar2_version_to_string_proper(enum libar2_argon2_version version);
* @param versionp Output parameter for the version number value
* @return 0 on success, -1 (with `errno` set to EINVAL) if `str` is invalid
*/
-LIBAR2_PUBLIC__
+LIBAR2_PUBLIC__ LIBAR2_NONNULL__(1, 2)
int libar2_string_to_version(const char *str, enum libar2_argon2_version *versionp);
/**
@@ -527,7 +533,7 @@ int libar2_string_to_version(const char *str, enum libar2_argon2_version *versio
* @return The number of bytes required for `buf`,
* including the NUL byte added to the end
*/
-LIBAR2_PUBLIC__
+LIBAR2_PUBLIC__ LIBAR2_NONNULL__(2)
size_t libar2_encode_params(char *buf, const struct libar2_argon2_parameters *params);
/**
@@ -578,7 +584,7 @@ size_t libar2_encode_base64(char *buf, const void *data, size_t len);
* a hash, and not just parameters, `&str[return]` will
* point to the hash
*/
-LIBAR2_PUBLIC__
+LIBAR2_PUBLIC__ LIBAR2_NONNULL__(1, 2, 3, 4)
size_t libar2_decode_params(const char *str, struct libar2_argon2_parameters *params, char **bufp, struct libar2_context *ctx);
/**
@@ -589,7 +595,7 @@ size_t libar2_decode_params(const char *str, struct libar2_argon2_parameters *pa
* @param lenp Output parameter for the length of the decoded data
* @return The number of bytes read
*/
-LIBAR2_PUBLIC__
+LIBAR2_PUBLIC__ LIBAR2_NONNULL__(1, 3)
size_t libar2_decode_base64(const char *str, void *data, size_t *lenp);
/**
@@ -599,7 +605,7 @@ size_t libar2_decode_base64(const char *str, void *data, size_t *lenp);
* @param errmsgp Output parameter for the error message, or `null`
* @return The first detected error, or LIBAR2_OK (0) if none
*/
-LIBAR2_PUBLIC__
+LIBAR2_PUBLIC__ LIBAR2_NONNULL__(1)
enum libar2_parameter_error libar2_validate_params(const struct libar2_argon2_parameters *params, const char **errmsgp);
/**
@@ -629,7 +635,7 @@ void libar2_erase(volatile void *mem, size_t size);
* }
*
* It is preferable this check is done by the process that
- * knowns the correct password hash, and that the tryed
+ * knowns the correct password hash, and that the tried
* password is hashed before it is sent to that process
*
* Note that on failure, the function will not necessarily
@@ -645,7 +651,7 @@ void libar2_erase(volatile void *mem, size_t size);
* @param ctx Library settings
* @return 0 on success, -1 on failure
*/
-LIBAR2_PUBLIC__
+LIBAR2_PUBLIC__ LIBAR2_NONNULL__(1, 4, 5)
int libar2_hash(void *hash, void *msg, size_t msglen, struct libar2_argon2_parameters *params, struct libar2_context *ctx);
#if defined(__clang__)
diff --git a/libar2_decode_base64.3 b/libar2_decode_base64.3
new file mode 100644
index 0000000..eb2dad3
--- /dev/null
+++ b/libar2_decode_base64.3
@@ -0,0 +1,108 @@
+.TH LIBAR2_DECODE_BASE64 7 LIBAR2
+.SH NAME
+libar2_decode_base64 - Decode base64-encoded data
+
+.SH SYNOPSIS
+.nf
+#include <libar2.h>
+
+size_t libar2_decode_base64(const char *\fIstr\fP, void *\fIdata\fP, size_t *\fIlenp\fP);
+.fi
+.PP
+Link with
+.IR -lar2 .
+
+.SH DESCRIPTION
+The
+.BR libar2_decode_base64 ()
+function decodes some binary data that has
+been encoded with base64. The base64-encoding
+shall be provided via the
+.I str
+parameter, and is decoded into the
+.I data
+parameter
+(unless
+.I data
+is
+.IR NULL ).
+The length of the decoded data, in bytes,
+is stored in
+.IR *lenp .
+.PP
+.I str
+may, but does not have to, be padded, up to
+(or short there of) the next length that is
+divisible by 4, unless the length is already
+divisible by 4, using equals-sign
+.RB ( = )
+characters.
+.PP
+Decoding stops at the first byte in
+.I str
+that cannot be part of a valid base64-encoding.
+.PP
+.I str
+and
+.I lenp
+may not be
+.IR NULL .
+
+.SH RETURN VALUES
+The
+.BR libar2_decode_base64 ()
+function returns the number of bytes
+successfully decoded from
+.I str
+(that is, the number of bytes read (minus
+any byte determined not to be part of the
+encoded data), not the number of bytes
+stored in
+.IR data ),
+and stores the decoded data in
+.I data
+and the length of the data, after it has
+been decoded, in
+.IR *lenp .
+
+.SH ERRORS
+The
+.BR libar2_decode_base64 ()
+function cannot fail.
+
+.SH EXAMPLES
+The following example demonstrates how to
+decode data from base64 and store it in a
+dynamically allocated buffer.
+.PP
+.nf
+#include <libar2.h>
+#include <stdlib.h>
+
+static char *
+decode_base64(const const *str, char **endp, size_t *lenp)
+{
+ size_t len;
+ size_t n = libar2_decode_base64(str, NULL, &len);
+ char *data = len ? malloc(len) : NULL;
+ if (len && !data) {
+ *endp = NULL;
+ return NULL;
+ }
+ if (libar2_decode_base64(str, data, lenp) != n || *lenp != len)
+ abort();
+ *endp = &str[n];
+ return data;
+}
+.fi
+
+.SH NOTES
+The encoding specified for
+.BR crypt (3)
+is B64, which is similar to, but with significant
+differences from, base64, which is the encoding
+that is standardised for Argon2.
+
+.SH SEE ALSO
+.BR libar2 (7),
+.BR libar2_encode_base64 (3)
diff --git a/libar2_decode_params.3 b/libar2_decode_params.3
new file mode 100644
index 0000000..a6b13f7
--- /dev/null
+++ b/libar2_decode_params.3
@@ -0,0 +1,194 @@
+.TH LIBAR2_DECODE_PARAMS 7 LIBAR2
+.SH NAME
+libar2_decode_params - Decode Argon2 hashing parameters
+
+.SH SYNOPSIS
+.nf
+#include <libar2.h>
+
+enum libar2_argon2_version {
+ LIBAR2_ARGON2_VERSION_10 = 0x10,
+ LIBAR2_ARGON2_VERSION_13 = 0x13
+};
+
+enum libar2_argon2_type {
+ LIBAR2_ARGON2D = 0,
+ LIBAR2_ARGON2I = 1,
+ LIBAR2_ARGON2ID = 2,
+ LIBAR2_ARGON2DS = 4
+};
+
+struct libar2_argon2_parameters {
+ enum libar2_argon2_type \fItype\fP;
+ enum libar2_argon2_version \fIversion\fP;
+ uint_least32_t \fIt_cost\fP;
+ uint_least32_t \fIm_cost\fP;
+ uint_least32_t \fIlanes\fP;
+ unsigned char *\fIsalt\fP;
+ size_t \fIsaltlen\fP;
+ unsigned char *\fIkey\fP;
+ size_t \fIkeylen\fP;
+ unsigned char *\fIad\fP;
+ size_t \fIadlen\fP;
+ size_t \fIhashlen\fP;
+};
+
+struct libar2_context {
+ /* Parts of this struct that are not relevant to \fBlibar2_decode_params\fP() have been omitted. */
+ void *\fIuser_data\fP;
+ void *(*\fIallocate\fP)(size_t \fInum\fP, size_t \fIsize\fP, size_t \fIalignment\fP, struct libar2_context *\fIctx\fP);
+ void (*\fIdeallocate\fP)(void *\fIptr\fP, struct libar2_context *\fIctx\fP);
+};
+
+size_t libar2_decode_params(const char *\fIstr\fP, const struct libar2_argon2_parameters *\fIparams\fP,
+ char **\fIbuf\fP, truct libar2_context *\fIctx\fP);
+.fi
+.PP
+Link with
+.IR -lar2 .
+
+.SH DESCRIPTION
+The
+.BR libar2_decode_params ()
+function decodes a string, provided via the
+.I str
+parameter, that encodes Argon2 hashing parameters,
+and stores the decoded parameters in
+.I param
+and return the number of bytes read from, up to
+but exclude the first byte that was determine not
+to be part of the encoded data. For more
+information about
+.IR param ,
+see
+.BR libar2_hash (3).
+.PP
+The input string,
+.IR str ,
+does not encode the \(dqsecret\(dq (pepper) or
+\(dqassociated data\(dq, therefore these will
+be set to zero-length. The tag (message/password
+hash) length will be inferred from the portion
+of the input string (specifically from the number
+of bytes that make up a valid base64 string) after
+the data that the
+.BR libar2_encode_params (3)
+function encodes,
+.B however
+the number of bytes read from this part of the
+string will not be included in the functions
+return value (the return value marks the end of
+the parameter string, not the hash string which
+also includes the tag).
+.PP
+The
+.BR libar2_decode_params ()
+function may use the
+.I *ctx->allocate
+function to dynamically allocate memory
+and the
+.I *ctx->deallocate
+function to deallocate memory it has
+allocated with
+.IR *ctx->allocate .
+The function may call
+.I *ctx->allocate
+once, and on failure if
+.I *ctx->allocate
+was called,
+.I *ctx->deallocate
+once. If
+.I *ctx->allocatew
+was called, but not
+.IR *ctx->deallocate ,
+the memory allocated with
+.I *ctx->allocate
+will be stored in
+.I *bufp
+and may be deallocated by the user with
+.I *ctx->deallocate
+once the result stored in
+.I params
+is not longer needed.
+See more information about
+.I ctx->allocate
+and
+.IR ctx->deallocate ,
+as well as
+.IR ctx->user_data ,
+see
+.BR libar2_hash (3).
+.PP
+None of the arguments may be
+.IR NULL .
+.PP
+Upon successful completion, if
+.I str
+contains the a tag,
+.IR &str[n] ,
+where
+.I n
+is the return value of the function,
+will point to the beginning of the tag.
+
+.SH RETURN VALUES
+The
+.BR libar2_decode_params ()
+returns the number of bytes in
+.I str
+that make up the decoded parameter, including
+the final dollar-sign
+.RB ( $ ),
+but excluding the tag, if any, at the end of
+the string which is used to infer the tag length,
+and stores the decoded parameters in
+.IR params ,
+and potentially dynamically allocated data in
+.IR *bufp ,
+upon successful completion
+On error, 0 is returned (not a valid return
+value on success completion) and
+.I errno
+is set to describe the error.
+
+.SH ERRORS
+The
+.BR libar2_decode_params ()
+function will fail if:
+.TP
+.B EINVAL
+.I str
+is improperly formatted or contains
+an unrecognised primitive type.
+.TP
+.B ERANGE
+.I str
+contains an integer that is too large to
+be represented by the field in
+.I params
+that it shall be stored in.
+.PP
+The
+.BR libar2_decode_params ()
+function will also fail if the
+.I *ctx->allocate
+function fails, and will, in that case,
+not modify
+.IR errno .
+
+.SH NOTES
+The encoded parameters will not be
+validate by the
+.BR libar2_decode_params ()
+function beyond what is needed to ensure that
+the parameters can be accurately parsed and
+represented. This has to be done using the
+.BR libar2_validate_params (3)
+function.
+
+.SH SEE ALSO
+.BR libar2 (7),
+.BR libar2_validate_params (3),
+.BR libar2_encode_params (3),
+.BR libar2_decode_base64 (3),
+.BR libar2_hash (3)
diff --git a/libar2_encode_base64.3 b/libar2_encode_base64.3
new file mode 100644
index 0000000..bb5b927
--- /dev/null
+++ b/libar2_encode_base64.3
@@ -0,0 +1,103 @@
+.TH LIBAR2_ENCODE_BASE64 7 LIBAR2
+.SH NAME
+libar2_encode_base64 - Encode data to base64
+
+.SH SYNOPSIS
+.nf
+#include <libar2.h>
+
+size_t libar2_encode_base64(char *\fIbuf\fP, const void *\fIdata\fP, size_t \fIlen\fP);
+.fi
+.PP
+Link with
+.IR -lar2 .
+
+.SH DESCRIPTION
+The
+.BR libar2_encode_base64 ()
+function encodes some binary data, provided
+via the
+.I data
+parameter, into base64, and stores the base64
+encoding in
+.I buf
+(unless
+.I buf
+is
+.IR NULL ).
+The number of bytes from
+.I data
+to encode shall be specified in the
+.I len
+parameter.
+.PP
+The encoding of
+.I data
+will
+.B not
+be padded to a length divisble by 4.
+.PP
+.I data
+may only be
+.I NULL
+if
+.I len
+is 0.
+
+.SH RETURN VALUES
+The
+.BR libar2_encode_base64 ()
+function returns the number of bytes required
+to encode the data to base64, plus one extra
+byte for the NUL byte that is added to the to
+terminate the string; that is, the number of
+bytes written to
+.I buf
+or the required allocation size of
+.IR buf .
+If
+.I buf
+is
+.RI non- NULL ,
+a string will be stored in it according to the
+specifications in the
+.B DESCRIPTION
+section.
+
+.SH ERRORS
+The
+.BR libar2_encode_base64 ()
+function cannot fail.
+
+.SH EXAMPLES
+The following example demonstrates how to
+encode data to base64 and store it in a
+dynamically allocated string.
+.PP
+.nf
+#include <libar2.h>
+#include <stdlib.h>
+
+static char *
+encode_base64(const void *data, size_t len)
+{
+ size_t n = libar2_encode_base64(NULL, data, len);
+ char *buf = malloc(n);
+ if (!buf)
+ return NULL;
+ if (libar2_encode_base64(buf, data, len) > n)
+ abort();
+ return buf;
+}
+.fi
+
+.SH NOTES
+The encoding specified for
+.BR crypt (3)
+is B64, which is similar to, but with significant
+differences from, base64, which is the encoding
+that is standardised for Argon2.
+
+.SH SEE ALSO
+.BR libar2 (7),
+.BR libar2_decode_base64 (3)
diff --git a/libar2_encode_params.3 b/libar2_encode_params.3
new file mode 100644
index 0000000..9f654a4
--- /dev/null
+++ b/libar2_encode_params.3
@@ -0,0 +1,163 @@
+.TH LIBAR2_ENCODE_PARAMS 7 LIBAR2
+.SH NAME
+libar2_encode_params - Encode Argon2 hashing parameters
+
+.SH SYNOPSIS
+.nf
+#include <libar2.h>
+
+enum libar2_argon2_version {
+ LIBAR2_ARGON2_VERSION_10 = 0x10,
+ LIBAR2_ARGON2_VERSION_13 = 0x13
+};
+
+enum libar2_argon2_type {
+ LIBAR2_ARGON2D = 0,
+ LIBAR2_ARGON2I = 1,
+ LIBAR2_ARGON2ID = 2,
+ LIBAR2_ARGON2DS = 4
+};
+
+struct libar2_argon2_parameters {
+ enum libar2_argon2_type \fItype\fP;
+ enum libar2_argon2_version \fIversion\fP;
+ uint_least32_t \fIt_cost\fP;
+ uint_least32_t \fIm_cost\fP;
+ uint_least32_t \fIlanes\fP;
+ unsigned char *\fIsalt\fP;
+ size_t \fIsaltlen\fP;
+ unsigned char *\fIkey\fP;
+ size_t \fIkeylen\fP;
+ unsigned char *\fIad\fP;
+ size_t \fIadlen\fP;
+ size_t \fIhashlen\fP;
+};
+
+size_t libar2_encode_params(char *\fIbuf\fP, const struct libar2_argon2_parameters *\fIparams\fP);
+.fi
+.PP
+Link with
+.IR -lar2 .
+
+.SH DESCRIPTION
+The
+.BR libar2_encode_params ()
+function encodes the Argon2 hashing parameters
+provided via the
+.I param
+parameter, as a string, in a standardised format,
+and stores the string in
+.I buf
+(unless
+.I buf
+is
+.IR NULL )
+and return the number of bytes that was (or would
+have been) written to
+.IR buf .
+.PP
+It is recommended that the
+.BR libar2_encode_params ()
+function is called twice: first with
+.I buf
+set to
+.IR NULL ,
+to get how large
+.I buf
+shall be, and then (with the same, unmodified,
+.IR params
+and) with a
+.I buf
+with an allocation size of at least the number
+of bytes that was returned by the function in
+the previous call to it.
+.PP
+The created string will have the following format:
+
+.RS
+.B \(dq$%s$v=%i$m=%lu,t=%lu,p=%lu$%s$\(dq,
+.RI < type >\fB,\fP
+.RI < version >\fB,\fP
+.RI < "memory cost" >\fB,\fP
+.RI < "time cost" >\fB,\fP
+.RI < "parallelism" >\fB,\fP
+.RI < "base64 encoded salt" >
+.RE
+
+The string does not encode the \(dqsecret\(dq
+(pepper), \(dqassociated data\(dq, or the
+\(dqtag\(dq (message hash) length. This string
+is the Argon2 hash string minus the \(dqtag\(dq
+(the hash of the message (the password)), which
+is encoded in base64 and appended to the string
+formatted by this function. For information
+about the expected contents of the
+.I params
+argument, see
+.BR libar2_hash (3).
+.PP
+.I params
+may not be
+.IR NULL .
+
+.SH RETURN VALUES
+The
+.BR libar2_encode_params ()
+function returns the number of bytes required
+to encode the parameter string, plus one extra
+byte for the NUL byte that is added to the to
+terminate the string; that is, the number of
+bytes written to
+.I buf
+or the required allocation size of
+.IR buf .
+If
+.I buf
+is
+.RI non- NULL ,
+a string will be stored in it according to the
+specifications in the
+.B DESCRIPTION
+section.
+
+.SH ERRORS
+The
+.BR libar2_encode_params ()
+function cannot fail.
+
+.SH EXAMPLES
+The following example demonstrates how to
+encode the hashing parameters into a dynamically
+allocated string.
+.PP
+.nf
+#include <libar2.h>
+#include <stdlib.h>
+
+static char *
+encode_params(const struct libar2_argon2_parameters *params)
+{
+ size_t n = libar2_encode_params(NULL, params);
+ char *buf = malloc(n);
+ if (!buf)
+ return NULL;
+ if (libar2_encode_params(buf, params) > n)
+ abort();
+ return buf;
+}
+.fi
+
+.SH NOTES
+The
+.BR libar2_encode_params ()
+function till note validate its input.
+This has to be done using the
+.BR libar2_validate_params (3)
+function.
+
+.SH SEE ALSO
+.BR libar2 (7),
+.BR libar2_validate_params (3),
+.BR libar2_decode_params (3),
+.BR libar2_encode_base64 (3),
+.BR libar2_hash (3)
diff --git a/libar2_erase.3 b/libar2_erase.3
new file mode 100644
index 0000000..53ca375
--- /dev/null
+++ b/libar2_erase.3
@@ -0,0 +1,51 @@
+.TH LIBAR2_ERASE 7 LIBAR2
+.SH NAME
+libar2_erase - Securily erase memory
+
+.SH SYNOPSIS
+.nf
+#include <libar2.h>
+
+void libar2_erase(volatile void *\fImem\fP, size_t \fIsize\fP);
+.fi
+.PP
+Link with
+.IR -lar2 .
+
+.SH DESCRIPTION
+The
+.BR libar2_erase ()
+function writes the number of bytes
+specified in the
+.I size
+parameter to the buffer specified in the
+.I mem
+parameter. Unlike functions like
+.BR bzero (3)
+and
+.BR memset (3),
+the compiler should not be able to optimise
+away a call to the
+.BR libar2_erase ()
+function, even if link-time optimisation
+is enabled, and is thus recommended for
+wiping passwords from memory after they
+have been hashed.
+.PP
+.I mem
+may only be
+.I NULL
+if
+.I size
+is 0.
+
+.SH RETURN VALUES
+None.
+
+.SH ERRORS
+The
+.BR libar2_erase ()
+function cannot fail.
+
+.SH SEE ALSO
+.BR libar2 (7)
diff --git a/libar2_hash.3 b/libar2_hash.3
new file mode 100644
index 0000000..da5af43
--- /dev/null
+++ b/libar2_hash.3
@@ -0,0 +1,482 @@
+.TH LIBAR2_HASH 7 LIBAR2
+.SH NAME
+libar2_hash - Hash a message with Argon2
+
+.SH SYNOPSIS
+.nf
+#include <libar2.h>
+
+enum libar2_argon2_version {
+ LIBAR2_ARGON2_VERSION_10 = 0x10,
+ LIBAR2_ARGON2_VERSION_13 = 0x13
+};
+
+enum libar2_argon2_type {
+ LIBAR2_ARGON2D = 0,
+ LIBAR2_ARGON2I = 1,
+ LIBAR2_ARGON2ID = 2,
+ LIBAR2_ARGON2DS = 4
+};
+
+struct libar2_argon2_parameters {
+ enum libar2_argon2_type \fItype\fP;
+ enum libar2_argon2_version \fIversion\fP;
+ uint_least32_t \fIt_cost\fP;
+ uint_least32_t \fIm_cost\fP;
+ uint_least32_t \fIlanes\fP;
+ unsigned char *\fIsalt\fP;
+ size_t \fIsaltlen\fP;
+ unsigned char *\fIkey\fP;
+ size_t \fIkeylen\fP;
+ unsigned char *\fIad\fP;
+ size_t \fIadlen\fP;
+ size_t \fIhashlen\fP;
+};
+
+struct libar2_context {
+ void *\fIuser_data\fP;
+ unsigned char \fIautoerase_message\fP;
+ unsigned char \fIautoerase_secret\fP;
+ unsigned char \fIautoerase_salt\fP;
+ unsigned char \fIautoerase_associated_data\fP;
+ void *(*\fIallocate\fP)(size_t \fInum\fP, size_t \fIsize\fP, size_t \fIalignment\fP, struct libar2_context *\fIctx\fP);
+ void (*\fIdeallocate\fP)(void *\fIptr\fP, struct libar2_context *\fIctx\fP);
+ int (*\fIinit_thread_pool\fP)(size_t \fIdesired\fP, size_t *\fIcreatedp\fP, struct libar2_context *\fIctx\fP);
+ size_t (*\fIget_ready_threads\fP)(size_t *\fIindices\fP, size_t \fIn\fP, struct libar2_context *\fIctx\fP);
+ int (*\fIrun_thread\fP)(size_t \fIindex\fP, void (*\fIfunction\fP)(void *\fIdata\fP), void *\fIdata\fP, struct libar2_context *\fIctx\fP);
+ int (*\fIjoin_thread_pool\fP)(struct libar2_context *\fIctx\fP);
+ int (*\fIdestroy_thread_pool\fP)(struct libar2_context *\fIctx\fP);
+};
+
+int libar2_hash(void *\fIhash\fP, void *\fImsg\fP, size_t \fImsglen\fP, struct libar2_argon2_parameters *\fIparams\fP, struct libar2_context *\fIctx\fP);
+.fi
+.PP
+Link with
+.I -lar2
+.IR -lblake .
+
+.SH DESCRIPTION
+The
+.BR libar2_hash ()
+function calculates an Argon2 hash of the
+message specified via the
+.I msg
+parameter, whose length is specified in the
+.I msglen
+parameter and in bytes, according to the
+hashing parameters specified via the
+.I params
+parameter. The resulting hash is stored,
+in raw, binary format, in
+.IR hash ,
+which must have an allocation size of at least
+the number of bytes specified by
+.IR params->hashlen .
+The
+.I ctx
+parameter is used to provide memory and thread
+management functions to the
+.BR libar2_hash ()
+function as well as details about what memory
+it may erase when it is no longer needed by
+the function.
+.PP
+.I msglen
+may not be equal to, or greater than,
+2 to the power of 32.
+.PP
+Only the
+.I msg
+argument may be
+.IR NULL ,
+.B but
+only if
+.I msglen
+is 0.
+.PP
+.I msg
+may be read-only if
+.I ctx->autoerase_message
+is 0.
+.PP
+The fields in
+.I params
+and
+.I ctx
+shall be set according to the following specifications:
+.TP
+.B params->type
+Argon2 primitiv type. This shall be one of
+the following values:
+.I LIBAR2_ARGON2D
+(secret-depending hashing: only for
+side-channel-free environments),
+.I LIBAR2_ARGON2I
+(secret-independent hashing; good for environments
+with side-channels but worse wit respect to trade
+of attacks if only one pass is used),
+.I LIBAR2_ARGON2ID
+(hybrid construction; OK against side-channels
+and better with respect to tradeoff attacks),
+.I LIBAR2_ARGON2DS
+(substition box (S-box)-hardened construction;
+.B NB!
+This construction was not included in the
+submission to the Password Hashing Competition).
+.TP
+.B params->version
+Argon2 version number.
+.I LIBAR2_ARGON2_VERSION_10
+for verison 1.0 and
+.I LIBAR2_ARGON2_VERSION_13
+for version 1.3.
+.TP
+.B params->t_cost
+Number of passes, also called time-cost.
+Must be a positive number (not zero)
+less than 2 to the power of 32.
+.TP
+.B params->m_cost
+Amount of required memory, in kilobytes,
+also called memory-cost. Must be at least 8
+but may not be equal to or greater than
+2 to the power of 32, nor may it be a value
+that represents half, or more, of the machine's
+address space (that is, the address space
+divided by 2048).
+.TP
+.B params->lanes
+Number of lines, also called the parallelism
+parameter. Must be a positive (not zero)
+number less than 2 to the power of 24.
+.TP
+.B params->salt
+Salt (a nonce; some random data that is
+unique, or fairly unique, to a specific
+hash). May be read-only if
+.I ctx->autoerase_salt
+is 0.
+.TP
+.B params->saltlen
+The number of bytes stored in
+.IR params->salt .
+Must be at least 8 and less than
+2 to the power of 32.
+.TP
+.B params->key
+Secret (pepper; some random data that is
+unique to the application). May be read-only if
+.I ctx->autoerase_secret
+is 0.
+.TP
+.B params->keylen
+The number of bytes stored in
+.IR params->key .
+Must a non-negative integer and less than
+2 to the power of 32.
+.TP
+.B params->ad
+Arbitrary extra associated data.
+May be read-only if
+.I ctx->autoerase_associated_data
+is 0.
+.TP
+.B params->adlen
+The number of bytes stored in
+.IR params->ad .
+Must a non-negative integer and less than
+2 to the power of 32.
+.TP
+.B params->hashlen
+The tag length (the length of the output
+hash), in bytes. Must be at least 4 and
+less than 2 to the power of 32.
+.TP
+.B ctx->user_data
+User-defined data which may be used by
+callbacks functions provided by the application.
+This field is not used by the libar2 library.
+.TP
+.B ctx->autoerase_message
+Whether
+.I msg
+shall be erased when the function no
+longer needs it. (High recommended for if
+.I msg
+is a password that is only hashed once.)
+Note that there is no guarantee that
+.I msg
+is erased if the function fails
+.TP
+.B ctx->autoerase_secret.
+Whether
+.I params->key
+shall be erased when the function no
+longer needs it. Note that there is no
+guarantee that
+.I params->key
+is erased if the function fails.
+.TP
+.B ctx->autoerase_salt
+Whether
+.I params->salt
+shall be erased when the function no
+longer needs it. Note that there is no
+guarantee that
+.I params->salt
+is erased if the function fails.
+.TP
+.B ctx->autoerase_associated_data
+Whether
+.I params->ad
+shall be erased when the function no
+longer needs it. Note that there is no
+guarantee that
+.I params->ad
+is erased if the function fails.
+.TP
+.B ctx->allocate
+Pointer to a function that the function
+may use to dynamically allocate memory.
+The function shall allocate
+.I num
+times
+.I size
+bytes allocated to a multiple of
+.I alignment
+bytes, and return a pointer to the allocated
+memory; or return
+.I NULL
+on failure. The
+.I ctx
+parameter will be set to struct containing
+the function pointer. It is guaranteed that
+.IR num ,
+.IR size ,
+and
+.IR alignment
+will be positive, and that
+.I alignment
+will be a power of two. It is however not
+guaranteed that
+.I alignment
+is a multiple of
+.IR sizeof(void*) .
+.TP
+.B ctx->deallocate
+Pointer to a function that the function
+may use to deallocate memory that it
+has allocated with
+.IR *ctx->allocate .
+The function shall deallocate
+.IR ptr ,
+which is guaranteed to be
+.RI non- NULL
+and to be allocated using
+.IR *ctx->allocate .
+The
+.I ctx
+parameter will be set to struct containing
+the function pointer.
+
+.B NB!
+The
+.BR libar2_hash ()
+function will not write over memory before
+it deallocates it. This can be done function
+within
+.IR *ctx->allocate
+using the
+.BR libar2_erase (3)
+function.
+.TP
+.B ctx->init_thread_pool
+Pointer to a function that either creates and
+initialises a thread pool or stores 0 in
+.I *createdp
+(recommended if
+.I desired
+is 1).
+.I desired
+will be set to the maximum number of threads the
+.BR libar2_hash ()
+function will be using, meaning that the thread
+pool need not contain more than this number of
+threads, but may contain less if it is deemed
+desirable. the
+.BR libar2_hash ()
+function will not determine what is optimial,
+this is left up to the application to dermine.
+The number of created threads shall be stored in
+.IR *createdp .
+The
+.I ctx
+parameter will be set to struct containing
+the function pointer. The function shall return
+0 on success, and -1 on failure.
+If the function stores 0 in
+.IR *createdp ,
+.IR ctx->get_ready_threads ,
+.IR ctx->run_thread ,
+.IR ctx->join_thread_pool ,
+and
+.IR ctx->destroy_thread_pool
+need note be set.
+.TP
+.B ctx->get_ready_threads
+Pointer to a function that waits until at least one
+thread in the thread pool is ready (may be immediately),
+and stores up to
+.I n
+of their indices (the first thread have index 0) in
+.IR indices .
+The function shall return the number of ready threads.
+It is permissible to return a lesser number as long
+as the returned number is positive and does not exceed
+that number of indices stored in
+.IR indices .
+On failure the function shall return 0. The
+.I ctx
+parameter will be set to struct containing
+the function pointer.
+.TP
+.B ctx->run_thread
+Pointer to a function that makes a thread on the
+thread pool run the function provided in
+.I function
+with the argument provided in
+.IR data .
+.I index
+will be the index of the thread (the first thread
+have index 0) that shall run the function. It will
+be guaranteed by
+.I *ctx->get_ready_threads
+that the thread is resting. The
+.I ctx
+parameter will be set to struct containing
+the function pointer.
+.TP
+.B ctx->join_thread_pool
+Pointer to a function that waits until all
+threads in the thread pool are resting. The
+.I ctx
+parameter will be set to struct containing
+the function pointer. The function shall return
+0 on successful completion and -1 on failure.
+.TP
+.B ctx->destroy_thread_pool
+Pointer to a function that destroys the
+thread pool, and all threads in it. The
+.I ctx
+parameter will be set to struct containing the
+function pointer, and it will be guaranteed
+that all threads in the thread pool are resting.
+It is guaranteed that the function is called
+if and only if
+.I *ctx->init_thread_poolw
+return 0 and stored a non-0 number in its
+.IR *createdp ,
+except if
+.I *ctx->join_thread_pool
+or
+.I *ctx->.get_ready_threads
+failed.
+.PP
+It is safe to assume that
+.I *ctx->allocate
+and
+.I *ctx->deallocate
+are called in stack order and are never
+called from code called using
+.IR *ctx->run_thread ,
+that is, only one thread will be calling
+it from inside the
+.BR libar2_hash ()
+function.
+.PP
+If thread support is desired, but the application
+do not want to keep track of the threads using a
+thread pool, The
+.I *ctx->init_thread_pool
+function must store the provided in its
+.I desired
+parameter to its memory location provided in its
+.I createdp
+parameter. The application must also, in this
+case, make sure that
+.I *ctx->join_thread_pool
+returns after all started threads have stopped,
+and that the
+.I *ctx->get_ready_threads
+function stores unique indices within the range
+0 to the value stored in the
+.I desired
+of the
+.I *ctx->init_thread_pool
+function (exclusive) (start with
+.I i
+set to 0, and each time an index is stored,
+calculate it with
+.IR "(i++ % desired)" .
+Alternatively, and more preferably, this scheme
+can be used, but adapted to limit the number of
+concurrent threads, keeping track of the number
+of running threads, and not let the
+.I *ctx->get_ready_threads
+function return before this number is small
+enough; the value stored in
+.I *createdp
+must however still set to the value provided
+to the
+.I *ctx->init_thread_pool
+function in its
+.I desired
+parametr, so that to threads are not running
+concurrently with the same memory segment as the
+provided argument for the function to run, as
+this could be a source of memory corruption. It
+is however recommended to implement proper thread
+pooling as the library will call
+.I *ctx->run_thread
+.I (4*params->t_cost*params->lanes)
+times.
+
+.SH RETURN VALUES
+The
+.BR libar2_hash ()
+returns 0 and stores the binary hash of the
+message in
+.I hash
+upon successful completion. On error -1
+is returned and
+.I errno
+is set to describe the error. (The function
+may have other side-effects as described in the
+.B DESCRIPTION
+section.)
+
+.SH ERRORS
+The
+.BR libar2_hash ()
+function will fail if:
+.TP
+.B EINVAL
+.I params
+contains invalid parameters or
+.I msglen
+is too large.
+.PP
+The
+.BR libar2_hash ()
+function will also fail if the any
+function provided via
+.I ctx
+fails, and will, in that case, not modify
+.IR errno .
+
+.SH SEE ALSO
+.BR libar2 (7),
+.BR libar2_encode_base64 (3),
+.BR libar2_encode_params (3),
+.BR libar2_decode_params (3),
+.BR libar2_erase (3)
diff --git a/libar2_latest_argon2_version.3 b/libar2_latest_argon2_version.3
new file mode 100644
index 0000000..8a10d47
--- /dev/null
+++ b/libar2_latest_argon2_version.3
@@ -0,0 +1,36 @@
+.TH LIBAR2_LATEST_ARGON2_VERSION 7 LIBAR2
+.SH NAME
+libar2_latest_argon2_version - Highest support version of Argon2
+
+.SH SYNOPSIS
+.nf
+#include <libar2.h>
+
+enum libar2_argon2_version {
+ LIBAR2_ARGON2_VERSION_10 = 0x10,
+ LIBAR2_ARGON2_VERSION_13 = 0x13
+};
+
+extern const enum libar2_argon2_version libar2_latest_argon2_version;
+.fi
+.PP
+Link with
+.IR -lar2 .
+
+.SH DESCRIPTION
+The
+.B libar2_latest_argon2_version
+global, constant variable is set to the latest version of Argon2
+that is supported by the version of the libar2 library linked by
+the application. In the current version of libar2,
+.B libar2_latest_argon2_version
+is set to
+.IR LIBAR2_ARGON2_VERSION_13 ,
+which represents version 1.3, also called version 13, of the
+Argon2 family.
+
+.SH SEE ALSO
+.BR libar2 (7),
+.BR libar2_version_to_string (3),
+.BR libar2_version_to_string_proper (3),
+.BR libar2_string_to_version (3)
diff --git a/libar2_string_to_type.3 b/libar2_string_to_type.3
new file mode 100644
index 0000000..b211c17
--- /dev/null
+++ b/libar2_string_to_type.3
@@ -0,0 +1,79 @@
+.TH LIBAR2_STRING_TO_TYPE 7 LIBAR2
+.SH NAME
+libar2_string_to_type - Convert a string to an Argon2 primitive type value
+
+.SH SYNOPSIS
+.nf
+#include <libar2.h>
+
+enum libar2_argon2_type {
+ LIBAR2_ARGON2D = 0,
+ LIBAR2_ARGON2I = 1,
+ LIBAR2_ARGON2ID = 2,
+ LIBAR2_ARGON2DS = 4
+};
+
+int libar2_string_to_type(const char *\fIstr\fP, enum libar2_argon2_type *\fItypep\fP);
+.fi
+.PP
+Link with
+.IR -lar2 .
+
+.SH DESCRIPTION
+The
+.BR libar2_string_to_type ()
+function converts a string, provided via the
+.I str
+parameter, to a Argon2 primitive type and stores
+the constant that represents that type in
+.IR *typep .
+.PP
+The strings \(dqargon2d\(dq, \(dqargon2i\(dq,
+\(dqargon2id\(dq, and \(dqargon2ds\(dq are the
+currently recognised strings, and are converted to
+.IR LIBAR2_ARGON2D ,
+.IR LIBAR2_ARGON2I ,
+.IR LIBAR2_ARGON2ID ,
+and.
+.IR LIBAR2_ARGON2DS ,
+respectively.
+.PP
+The
+.BR libar2_string_to_type ()
+is case-insensitive and will recognise the
+dollar-sign
+.RB ( $ )
+character, or a NUL byte, as the end of the
+string.
+.PP
+Neither argument may be
+.IR NULL .
+
+.SH RETURN VALUES
+The
+.BR libar2_string_to_type ()
+function returns 0, and sets
+.I *typep
+to the value that
+.I str
+represents, upon successful completion.
+On error, -1 is returned and
+.I errno
+is set to describe the error.
+
+.SH ERRORS
+The
+.BR libar2_string_to_type ()
+function will fail if:
+.TP
+.B EINVAL
+.I str
+does not represent a recognised Argon2 function
+or is not formatted according to the specifications
+in the
+.B DESCRIPTION
+section.
+
+.SH SEE ALSO
+.BR libar2 (7),
+.BR libar2_type_to_string (3)
diff --git a/libar2_string_to_version.3 b/libar2_string_to_version.3
new file mode 100644
index 0000000..d682320
--- /dev/null
+++ b/libar2_string_to_version.3
@@ -0,0 +1,78 @@
+.TH LIBAR2_STRING_TO_VERSION 7 LIBAR2
+.SH NAME
+libar2_string_to_version - Convert a string to an Argon2 version value
+
+.SH SYNOPSIS
+.nf
+#include <libar2.h>
+
+enum libar2_argon2_version {
+ LIBAR2_ARGON2_VERSION_10 = 0x10,
+ LIBAR2_ARGON2_VERSION_13 = 0x13
+};
+
+int libar2_string_to_version(const char *\fIstr\fP, enum libar2_argon2_version *\fIversionp\fP);
+.fi
+.PP
+Link with
+.IR -lar2 .
+
+.SH DESCRIPTION
+The
+.BR libar2_string_to_version ()
+function converts a string, provided via the
+.I str
+parameter, to a version of the Argon2 family and
+stores the constant that represents that version in
+.IR *versionp .
+.PP
+The strings \(dq1.0\(dq and \(dq1.3\(dq, both either
+with or without the dot
+.RB ( . ),
+are the currently recognised strings, and are
+converted to
+.IR LIBAR2_ARGON2_VERSION_10
+and
+.IR LIBAR2_ARGON2_VERSION_13 ,
+respectively.
+.PP
+Neither argument may be
+.IR NULL .
+
+.SH RETURN VALUES
+The
+.BR libar2_string_to_version ()
+function returns 0, and sets
+.I *versionp
+to the value that
+.I str
+represents, upon successful completion.
+On error, -1 is returned and
+.I errno
+is set to describe the error.
+
+.SH ERRORS
+The
+.BR libar2_string_to_version ()
+function will fail if:
+.TP
+.B EINVAL
+.I str
+does not represent a recognised version
+of the Argon2 familly or is not formatted
+according to the specifications in the
+.B DESCRIPTION
+section.
+
+.SH NOTES
+The Argon2 hash string encodes the value of
+.I version
+in decimal, not hexadecimal, meaning that the
+.BR libar2_string_to_version ()
+function cannot be used to decode the hash string.
+
+.SH SEE ALSO
+.BR libar2 (7),
+.BR libar2_version_to_string (3),
+.BR libar2_version_to_string_proper (3),
+.BR libar2_latest_argon2_version (3)
diff --git a/libar2_type_to_string.3 b/libar2_type_to_string.3
new file mode 100644
index 0000000..77408ec
--- /dev/null
+++ b/libar2_type_to_string.3
@@ -0,0 +1,82 @@
+.TH LIBAR2_TYPE_TO_STRING 7 LIBAR2
+.SH NAME
+libar2_type_to_string - Convert an Argon2 primitive type value to a string
+
+.SH SYNOPSIS
+.nf
+#include <libar2.h>
+
+enum libar2_argon2_type {
+ LIBAR2_ARGON2D = 0,
+ LIBAR2_ARGON2I = 1,
+ LIBAR2_ARGON2ID = 2,
+ LIBAR2_ARGON2DS = 4
+};
+
+enum libar2_casing {
+ LIBAR2_LOWER_CASE,
+ LIBAR2_TITLE_CASE,
+ LIBAR2_UPPER_CASE
+};
+
+const char *libar2_type_to_string(enum libar2_argon2_type \fItype\fP, enum libar2_casing \fIcasing\fP);
+.fi
+.PP
+Link with
+.IR -lar2 .
+
+.SH DESCRIPTION
+The
+.BR libar2_type_to_string ()
+function returns a statically allocated string that
+represents the value of the
+.I type
+parameter, which shall represent a primitive type
+of Argon2 (that is, Argon2d, Argon2i, Argon2id, or
+Argon2ds), using the casing specified by the
+.I casing
+parameter.
+.PP
+If the
+.I casing
+parameter is
+.IR LIBAR2_LOWER_CASE ,
+the returned string will be in all lower case,
+that is, for example \(dqargon2d\(dq.
+If the
+.I casing
+parameter is
+.IR LIBAR2_TITLE_CASE ,
+the first character returned string will be in
+upper case, and the rest of the string will be
+in lower case, that is, for example \(dqArgon2d\(dq.
+If the
+.I casing
+parameter is
+.IR LIBAR2_UPPER_CASE ,
+the returned string will be in all upper case,
+that is, for example \(dqARGON2D\(dq.
+
+.SH RETURN VALUES
+The
+.BR libar2_type_to_string ()
+function returns a statically allocated string
+as described in the
+.B DESCRIPTION
+section upon successful completion. On error,
+.I NULL
+is returned and
+.I errno
+is set to describe the error.
+
+.SH ERRORS
+The
+.BR libar2_type_to_string ()
+function will fail if:
+.TP
+.B EINVAL
+Either argument is invalid.
+
+.SH SEE ALSO
+.BR libar2 (7),
+.BR libar2_string_to_type (3)
diff --git a/libar2_validate_params.3 b/libar2_validate_params.3
new file mode 100644
index 0000000..4311274
--- /dev/null
+++ b/libar2_validate_params.3
@@ -0,0 +1,162 @@
+.TH LIBAR2_VALIDATE_PARAMS 7 LIBAR2
+.SH NAME
+libar2_validate_params - Validate Argon2 hashing parameters
+
+.SH SYNOPSIS
+.nf
+#include <libar2.h>
+
+enum libar2_parameter_error {
+ LIBAR2_OK,
+ LIBAR2_T_COST_TOO_SMALL,
+ LIBAR2_T_COST_TOO_LARGE,
+ LIBAR2_M_COST_TOO_SMALL,
+ LIBAR2_M_COST_TOO_LARGE,
+ LIBAR2_TOO_FEW_LANES,
+ LIBAR2_TOO_MANY_LANES,
+ LIBAR2_SALT_TOO_SMALL,
+ LIBAR2_SALT_TOO_LARGE,
+ LIBAR2_KEY_TOO_LARGE,
+ LIBAR2_AD_TOO_LARGE,
+ LIBAR2_HASH_TOO_SMALL,
+ LIBAR2_HASH_TOO_LARGE,
+ LIBAR2_INVALID_TYPE,
+ LIBAR2_INVALID_VERSION
+};
+
+enum libar2_argon2_version {
+ LIBAR2_ARGON2_VERSION_10 = 0x10,
+ LIBAR2_ARGON2_VERSION_13 = 0x13
+};
+
+enum libar2_argon2_type {
+ LIBAR2_ARGON2D = 0,
+ LIBAR2_ARGON2I = 1,
+ LIBAR2_ARGON2ID = 2,
+ LIBAR2_ARGON2DS = 4
+};
+
+struct libar2_argon2_parameters {
+ enum libar2_argon2_type \fItype\fP;
+ enum libar2_argon2_version \fIversion\fP;
+ uint_least32_t \fIt_cost\fP;
+ uint_least32_t \fIm_cost\fP;
+ uint_least32_t \fIlanes\fP;
+ unsigned char *\fIsalt\fP;
+ size_t \fIsaltlen\fP;
+ unsigned char *\fIkey\fP;
+ size_t \fIkeylen\fP;
+ unsigned char *\fIad\fP;
+ size_t \fIadlen\fP;
+ size_t \fIhashlen\fP;
+};
+
+enum libar2_parameter_error libar2_validate_params(const struct libar2_argon2_parameters *\fIparams\fP, const char **\fIerrmsgp\fP);
+.fi
+.PP
+Link with
+.IR -lar2 .
+
+.SH DESCRIPTION
+The
+.BR libar2_validate_params ()
+function checks that the hashing parameters
+provided in the
+.I params
+parameters are valid and can be used for
+hashing by the libar2 library. An error
+description will be stored in
+.I *errmsgp
+unless
+.I errmsgp
+is
+.IR NULL .
+.PP
+Only the first discovered invalid data
+will be described.
+.PP
+.I params
+may not be
+.IR NULL .
+
+.SH RETURN VALUES
+The
+.BR libar2_validate_params ()
+function returns
+.I LIBAR2_OK
+(which has the value 0) and stores the
+statically allocated string
+.B \(dqOK\(dq
+in
+.I *errmsgp
+(unless
+.I errmsgp
+is
+.IR NULL )
+if the input is valid. If the input is
+invalid, an error code (with a positive
+value) will returned and description of
+what is incorrect is stored in
+.I *errmsgp
+(unless
+.I errmsgp
+is
+.IR NULL ).
+The return values that indicate invalid
+input, in the current version of the
+function are:
+.TP
+.B LIBAR2_T_COST_TOO_SMALL
+The time-cost parameter is too small.
+.TP
+.B LIBAR2_T_COST_TOO_LARGE
+The time-cost parameter is too large.
+.TP
+.B LIBAR2_M_COST_TOO_SMALL
+The memory-cost parameter is too small.
+.TP
+.B LIBAR2_M_COST_TOO_LARGE
+The memory-cost parameter is too large.
+.TP
+.B LIBAR2_TOO_FEW_LANES
+The lane-count parameter is too small.
+.TP
+.B LIBAR2_TOO_MANY_LANES
+The lane-count parameter is too large
+.TP
+.B LIBAR2_SALT_TOO_SMALL
+The salt parameter is too small.
+.TP
+.B LIBAR2_SALT_TOO_LARGE
+The salt parameter is too large.
+.TP
+.B LIBAR2_KEY_TOO_LARGE
+The secret (pepper) parameter is too large.
+.TP
+.B LIBAR2_AD_TOO_LARGE
+The associated data parameter is too large.
+.TP
+.B LIBAR2_HASH_TOO_SMALL
+The tag length is too small.
+.TP
+.B LIBAR2_HASH_TOO_LARGE
+The tag length is too large.
+.TP
+.B LIBAR2_INVALID_TYPE
+The primitive type parameter is not supported
+by the linked version of the libar2 library.
+.TP
+.B LIBAR2_INVALID_VERSION
+The Argon2 version parameter is not supported
+by the linked version of the libar2 library.
+
+.SH ERRORS
+The
+.BR libar2_validate_params ()
+function cannot fail.
+
+.SH SEE ALSO
+.BR libar2 (7),
+.BR libar2_encode_params (3),
+.BR libar2_decode_params (3),
+.BR libar2_hash (3)
diff --git a/libar2_version_to_string.3 b/libar2_version_to_string.3
new file mode 100644
index 0000000..a20d83e
--- /dev/null
+++ b/libar2_version_to_string.3
@@ -0,0 +1,66 @@
+.TH LIBAR2_VERSION_TO_STRING 7 LIBAR2
+.SH NAME
+libar2_version_to_string - Convert an Argon2 version number to a string without a dot
+
+.SH SYNOPSIS
+.nf
+#include <libar2.h>
+
+enum libar2_argon2_version {
+ LIBAR2_ARGON2_VERSION_10 = 0x10,
+ LIBAR2_ARGON2_VERSION_13 = 0x13
+};
+
+const char *libar2_version_to_string(enum libar2_argon2_version \fIversion\fP);
+.fi
+.PP
+Link with
+.IR -lar2 .
+
+.SH DESCRIPTION
+The
+.BR libar2_version_to_string ()
+function returns a statically allocated string that
+represents the value of the
+.I version
+parameter, which shall represent a version of the
+Argon2 family. The returned string will not contain
+a dot
+.RB ( . ),
+meaning it will be formatted in hexadecimal without
+a base-prefix; for example \(dq13\(dq for
+.IR LIBAR2_ARGON2_VERSION_13 .
+
+.SH RETURN VALUES
+The
+.BR libar2_version_to_string ()
+function returns a statically allocated string
+as described in the
+.B DESCRIPTION
+section upon successful completion. On error,
+.I NULL
+is returned and
+.I errno
+is set to describe the error.
+
+.SH ERRORS
+The
+.BR libar2_version_to_string ()
+function will fail if:
+.TP
+.B EINVAL
+.I version
+is not a supported version of Argon2.
+
+.SH NOTES
+The Argon2 hash string encodes the value of
+.I version
+in decimal, not hexadecimal, meaning that the
+.BR libar2_version_to_string ()
+function cannot be used to create the hash string.
+
+.SH SEE ALSO
+.BR libar2 (7),
+.BR libar2_version_to_string_proper (3),
+.BR libar2_string_to_version (3),
+.BR libar2_latest_argon2_version (3)
diff --git a/libar2_version_to_string_proper.3 b/libar2_version_to_string_proper.3
new file mode 100644
index 0000000..4d7d115
--- /dev/null
+++ b/libar2_version_to_string_proper.3
@@ -0,0 +1,58 @@
+.TH LIBAR2_VERSION_TO_STRING_PROPER 7 LIBAR2
+.SH NAME
+libar2_version_to_string_proper - Convert an Argon2 version number to a string with a dot
+
+.SH SYNOPSIS
+.nf
+#include <libar2.h>
+
+enum libar2_argon2_version {
+ LIBAR2_ARGON2_VERSION_10 = 0x10,
+ LIBAR2_ARGON2_VERSION_13 = 0x13
+};
+
+const char *libar2_version_to_string_proper(enum libar2_argon2_version \fIversion\fP);
+.fi
+.PP
+Link with
+.IR -lar2 .
+
+.SH DESCRIPTION
+The
+.BR libar2_version_to_string_proper ()
+function returns a statically allocated string that
+represents the value of the
+.I version
+parameter, which shall represent a version of the
+Argon2 family. The returned string will contain
+a dot
+.RB ( . );
+for example \(dq1.3\(dq for
+.IR LIBAR2_ARGON2_VERSION_13 .
+
+.SH RETURN VALUES
+The
+.BR libar2_version_to_string_proper ()
+function returns a statically allocated string
+as described in the
+.B DESCRIPTION
+section upon successful completion. On error,
+.I NULL
+is returned and
+.I errno
+is set to describe the error.
+
+.SH ERRORS
+The
+.BR libar2_version_to_string_proper ()
+function will fail if:
+.TP
+.B EINVAL
+.I version
+is not a supported version of Argon2.
+
+.SH SEE ALSO
+.BR libar2 (7),
+.BR libar2_version_to_string (3),
+.BR libar2_string_to_version (3),
+.BR libar2_latest_argon2_version (3)