aboutsummaryrefslogtreecommitdiffstats
path: root/common.h
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2026-05-21 17:12:20 +0200
committerMattias Andrée <m@maandree.se>2026-05-21 17:12:20 +0200
commitb29f4153e83623f24bebe99976e1368ef31bb008 (patch)
tree65473709df1194a2f9277dc5fb47add5e41430c0 /common.h
parentAdd (so far untested and undocument) support for pepper (diff)
downloadlibrecrypt-b29f4153e83623f24bebe99976e1368ef31bb008.tar.gz
librecrypt-b29f4153e83623f24bebe99976e1368ef31bb008.tar.bz2
librecrypt-b29f4153e83623f24bebe99976e1368ef31bb008.tar.xz
Add support for custom hash functions
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to 'common.h')
-rw-r--r--common.h246
1 files changed, 11 insertions, 235 deletions
diff --git a/common.h b/common.h
index b329fca..e020e11 100644
--- a/common.h
+++ b/common.h
@@ -9,6 +9,7 @@
# pragma clang diagnostic ignored "-Wimplicit-void-ptr-cast" /* C++ warning, and we are in internal files */
# pragma clang diagnostic ignored "-Wc++-keyword" /* C++ warning, and we are in internal files */
# pragma clang diagnostic ignored "-Wc++-unterminated-string-initialization" /* Stupid C++ warning, and we are in internal files */
+# pragma clang diagnostic ignored "-Wcovered-switch-default" /* harmful warning */
#endif
#if defined(__GNUC__)
# pragma GCC diagnostic ignored "-Winline"
@@ -134,185 +135,24 @@ struct librecrypt_context {
void *user_data;
/**
- * Per hash algorithm peppers
- */
- struct pepper peppers[LIBRECRYPT_HASH_ALGORITHM_END];
- /* TODO we probably don't want slots allocated for
- * algorithms that have been disabled */
-};
-
-
-/**
- * Hash algorithm information and implementation
- *
- * Current limitations:
- *
- * - The algorithm must not use the '*' symbol except
- * in the way the librecrypt library uses '*' for
- * specifying sizes, in bytes (after base64-decoding),
- * of randomised data (salt) and the hash result
- *
- * - The algorithm must not use the '>' symbol
- *
- * - The hash must be att the end, immediately after
- * the last '$' (some expections exists for legacy
- * hash algorithms), and empty must be usable to
- * specify default hash size
- *
- * - Salts and hashes must be encoded in some variant
- * of base64 where the bytes (represented with the
- * most significant bit first) a₇a₆a₅a₄a₃a₂a₁a₀,
- * b₇b₆b₅b₄b₃b₂b₁b₀, and c₇c₆c₅c₄c₃c₂c₁c₀ are
- * rearranged to a₇a₆a₅a₄a₃a₂, a₁a₀b₇b₆b₅b₄,
- * b₃b₂b₁b₀c₇c₆, c₅c₄c₃c₂c₁c₀, and missing bits
- * are set to 0; and padding if supported at all,
- * is only allowed, up to 3 pad letters, at the
- * end to pad the output to a multiple of 4 letters
- */
-struct librecrypt_algorithm {
- /**
- * Determine if a password hash string
- * selects the algorithm
- *
- * @param settings The password hash string, containing a single algorithm
- * @param len The number of bytes in `settings`
- * @return A positive value if the string matches the algorithm,
- * 0 otherwise
- *
- * If non-zero is returned for multiple algorithm,
- * the first with the highest value wins
- *
- * This function shall be MT-Safe and AS-Safe
- */
- unsigned (*is_algorithm)(const char *settings, size_t len);
-
- /**
- * Implements `librecrypt_hash_binary` for a single hash algorithm;
- * see `librecrypt_hash_binary` for more information
- *
- * @param out_buffer See `librecrypt_hash_binary`
- * @param size See `librecrypt_hash_binary`
- * @param phrase See `librecrypt_hash_binary`; may be `NULL`
- * even if `len` is positive, this happens when
- * `size` is too small and the hash result will
- * not be included, so there is no need to actually
- * calculate the hash, however `len` and `settings`
- * should still be checked
- * @param len See `librecrypt_hash_binary`
- * @param settings See `librecrypt_hash_binary`,
- * will not contains asterisk-encoding
- * @param prefix The length of `settings`, in bytes
- * @param ctx See `librecrypt_hash_binary`
- * @return 0 on success, -1 on failure
- * @throws See `librecrypt_hash_binary`
- *
- * This function shall be MT-Safe but may be AS-Unsafe
+ * Application-provided hash function implementations
*/
- int (*hash)(char *restrict out_buffer, size_t size, const char *phrase, size_t len,
- const char *settings, size_t prefix, LIBRECRYPT_CONTEXT *ctx);
+ const struct librecrypt_algorithm *algos;
/**
- * Check whether the hash algorithm is supported for given
- * configuration and input
- *
- * @param phrase The password to hash, may contain NUL bytes;
- * may be `NULL` even if `len` is non-zero
- * @param len The number of bytes in `phrase`, if `phrase` is `NULL`,
- * the function will check that the specified number of
- * bytes is supported as well as any byte sequence unless
- * `text` is non-zero
- * @param text Assume the password is valid UTF-8 text (without NUL bytes)
- * iff non-zero; ignored if `phrase` is non-`NULL`
- * @param settings The password hash string; it is allowed for algorithm
- * tuning parameters, and the hash result, to be omitted
- * @param prefix The number of bytes in `settings`
- * @param len_out Output parameter for the binary hash size, in bytes
- * @return 1 if the configuration is supported and correctly
- * configured, 0 otherwise
- *
- * This function shall be MT-Safe and AS-Safe
- */
- int (*test_supported)(const char *phrase, size_t len, int text, const char *settings,
- size_t prefix, size_t *len_out);
-
- /**
- * See `librecrypt_make_settings`
- *
- * @param out_buffer See `librecrypt_make_settings`
- * @param size See `librecrypt_make_settings`
- * @param algorithm See `librecrypt_make_settings`,
- * will match the algorithm or be `NULL`
- * @param memcost See `librecrypt_make_settings`
- * @param timecost See `librecrypt_make_settings`
- * @param gensalt See `librecrypt_make_settings`
- * @param rng See `librecrypt_make_settings`,
- * except the function will not be called
- * with `rng` set to `NULL`
- * @param user See `librecrypt_make_settings`
- * @return See `librecrypt_make_settings`
- * @throws See `librecrypt_make_settings`
- *
- * This function shall be MT-Safe but may be AS-Safe
+ * The number of elements in `.algos`
*/
- ssize_t (*make_settings)(char *out_buffer, size_t size, const char *algorithm,
- size_t memcost, uintmax_t timecost, int gensalt,
- ssize_t (*rng)(void *out, size_t n, void *user), void *user);
+ size_t nalgos;
/**
- * Expected argument for the `lut` parameter
- * of the `librecrypt_encode` function
- *
- * This shall repeat a 64 character ASCII
- * alphabet 4 times
- */
- const char *encoding_lut;
-
- /**
- * Expected argument for the `lut` parameter
- * of the `librecrypt_decode` function
- *
- * This shall unique map the letters in
- * `.encoding_lut` to there initial position
- * in `.encoding_lut` (that's, uniquely to
- * the range [0, 63]). All other bytes
- * (including `.pad`) shall map to `0xFFu`
- */
- const unsigned char *decoding_lut;
-
- /**
- * The algoritm's hash result size, in number
- * of bytes when using binary encoding
- */
- size_t hash_size;
-
- /**
- * 1 if `.hash_size` is just a default,
- * 0 if `.hash_size` is always used
- */
- signed char flexible_hash_size;
-
- /**
- * Expected argument for the `strict_pad` parameter
- * of the `librecrypt_decode` function
- *
- * Shall be either 1 (always pad when encoding,
- * and require padding when decoding) or 0
- * (do not pad when encoding, but allow padding
- * (provided that `.pad != 0`) when decoding)
- */
- signed char strict_pad;
-
- /**
- * Expected argument for the `pad` parameter
- * of the `librecrypt_decode` function
- *
- * The pad character, used to pad base64-encoding
- * to a multiple of 4 letters, shall be `'\0'` if
- * not specified
+ * Per hash algorithm peppers
*/
- char pad;
+ struct pepper peppers[LIBRECRYPT_HASH_ALGORITHM_END];
+ /* TODO we probably don't want slots allocated for
+ * algorithms that have been disabled */
};
+
/**
* Check if an `struct algorithm *` is the `END_OF_ALGORITHMS`
* at the end of `librecrypt_algorithms_`
@@ -499,71 +339,7 @@ const struct librecrypt_algorithm *librecrypt_find_first_algorithm_(const char *
* for the hash algorithm `algo`
*/
LIBRECRYPT_NONNULL_1__
-struct pepper *librecrypt_context_get_pepper_(LIBRECRYPT_CONTEXT *ctx, enum librecrypt_hash_algorithm algo, size_t len);
-
-
-/**
- * Function used to validate a password hash string
- *
- * @param settings The string to validate
- * @param len The number of bytes in `settings`
- * @param fmt The expected format of the string, it may contain
- * the metacharacter '%' (`fmt` is parsed left to right)
- * to perform special string content checks:
- * "%%" - Literal '%'
- * "%*" - Any sequence of non-'$' bytes (greedly matched)
- * "%s" - String
- * "%u" - Unsigned integer that may start with a leading zeroes
- * "%p" - Unsigned integer that most not start with a leading zeroes
- * "%b" - Binary data, either encoded to ASCII or ungenerated content
- * that is length specified using asterisk-notation
- * "%h" - Same as "%b", except empty content as always allowed unless
- * asterisk-notation is used
- * "%^s" - Same as "%s" except with output argument
- * "%^u" - Same as "%u" except with output argument
- * "%^p" - Same as "%p" except with output argument
- * "%^b" - Same as "%b" except with one output argument: length
- * "%&b" - Same as "%b" except with two output argument:
- * pointer to text, text length, or NULL and binary length
- * "%^h" - Same as "%h" except with one output argument: length
- * "%&h" - Same as "%h" except with two output argument:
- * pointer to text, text length, or NULL and binary length
- * @param ... Arguments for each use of '%' in `fmt`:
- * "%%" - None
- * "%*" - None
- * "%s" - At least one `const char *`: allowed matches (in order of preference),
- * followed by a `NULL`
- * "%u" - Two `uintmax_t`: the minimum value and the maximum value
- * "%p" - Same as "%u"
- * "%b" - Two `uintmax_t`: the minimum value and the maximum value,
- * one `const unsigned char dlut[static 256]`: the ASCII-encoding decoding table,
- * one `char`: the padding character or `'\0'` if none may be used, and
- * one `int`: whether padding must always be used unless the previous argument is `'\0'`
- * "%h" - Same as "%b"
- * "%^s" - Same as "%s" but with an additional argument, as the first one:
- * a `const char **` used to store the matched string
- * "%^u" - Same as "%u" but with an additional argument, as the first one:
- * a `uintmax_t *` used to store the encoded integer
- * "%^p" - Same as "%p" but with an additional argument, as the first one:
- * a `uintmax_t *` used to store the encoded integer
- * "%^b" - Same as "%b" but with an additional argument, as the first one:
- * a `uintmax_t *` used to store the number of encoded bytes or
- * the encoded integer after the asterisk if asterisk-encoding is used
- * "%&b" - Same as "%b" but with two additional arguments, as the first two:
- * a `const char **` and a `uintmax_t *`: if asterisk-notation is used
- * the `const char *` will be set to `NULL` and the `uintmax_t` will be
- * set to the encoded number, othererwise the `const char *` will be
- * set to point to the position in `settings` where the base-64 encoded
- * text begins and the `uintmax_t` will be set to length of the text
- * (as encoded in base-64, _not_ as decoded to binary)
- * "%^h" - Same as "%^b"
- * "%&h" - Same as "%&b"
- * @return 1 if `string` matches `fmt`, 0 otherwise
- *
- * This function will call abort(3) if misused.
- */
-LIBRECRYPT_READ_MEM__(1, 2) LIBRECRYPT_NONNULL_I__(3) LIBRECRYPT_WUR__ HIDDEN
-int librecrypt_scan_settings_(const char *settings, size_t len, const char *fmt, ...);
+struct pepper *librecrypt_get_pepper_(LIBRECRYPT_CONTEXT *ctx, enum librecrypt_hash_algorithm algo, size_t len);