/* See LICENSE file for copyright and license details. */ #ifndef LIBKECCAK_H #define LIBKECCAK_H 1 #include #include #include #include #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wdocumentation" # pragma clang diagnostic ignored "-Wunknown-attributes" #endif /** * Only include some C code if compiling with GCC. * * For internal use. */ #ifdef __GNUC__ # define LIBKECCAK_GCC_ONLY(x) x #else # define LIBKECCAK_GCC_ONLY(x) #endif /** * Data structure that describes the parameters * that should be used when hashing */ struct libkeccak_spec { /** * The bitrate */ long int bitrate; /** * The capacity */ long int capacity; /** * The output size */ long int output; }; /** * Data structure that describes the state of a hashing process * * The `char`-size of the output hashsum is calculated by `(.n + 7) / 8` */ struct libkeccak_state { /** * The lanes (state/sponge) */ int64_t S[25]; /** * The bitrate */ long int r; /** * The capacity */ long int c; /** * The output size */ long int n; /** * The state size */ long int b; /** * The word size */ long int w; /** * The word mask */ int64_t wmod; /** * ℓ, the binary logarithm of the word size */ long int l; /** * 12 + 2ℓ, the number of rounds */ long int nr; /** * Pointer for `M` */ size_t mptr; /** * Size of `M` */ size_t mlen; /** * Left over water to fill the sponge with at next update */ unsigned char *M; }; /** * Initialise a state according to hashing specifications * * @param state The state that should be initialised * @param spec The specifications for the state * @return Zero on success, -1 on error */ LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__))) int libkeccak_state_initialise(struct libkeccak_state *, const struct libkeccak_spec *); /** * Reset a state according to hashing specifications * * @param state The state that should be reset */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__))) inline void libkeccak_state_reset(struct libkeccak_state *state) { state->mptr = 0; memset(state->S, 0, sizeof(state->S)); } /** * Release resources allocation for a state without wiping sensitive data * * @param state The state that should be destroyed */ inline void libkeccak_state_fast_destroy(struct libkeccak_state *state) { if (state) { free(state->M); state->M = NULL; } } /** * Wipe data in the state's message wihout freeing any data * * @param state The state that should be wipe */ LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__, __nothrow__, __optimize__("-O0")))) void libkeccak_state_wipe_message(volatile struct libkeccak_state *); /** * Wipe data in the state's sponge wihout freeing any data * * @param state The state that should be wipe */ LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__, __nothrow__, __optimize__("-O0")))) void libkeccak_state_wipe_sponge(volatile struct libkeccak_state *); /** * Wipe sensitive data wihout freeing any data * * @param state The state that should be wipe */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__, __optimize__("-O0")))) void libkeccak_state_wipe(volatile struct libkeccak_state *); /** * Release resources allocation for a state and wipe sensitive data * * @param state The state that should be destroyed */ LIBKECCAK_GCC_ONLY(__attribute__((__optimize__("-O0")))) inline void libkeccak_state_destroy(volatile struct libkeccak_state *state) { if (state) { libkeccak_state_wipe(state); free(state->M); state->M = NULL; } } /** * Wrapper for `libkeccak_state_initialise` that also allocates the states * * @param spec The specifications for the state * @return The state, `NULL` on error */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__, __malloc__))) struct libkeccak_state *libkeccak_state_create(const struct libkeccak_spec *); /** * Wrapper for `libkeccak_state_fast_destroy` that also frees the allocation of the state * * @param state The state that should be freed */ inline void libkeccak_state_fast_free(struct libkeccak_state *state) { libkeccak_state_fast_destroy(state); free(state); } /** * Wrapper for `libkeccak_state_destroy` that also frees the allocation of the state * * @param state The state that should be freed */ LIBKECCAK_GCC_ONLY(__attribute__((__optimize__("-O0")))) inline void libkeccak_state_free(volatile struct libkeccak_state *state) { #ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wcast-qual" #endif libkeccak_state_destroy(state); free((struct libkeccak_state *)state); #ifdef __GNUC__ # pragma GCC diagnostic pop #endif } /** * Make a copy of a state * * @param dest The slot for the duplicate, must not be initialised (memory leak otherwise) * @param src The state to duplicate * @return Zero on success, -1 on error */ LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__))) int libkeccak_state_copy(struct libkeccak_state *restrict, const struct libkeccak_state *restrict); /** * A wrapper for `libkeccak_state_copy` that also allocates the duplicate * * @param src The state to duplicate * @return The duplicate, `NULL` on error */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__, __malloc__))) struct libkeccak_state *libkeccak_state_duplicate(const struct libkeccak_state *); /** * Marshal a `struct libkeccak_state` into a buffer * * @param state The state to marshal * @param data The output buffer, can be `NULL` * @return The number of bytes stored to `data` */ LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__(1), __nothrow__))) size_t libkeccak_state_marshal(const struct libkeccak_state *restrict, void *restrict); /** * Unmarshal a `struct libkeccak_state` from a buffer * * @param state The slot for the unmarshalled state, must not be * initialised (memory leak otherwise), can be `NULL` * @param data The input buffer * @return The number of bytes read from `data`, 0 on error */ LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__(2)))) size_t libkeccak_state_unmarshal(struct libkeccak_state *restrict, const void *restrict); /** * Get the number of bytes that are absorbed during * one pass of the absorption phase * * @param state The hashing state * @return The number of bytes absorbed during one pass */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__, __warn_unused_result__, __pure__))) inline size_t libkeccak_zerocopy_chunksize(struct libkeccak_state *state) { return (size_t)state->r >> 3; } /** * Absorb more of the message to the Keccak sponge * without copying the data to an internal buffer * * It is safe run zero-copy functions before non-zero-copy * functions for the same state, running zero-copy functions * after non-zero-copy functions on the other hand can * cause the message to be misread * * @param state The hashing state * @param msg The partial message * @param msglen The length of the partial message; must be a * multiple of `libkeccak_zerocopy_chunksize(state)` * (undefined behaviour otherwise) */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__))) void libkeccak_zerocopy_update(struct libkeccak_state *restrict, const void *restrict, size_t); /** * Absorb more of the message to the Keccak sponge * without wiping sensitive data when possible * * @param state The hashing state * @param msg The partial message * @param msglen The length of the partial message * @return Zero on success, -1 on error */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__))) int libkeccak_fast_update(struct libkeccak_state *restrict, const void *restrict, size_t); /** * Absorb more of the message to the Keccak sponge * and wipe sensitive data when possible * * @param state The hashing state * @param msg The partial message * @param msglen The length of the partial message * @return Zero on success, -1 on error */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__))) int libkeccak_update(struct libkeccak_state *restrict, const void *restrict, size_t); /** * Absorb the last part of the message and squeeze the Keccak sponge * without copying the data to an internal buffer * * It is safe run zero-copy functions before non-zero-copy * functions for the same state, running zero-copy functions * after non-zero-copy functions on the other hand can * cause the message to be misread * * @param state The hashing state * @param msg The rest of the message; will be edited; extra memory * shall be allocated such that `suffix` and a 10*1 pad (which * is at least 2 bits long) can be added in a why the makes it's * length a multiple of `libkeccak_zerocopy_chunksize(state)` * @param msglen The length of the partial message * @param bits The number of bits at the end of the message not covered by `msglen` * @param suffix The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination * @param hashsum Output parameter for the hashsum, may be `NULL` */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__(1, 2)))) void libkeccak_zerocopy_digest(struct libkeccak_state *restrict, void *restrict, size_t, size_t, const char *restrict, void *restrict); /** * Absorb the last part of the message and squeeze the Keccak sponge * without wiping sensitive data when possible * * @param state The hashing state * @param msg The rest of the message, may be `NULL` * @param msglen The length of the partial message * @param bits The number of bits at the end of the message not covered by `msglen` * @param suffix The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination * @param hashsum Output parameter for the hashsum, may be `NULL` * @return Zero on success, -1 on error */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__(1)))) int libkeccak_fast_digest(struct libkeccak_state *restrict, const void *restrict, size_t, size_t, const char *restrict, void *restrict); /** * Absorb the last part of the message and squeeze the Keccak sponge * and wipe sensitive data when possible * * @param state The hashing state * @param msg The rest of the message, may be `NULL` * @param msglen The length of the partial message * @param bits The number of bits at the end of the message not covered by `msglen` * @param suffix The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination * @param hashsum Output parameter for the hashsum, may be `NULL` * @return Zero on success, -1 on error */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__(1)))) int libkeccak_digest(struct libkeccak_state *restrict, const void *restrict, size_t, size_t, const char *restrict, void *restrict); /** * Force some rounds of Keccak-f * * @param state The hashing state * @param times The number of rounds */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__))) void libkeccak_simple_squeeze(register struct libkeccak_state *, register long int); /** * Squeeze as much as is needed to get a digest a number of times * * @param state The hashing state * @param times The number of digests */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__))) void libkeccak_fast_squeeze(register struct libkeccak_state *, register long int); /** * Squeeze out another digest * * @param state The hashing state * @param hashsum Output parameter for the hashsum */ LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__))) void libkeccak_squeeze(register struct libkeccak_state *restrict, register void *restrict); #include "libkeccak/hmac.h" #include "libkeccak/legacy.h" #include "libkeccak/util.h" #include "libkeccak/keccak.h" #include "libkeccak/sha3.h" #include "libkeccak/rawshake.h" #include "libkeccak/shake.h" #include "libkeccak/cshake.h" #if defined(__clang__) # pragma clang diagnostic pop #endif #endif