/* See LICENSE file for copyright and license details. */ #ifndef LIBHASHSUM_H #define LIBHASHSUM_H #include #include #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 * * @since 1.0 */ enum libhashsum_algorithm { /* since 1.0 */ LIBHASHSUM_MD2, /**< MD2 */ LIBHASHSUM_MD4, /**< MD4 */ LIBHASHSUM_MD5, /**< MD5; this algorithm has been compromised */ LIBHASHSUM_RIPEMD_128, /**< RIPEMD-128 */ LIBHASHSUM_RIPEMD_160, /**< RIPEMD-160 */ LIBHASHSUM_RIPEMD_256, /**< RIPEMD-256 */ LIBHASHSUM_RIPEMD_320, /**< RIPEMD-320 */ LIBHASHSUM_SHA0, /**< SHA0; this algorithm has been compromised */ LIBHASHSUM_SHA1, /**< SHA1; this algorithm has been compromised */ LIBHASHSUM_SHA_224, /**< SHA-224 (SHA2) */ LIBHASHSUM_SHA_256, /**< SHA-256 (SHA2) */ LIBHASHSUM_SHA_384, /**< SHA-384 (SHA2) */ LIBHASHSUM_SHA_512, /**< SHA-512 (SHA2) */ LIBHASHSUM_SHA_512_224, /**< SHA-512/224 (SHA2) */ LIBHASHSUM_SHA_512_256 /**< SHA-512/256 (SHA2) */ }; /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_MD2` * * @since 1.0 */ #define LIBHASHSUM_MD2_HASH_SIZE 16 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_MD4` * * @since 1.0 */ #define LIBHASHSUM_MD4_HASH_SIZE 16 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_MD5` * * @since 1.0 */ #define LIBHASHSUM_MD5_HASH_SIZE 16 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RIPEMD_128` * * @since 1.0 */ #define LIBHASHSUM_RIPEMD_128_HASH_SIZE 16 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RIPEMD_160` * * @since 1.0 */ #define LIBHASHSUM_RIPEMD_160_HASH_SIZE 20 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RIPEMD_256` * * @since 1.0 */ #define LIBHASHSUM_RIPEMD_256_HASH_SIZE 32 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RIPEMD_320` * * @since 1.0 */ #define LIBHASHSUM_RIPEMD_320_HASH_SIZE 40 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHA0` * * @since 1.0 */ #define LIBHASHSUM_SHA0_HASH_SIZE 20 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHA1` * * @since 1.0 */ #define LIBHASHSUM_SHA1_HASH_SIZE 20 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHA_224` * * @since 1.0 */ #define LIBHASHSUM_SHA_224_HASH_SIZE 28 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHA_256` * * @since 1.0 */ #define LIBHASHSUM_SHA_256_HASH_SIZE 32 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHA_384` * * @since 1.0 */ #define LIBHASHSUM_SHA_384_HASH_SIZE 48 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHA_512` * * @since 1.0 */ #define LIBHASHSUM_SHA_512_HASH_SIZE 64 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHA_512_224` * * @since 1.0 */ #define LIBHASHSUM_SHA_512_224_HASH_SIZE 28 /** * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHA_512_256` * * @since 1.0 */ #define LIBHASHSUM_SHA_512_256_HASH_SIZE 32 /** * 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; struct { struct libsha1_state s; uint8_t sum[20]; } sha0, sha1; struct { struct libsha2_state s; uint8_t sum[64]; } sha2; }; /** * Message hash functions and state * * @since 1.0 */ struct libhashsum_hasher { /** * The used hash algorithm * * @since 1.0 */ enum libhashsum_algorithm algorithm; /** * The number of bytes required for each * call to `.process_block` * * @since 1.0 */ size_t input_block_size; /** * The number of bytes in the resulting hash * * @since 1.0 */ 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 with successful * completion * * @since 1.0 */ unsigned char *hash_output; /** * Whether the algorithm supports non-whole octet input * * @since 1.0 */ 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` * * @since 1.0 */ 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, the function may rewrite it's content * @param bytes The number of bytes available in `data` for reading * @param extra_bits Additional bits in `data` not covered by `bytes` * @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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int (*finalise_const)(struct libhashsum_hasher *this, const void *data, size_t bytes, unsigned extra_bits); /** * 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 extra_bits Additional bits in `data` not covered by `bytes` * @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 * * @since 1.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 * * @since 1.0 */ 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_hasher(struct libhashsum_hasher *this, enum libhashsum_algorithm algorithm); /** * Create an initialised state for MD2 * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_md2_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for MD4 * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_md4_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for MD5 * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_md5_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for RIPEMD-128 * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_ripemd_128_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for RIPEMD-160 * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_ripemd_160_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for RIPEMD-256 * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_ripemd_256_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for RIPEMD-320 * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_ripemd_320_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for SHA0 * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_sha0_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for SHA1 * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_sha1_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for SHA-224 (SHA2) * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_sha_224_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for SHA-256 (SHA2) * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_sha_256_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for SHA-384 (SHA2) * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_sha_384_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for SHA-512 (SHA2) * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_sha_512_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for SHA-512/224 (SHA2) * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_sha_512_224_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for SHA-512/256 (SHA2) * hashing 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 * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_sha_512_256_hasher(struct libhashsum_hasher *this); /** * Create an initialised state for SHA2 * hashing and return hash functions and details * * @param this The output parameter for the functions, details, and state * @param algobits 32 for a 32-bit algorithm, 64 for a 64-bit algorithm * @param hashbits Hash output size in bits * @return 0 on success, -1 on failure * * @throws EINVAL `algobits` is invalid (neither 32 nor 64) * @throws EINVAL `hashbits` is invalid (neither 224, 256, 384, nor 512) * @throws EINVAL The combination of `algobits` and `hashbits` is invalid * (`hashbits` is 384 or 512 but `algobits` is 32) * * @since 1.0 */ LIBHASHSUM_1_NONNULL_ int libhashsum_init_sha2_hasher(struct libhashsum_hasher *this, unsigned algobits, size_t hashbits); #endif