/* See LICENSE file for copyright and license details. */ #ifndef LIBHASHSUM_H #define LIBHASHSUM_H #include #include #if defined(__GNUC__) # define LIBHASHSUM_USERET_ __attribute__((__warn_unused_result__)) # define LIBHASHSUM_1_NONNULL_ __attribute__((__nonnull__(1))) #else # define LIBHASHSUM_USERET_ # define LIBHASHSUM_1_NONNULL_ #endif /** * Hashing algorithm */ enum libhashsum_algorithm { LIBHASHSUM_MD2, /**< MD2 */ LIBHASHSUM_MD4, /**< MD4 */ LIBHASHSUM_MD5, /**< MD5 */ LIBHASHSUM_RIPEMD_128, /**< RIPEMD-128 */ LIBHASHSUM_RIPEMD_160, /**< RIPEMD-160 */ LIBHASHSUM_RIPEMD_256, /**< RIPEMD-256 */ LIBHASHSUM_RIPEMD_320 /**< RIPEMD-320 */ }; /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_MD2` */ #define LIBHASHSUM_MD2_HASH_SIZE 16 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_MD4` */ #define LIBHASHSUM_MD4_HASH_SIZE 16 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_MD5` */ #define LIBHASHSUM_MD5_HASH_SIZE 16 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RIPEMD_128` */ #define LIBHASHSUM_RIPEMD_128_HASH_SIZE 16 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RIPEMD_160` */ #define LIBHASHSUM_RIPEMD_160_HASH_SIZE 20 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RIPEMD_256` */ #define LIBHASHSUM_RIPEMD_256_HASH_SIZE 32 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RIPEMD_320` */ #define LIBHASHSUM_RIPEMD_320_HASH_SIZE 40 /** * Hash state * * For internal use */ union libhashsum_state { struct { unsigned char x[32]; unsigned char mp[16]; unsigned char mz[16]; unsigned char sum[16]; unsigned t; } md2; struct { union { uint32_t h32[4]; uint8_t sum[16]; } h; union { uint32_t m32[16]; uint8_t m8[64]; } m; uint64_t count; } md4; struct { union { uint32_t h32[4]; uint8_t sum[16]; } h; uint8_t m[64]; uint32_t w[16]; uint64_t count; } md5; struct { union { uint32_t h32[4]; uint8_t sum[16]; } h; union { uint32_t m32[16]; uint8_t m8[64]; } m; uint64_t count; } ripemd_128; struct { union { uint32_t h32[5]; uint8_t sum[20]; } h; union { uint32_t m32[16]; uint8_t m8[64]; } m; uint32_t w1[5]; uint32_t w2[5]; uint64_t count; } ripemd_160; struct { union { uint32_t h32[8]; uint8_t sum[32]; } h; union { uint32_t m32[16]; uint8_t m8[64]; } m; uint64_t count; } ripemd_256; struct { union { uint32_t h32[10]; uint8_t sum[40]; } h; union { uint32_t m32[16]; uint8_t m8[64]; } m; uint32_t w1[5]; uint32_t w2[5]; uint64_t count; } ripemd_320; }; /** * Message hash functions and state */ struct libhashsum_hasher { /** * The used hash algorithm */ enum libhashsum_algorithm algorithm; /** * The number of bytes required for each * call to `.process_block` */ size_t input_block_size; /** * The number of bytes in the resulting hash */ size_t hash_size; /** * The hash * * This will be set to `NULL` when the structure * is initialised, but will be set to a pointer * to a buffer inside `.state` once `.finalise_const` * or `.finalise` has been called */ unsigned char *hash_output; /** * Whether the algorithm supports non-whole octet input */ unsigned char supports_non_whole_bytes; /** * Update the hash state given additional * input data * * @param this The object containing this function pointer * @param data The new input data * @param bytes The number of bytes available in `data` * @return The number of bytes processed from `data` */ LIBHASHSUM_USERET_ LIBHASHSUM_1_NONNULL_ size_t (*process)(struct libhashsum_hasher *this, const void *data, size_t bytes); /** * Update the hash state given it's final * input data * * @param this The object containing this function pointer * @param data The new input data * @param bytes The number of bytes available in `data` * @return 0 on success, -1 on failure * * @throws EINVAL `extra_bits` is greater than 7 * @throws EINVAL `extra_bits` is non-zero but `.supports_non_whole_bytes` is 0 */ LIBHASHSUM_1_NONNULL_ int (*finalise_const)(struct libhashsum_hasher *this, const void *data, unsigned extra_bits, size_t bytes); /** * Update the hash state given it's final * input data * * @param this The object containing this function pointer * @param data The new input data, the function may rewrite it's content * @param bytes The number of bytes available in `data` for reading * @param size `bytes` plus any number of additional bytes available * for the function to write additional data block padding * @return 0 on success, -1 on failure * * @throws EINVAL `extra_bits` is greater than 7 * @throws EINVAL `extra_bits` is non-zero but `.supports_non_whole_bytes` is 0 */ LIBHASHSUM_1_NONNULL_ int (*finalise)(struct libhashsum_hasher *this, void *data, size_t bytes, unsigned extra_bits, size_t size); /** * The hash state * * For internal use */ union libhashsum_state state; }; /** * Create an initialised state for a hash algorithm * and return hash functions and details * * @param this The output parameter for the functions, details, and state * @param algorithm The hashing algorithm * @return 0 on success, -1 on failure * * @throws EINVAL `algorithm` is unsupported */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_hasher(struct libhashsum_hasher *this, enum libhashsum_algorithm algorithm); /** * Create an initialised state for a MD2 * and return hash functions and details * * @param this The output parameter for the functions, details, and state * @return 0 on success, -1 on failure * * Failure isn't actually possible, so this function always return 0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_md2_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for a MD4 * and return hash functions and details * * @param this The output parameter for the functions, details, and state * @return 0 on success, -1 on failure * * Failure isn't actually possible, so this function always return 0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_md4_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for a MD5 * and return hash functions and details * * @param this The output parameter for the functions, details, and state * @return 0 on success, -1 on failure * * Failure isn't actually possible, so this function always return 0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_md5_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for a RIPEMD-128 * and return hash functions and details * * @param this The output parameter for the functions, details, and state * @return 0 on success, -1 on failure * * Failure isn't actually possible, so this function always return 0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_ripemd_128_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for a RIPEMD-160 * and return hash functions and details * * @param this The output parameter for the functions, details, and state * @return 0 on success, -1 on failure * * Failure isn't actually possible, so this function always return 0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_ripemd_160_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for a RIPEMD-256 * and return hash functions and details * * @param this The output parameter for the functions, details, and state * @return 0 on success, -1 on failure * * Failure isn't actually possible, so this function always return 0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_ripemd_256_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for a RIPEMD-320 * and return hash functions and details * * @param this The output parameter for the functions, details, and state * @return 0 on success, -1 on failure * * Failure isn't actually possible, so this function always return 0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_ripemd_320_hasher(struct libhashsum_hasher *this); #endif