/* See LICENSE file for copyright and license details. */ #ifndef LIBSHA2_H #define LIBSHA2_H 1 #include #include /** * Algorithms supported by libsha2 */ enum libsha2_algorithm { /** * SHA-224, outputs 28 bytes */ LIBSHA2_224, /** * SHA-256, outputs 32 bytes */ LIBSHA2_256, /** * SHA-384, outputs 48 bytes */ LIBSHA2_384, /** * SHA-512, outputs 64 bytes */ LIBSHA2_512, /** * SHA-512/224, outputs 28 bytes */ LIBSHA2_512_224, /** * SHA-512/256, outputs 32 bytes */ LIBSHA2_512_256 }; /** * Data structure that describes the state of a hashing process * * Data that could just as well be allocated (with `auto`) are * allocated here so that is is easier to wipe the data without * exposing two versions of each function: one to wipe data, * and one not to wipe data to gain speed, now you can use use * `explicit_bzero` (or `memset`) when you are done. * * This data structure is flat (it contains dynamic pointers) * and can be marshalled and unmarshalled naïvely, and does * not need destroyed; however, if you when to marshall it * using as little memory as possible, this are comments * about data that does not need to be mashalled */ struct libsha2_state { /** * The size of the message, as far as processed, in bits; */ size_t message_size; /** * Round constants */ union { /** * For 32-bit algorithms */ uint32_t b32[64]; /** * For 64-bit algorithms */ uint64_t b64[80]; } k; /** * Words * * Does not need to be marshalled */ union { /** * For 32-bit algorithms */ uint32_t b32[64]; /** * For 64-bit algorithms */ uint64_t b64[80]; } w; /** * Hashing values */ union { /** * For 32-bit algorithms */ uint32_t b32[8]; /** * For 64-bit algorithms */ uint64_t b64[8]; } h; /** * Temporary hashing values * * Does not need to be marshalled */ union { /** * For 32-bit algorithms */ uint32_t b32[8]; /** * For 64-bit algorithms */ uint64_t b64[8]; } work_h; /** * Space for chunks to process, limited * to 64 bytes on 32-bit algorithms */ unsigned char chunk[128]; /** * Space for storing the last bits and * the padding * * Does not need to be marshalled */ char appendix[256]; /** * The size of the chunks, in bytes */ size_t chunk_size; /** * The algorithm that is used */ enum libsha2_algorithm algorithm; int __padding1; }; /** * Initialise a state * * @parma state The state that should be initialised * @parma algorithm The hashing algorithm * @return Zero on success, -1 on error */ #if defined(__GNUC__) __attribute__((__leaf__, __nothrow__, __nonnull__)) #endif int libsha2_init(struct libsha2_state *restrict, enum libsha2_algorithm); /** * Get the output size of the algorithm specified for a state * * @parma state The state * @return The number of bytes in the output, zero on error */ #if defined(__GNUC__) __attribute__((__nothrow__, __nonnull__, __pure__)) #endif size_t libsha2_state_output_size(const struct libsha2_state *restrict); /** * Get the output size of an algorithm * * @parma algorithm The hashing algorithm * @return The number of bytes in the output, zero on error */ #if defined(__GNUC__) __attribute__((__leaf__, __nothrow__, __const__)) #endif size_t libsha2_algorithm_output_size(enum libsha2_algorithm); /** * Absorb more of the message * * @param state The hashing state * @param message The message, in bits, must be equivalent to 0 modulus 8 * @param msglen The length of the message */ #if defined(__GNUC__) __attribute__((__nonnull__, __nothrow__)) #endif void libsha2_update(struct libsha2_state *restrict, const char *restrict, size_t); /** * Absorb the last part of the message and output a hash * * @param state The hashing state * @param message The message, in bits * @param msglen The length of the message, zero if there is nothing more to absorb * @param output The output buffer for the hash */ #if defined(__GNUC__) __attribute__((__nonnull__(1, 4), __nothrow__)) #endif void libsha2_digest(struct libsha2_state *restrict, const char *restrict, size_t, char *); /** * Calculate the checksum for a file, * the content of the file is assumed non-sensitive * * @param fd The file descriptor of the file * @param algorithm The hashing algorithm * @param hashsum Output buffer for the hash * @return Zero on success, -1 on error */ #if defined(__GNUC__) __attribute__((__nonnull__, __leaf__)) #endif int libsha2_sum_fd(int, enum libsha2_algorithm, char *restrict); /** * Convert a binary hashsum to lower case hexadecimal representation * * @param output Output array, should have an allocation size of at least `2 * n + 1` * @param hashsum The hashsum to convert * @param n The size of `hashsum` */ #if defined(__GNUC__) __attribute__((__leaf__, __nonnull__, __nothrow__)) #endif void libsha2_behex_lower(char *restrict, const char *restrict, size_t); /** * Convert a binary hashsum to upper case hexadecimal representation * * @param output Output array, should have an allocation size of at least `2 * n + 1` * @param hashsum The hashsum to convert * @param n The size of `hashsum` */ #if defined(__GNUC__) __attribute__((__leaf__, __nonnull__, __nothrow__)) #endif void libsha2_behex_upper(char *restrict, const char *restrict, size_t); /** * Convert a hexadecimal hashsum (both lower case, upper * case and mixed is supported) to binary representation * * @param output Output array, should have an allocation * size of at least `strlen(hashsum) / 2` * @param hashsum The hashsum to convert */ #if defined(__GNUC__) __attribute__((__leaf__, __nonnull__, __nothrow__)) #endif void libsha2_unhex(char *restrict, const char *restrict); #endif