aboutsummaryrefslogblamecommitdiffstats
path: root/libhashsum.h
blob: cf13a2e6e9869d12444427709d64f27acd32dbbf (plain) (tree)
1
2
3
4
5
6
7
8
9
10




                                                         
 



                                                                   
                                                         


                              
                            



      
                                                                         

              




                                                                         

              




                                                                         

              




                                                                                

              




                                                                                

              




                                                                                

              




                                                                                

              


                                          

                                                                          

              




                                                                          

              


                                    

                                                                             

              




                                                                             

              




                                                                             

              




                                                                             

              




                                                                                 

              




                                                                                 

              


                                           
























































                                                                                
                                                                              


              
                                        

   
                                                                              
                            


              
                                        

   
                                                                              
                            


              
                                        

   
                                                                                 
                            


              
                                           

   
                                                                                 
                            


              
                                           

   
                                                                                 
                            


              
                                           
 



























                                                                              















                                                                             
 





                                          
                                
 
 







































                                                                                               


                                                                 



   












                                                                                                          
                                   

              



                                  

                      



                                            










                                             

                                                

                      




                                                    

                      








                                                             

                                                         

                      




                                                               

                      



                                               




































































                                                                                 






                                                                      

                      




                                                                                          
                                                

                     






                                                                


                                                               
                                                                           
                                                  


                                                                                   


                                                                                         

                      

                             
                                                                                                                   




                                                 






                                                                






                                                                  
                                                                           
                                                                                        




                                                                                       


                                                                                         

                      




                                                                                                                    



































                                                                                











                                                                    


                           

                      




                                     




                           







                                                                                 
                                                 

                                                                     
                                                                              
                                                                        





                                                                                
                                               

              

                     
                                                                                                

   










                                                                         
                                                                                                          

   






                                                                                 

                                                                        
                                                                        





                                                                                
                                               



                   
                                                                                              

   

                                                



                                                                            
                                                        

              




                                                               

                                                



                                                                            
                                                        

              




                                                               

                                                



                                                                            
                                                        

              




                                                               

                                                



                                                                            
                                                        

              




                                                                      

                                                



                                                                            
                                                        

              




                                                                      

                                                



                                                                            
                                                        

              




                                                                      

                                                



                                                                            
                                                        

              



                                                                      



                                                               
   

                                                



                                                                            
                                                        

              




                                                                

                                                



                                                                            
                                                        

              



                                                                






                                                                            
                                                        

              










                                                                            
                                                        

              










                                                                            
                                                        

              










                                                                            
                                                        

              










                                                                            
                                                        

              










                                                                            
                                                        

              
















                                                                                
                                                        

              



                                                                                                    



































































                                                                                
                                                                                       








                                                                  

                                                                                    



























































































































































































































                                                                                                      




                                                                            
                                                           






                                                        
                                                                                      





                                                                            
                                                           






                                                        
                                                                                      






                                                                                
                                                               







                                                               
                                                                                                     





                                                                            
                                                           






                                                        
                                                                                      





                                                                            
                                                           






                                                        
                                                                                      






                                                                                
                                                               







                                                               
                                                                                                     




                                                


                                                                                 
                                                                                   


                                                                             

                                                                          

                                                                       




                                                        
                                                                                                                      
 






















                                                                                
                                                                                                     
























                                                                                        
                                                                                                     

                                                                                        

      
/* See LICENSE file for copyright and license details. */
#ifndef LIBHASHSUM_H
#define LIBHASHSUM_H

#include <stddef.h>


#if defined(__GNUC__)
# define LIBHASHSUM_USERET_ __attribute__((__warn_unused_result__))
# define LIBHASHSUM_1_NONNULL_ __attribute__((__nonnull__(1)))
# define LIBHASHSUM_NONNULL_ __attribute__((__nonnull__))
#else
# define LIBHASHSUM_USERET_
# define LIBHASHSUM_1_NONNULL_
# define LIBHASHSUM_NONNULL_
#endif


/**
 * 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

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHA3_224`
 * 
 * @since  1.0
 */
#define LIBHASHSUM_KECCAK_224_HASH_SIZE 28

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_KECCAK_256`
 * 
 * @since  1.0
 */
#define LIBHASHSUM_KECCAK_256_HASH_SIZE 32

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_KECCAK_384`
 * 
 * @since  1.0
 */
#define LIBHASHSUM_KECCAK_384_HASH_SIZE 48

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_KECCAK_512`
 * 
 * @since  1.0
 */
#define LIBHASHSUM_KECCAK_512_HASH_SIZE 64

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHA3_224`
 * 
 * @since  1.0
 */
#define LIBHASHSUM_SHA3_224_HASH_SIZE 28

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHA3_256`
 * 
 * @since  1.0
 */
#define LIBHASHSUM_SHA3_256_HASH_SIZE 32

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHA3_384`
 * 
 * @since  1.0
 */
#define LIBHASHSUM_SHA3_384_HASH_SIZE 48

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHA3_512`
 * 
 * @since  1.0
 */
#define LIBHASHSUM_SHA3_512_HASH_SIZE 64

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHAKE128`
 * 
 * @since  1.0
 */
#define LIBHASHSUM_SHAKE128_HASH_SIZE 16

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHAKE256`
 * (using default hash size)
 * 
 * @since  1.0
 */
#define LIBHASHSUM_SHAKE256_HASH_SIZE 32

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_SHAKE512`
 * (using default hash size)
 * 
 * @since  1.0
 */
#define LIBHASHSUM_SHAKE512_HASH_SIZE 64

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RAWSHAKE128`
 * (using default hash size)
 * 
 * @since  1.0
 */
#define LIBHASHSUM_RAWSHAKE128_HASH_SIZE 16

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RAWSHAKE256`
 * (using default hash size)
 * 
 * @since  1.0
 */
#define LIBHASHSUM_RAWSHAKE256_HASH_SIZE 32

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RAWSHAKE512`
 * (using default hash size)
 * 
 * @since  1.0
 */
#define LIBHASHSUM_RAWSHAKE512_HASH_SIZE 64

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_BLAKE224`
 * 
 * @since  1.0
 */
#define LIBHASHSUM_BLAKE224_HASH_SIZE 28

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_BLAKE256`
 * 
 * @since  1.0
 */
#define LIBHASHSUM_BLAKE256_HASH_SIZE 32

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_BLAKE384`
 * 
 * @since  1.0
 */
#define LIBHASHSUM_BLAKE384_HASH_SIZE 48

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_BLAKE512`
 * 
 * @since  1.0
 */
#define LIBHASHSUM_BLAKE512_HASH_SIZE 64

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_BLAKE2S`
 * (using default/maximium hash size)
 * 
 * @since  1.0
 */
#define LIBHASHSUM_BLAKE2S_HASH_SIZE 32

/**
 * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_BLAKE2B`
 * (using default/maximium hash size)
 * 
 * @since  1.0
 */
#define LIBHASHSUM_BLAKE2B_HASH_SIZE 64


#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wpadded"
#endif


#include "libhashsum/internal.h"


/**
 * Hashing algorithm
 * 
 * @since  1.0
 */
enum libhashsum_algorithm {
	/* since 1.0 */
	LIBHASHSUM_MD2,          /**< MD2; this algorithm has been theoretically compromised */
	LIBHASHSUM_MD4,          /**< MD4; this algorithm has been compromised */
	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) */
	LIBHASHSUM_KECCAK,       /**< Keccak[] */
	LIBHASHSUM_KECCAK_224,   /**< Keccak-224 */
	LIBHASHSUM_KECCAK_256,   /**< Keccak-256 */
	LIBHASHSUM_KECCAK_384,   /**< Keccak-384 */
	LIBHASHSUM_KECCAK_512,   /**< Keccak-512 */
	LIBHASHSUM_SHA3_224,     /**< SHA3-224 */
	LIBHASHSUM_SHA3_256,     /**< SHA3-256 */
	LIBHASHSUM_SHA3_384,     /**< SHA3-384 */
	LIBHASHSUM_SHA3_512,     /**< SHA3-512 */
	LIBHASHSUM_SHAKE128,     /**< SHAKE128 */
	LIBHASHSUM_SHAKE256,     /**< SHAKE256 */
	LIBHASHSUM_SHAKE512,     /**< SHAKE512 */
	LIBHASHSUM_RAWSHAKE128,  /**< RawSHAKE128 */
	LIBHASHSUM_RAWSHAKE256,  /**< RawSHAKE256 */
	LIBHASHSUM_RAWSHAKE512,  /**< RawSHAKE512 */
	LIBHASHSUM_BLAKE224,     /**< BLAKE224 (BLAKE, BLAKEs) */
	LIBHASHSUM_BLAKE256,     /**< BLAKE256 (BLAKE, BLAKEs) */
	LIBHASHSUM_BLAKE384,     /**< BLAKE384 (BLAKE, BLAKEb) */
	LIBHASHSUM_BLAKE512,     /**< BLAKE512 (BLAKE, BLAKEb) */
	LIBHASHSUM_BLAKE2S,      /**< BLAKE2s (BLAKE2) */
	LIBHASHSUM_BLAKE2B       /**< BLAKE2b (BLAKE2) */
};


/**
 * Which bits in non-whole octets are used
 * 
 * @since  1.0
 */
enum {
	/* since 1.0 */
	LIBHASHSUM_UNSUPPORTED = 0,       /**< Non-whole octets are unsupport */
	LIBHASHSUM_LEAST_SIGNIFICANT = 1, /**< The least significant bits of a non-whole octet are used */
	LIBHASHSUM_MOST_SIGNIFICANT = 2   /**< The most significant bits of a non-whole octet are used */
};


/**
 * Message hash functions and state
 * 
 * @since  1.0
 */
struct libhashsum_hasher {
	/**
	 * The used hash algorithm
	 * 
	 * @since  1.0
	 */
	enum libhashsum_algorithm algorithm;

	/**
	 * A string describing the used hash
	 * algorithm and parameters
	 * 
	 * This may be pointer to a buffer in
	 * `.state`
	 * 
	 * @since  1.0
	 */
	const char *algorithm_string;

	/**
	 * 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;

	/**
	 * libhashsum always uses the least significant bits of
	 * a non-whole octet, however every hash function that
	 * supports non-whole input octets specify their own standard
	 * for how non-whole octet are encoded. This field will be
	 * set to specify the standard used for the hash function.
	 * 
	 * If this field is set to `LIBHASHSUM_UNSUPPORTED`,
	 * `.supports_non_whole_bytes` will be 0, and non-whole
	 * input bytes are unsupported.
	 * 
	 * If this field is set to `LIBHASHSUM_LEAST_SIGNIFICANT`,
	 * `.supports_non_whole_bytes` will be 1, and the standard
	 * used by the hash function is the same as in libhashsum
	 * (the least significant bits are used), and no conversion
	 * between the hash function's standard and libhashsum's
	 * standard is required for input messages.
	 * 
	 * If this field is set to `LIBHASHSUM_MOST_SIGNIFICANT`,
	 * `.supports_non_whole_bytes` will be 1, and the standard
	 * used by the hash function is the opposite of libhashsum's
	 * standard, thus if you have reference input message with
	 * a partial final byte (where the most significant bits are
	 * used, and the least significant bits are discarded), you
	 * have to reverse the bits in the last octet before
	 * inputing it to `*.finalise` or `*.finalise_const`.
	 * 
	 * If you are creating your own message, you always store
	 * the used bits, in a non-whole octet, in the least
	 * significant part of the octet, when inputing it to
	 * `*.finalise` or `*.finalise_const`.
	 * 
	 * @since  1.0
	 */
	unsigned char standard_partial_byte_input_encoding; /* TODO man, test */

	/**
	 * libhashsum always uses the least significant bits of
	 * a non-while octet, however every hash function that
	 * supports non-whole output octets specify their own standard
	 * for how non-whole octets are encoded. This field will be
	 * set to specify the standard used for the hash function.
	 * 
	 * If this field is set to `LIBHASHSUM_UNSUPPORTED`, non-whole
	 * output bytees are unsupported.
	 * 
	 * If this field is set to `LIBHASHSUM_LEAST_SIGNIFICANT`,
	 * the standard used by the hash function is the same as in
	 * libhashsum (the least significant bits are used), and no
	 * conversion between the hash function's standard and
	 * libhashsum's standard is required for hashes.
	 * 
	 * If this field is set to `LIBHASHSUM_MOST_SIGNIFICANT`,
	 * the standard used by the hash function is the opposite of
	 * libhashsum's standard, thus if you have reference hash
	 * with a partial final byte (where the most significant bits
	 * are used, and the least significant bits are unused), you
	 * have to reverse the bits in the last octet before comparing
	 * the reference hash with the output of `*.finalise` and
	 * `*.finalise_const`.
	 * 
	 * The text above assumes that the hash function's standard
	 * is to always clear unused bits; this is also always done
	 * by `*.finalise` and `*.finalise_const`.
	 * 
	 * @since  1.0
	 */
	unsigned char standard_partial_byte_output_encoding; /* TODO man, test */

	/**
	 * 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 its final
	 * input data
	 * 
	 * Regardless of the algorithm's standard, the function
	 * will takes the lower bits from `data[bytes]`, if
	 * `extra_bits > 0` and use the for the additional bits;
	 * the least significant bit will be used as the first
	 * bit and the most significant bit will be used as the
	 * last bit
	 * 
	 * `this->hash_output` will be set to point to a buffer
	 * in `this->state` containing the hash
	 * 
	 * @param   this        The object containing this function pointer
	 * @param   data        The new input data
	 * @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
	 * 
	 * Regardless of the algorithm's standard, the function
	 * will takes the lower bits from `data[bytes]`, if
	 * `extra_bits > 0` and use the for the additional bits;
	 * the least significant bit will be used as the first
	 * bit and the most significant bit will be used as the
	 * last bit
	 * 
	 * `this->hash_output` will be set to point to a buffer
	 * in `this->state` containing the hash. However if
	 * `this->hash_output` is already non-`NULL`, the function
	 * _may_ choose to immediately output to the buffer that
	 * `this->hash_output` pointers to (the application must
	 * make sure it is sufficiently large).
	 * 
	 * @param   this        The object containing this function pointer
	 * @param   data        The new input data, the function may rewrite its 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);

	/**
	 * Extend the hash with an additional `this->hash_size` bytes
	 * 
	 * This pointer will be set to `NULL` when the object initialised,
	 * but once `*.finalise` or `*.finalise_const` is called, it
	 * will be set a point to a function _if_ the algorithm supports
	 * extending the hash indefinitely (if there is a limit, this
	 * pointer will be set to `NULL` once the limit has been reached)
	 * 
	 * If the hash function supports generating hashes before the
	 * entire file has been processed, this pointer be non-`NULL`
	 * immediately when the object is initialised, however the
	 * hash function does not support extending the hash, calling
	 * this function, `*.finalise`, or `*.finalise_const` will
	 * reset this pointer to `NULL`. (No currently supported hash
	 * function supports this behaviour.)
	 * 
	 * `this->hash_output` will be set to point to a buffer
	 * in `this->state` containing the hash extent. Note that
	 * this overrides any hash previously generated for `this`.
	 * 
	 * @param  this    The object containing this function pointer
	 * @param  skip    Non-zero if the function need not set
	 *                 `this->hash_output` and output the hash extent
	 *                 (note that the function may ignore this argument)
	 * @param  buffer  If non-`NULL`, the function _may_ choose output the
	 *                 hash extent to the provided buffer (the application
	 *                 must ensure it is sufficently large). If the function
	 *                 does output to the provided buffer, it will reset
	 *                 `this->hash_output` to `NULL`.
	 * 
	 * @since  1.0
	 */
	LIBHASHSUM_1_NONNULL_
	void (*stretch)(struct libhashsum_hasher *this, int skip, void *buffer);

	/**
	 * Unless this pointer its `NULL`, it points to
	 * function that shall be once the object (`this`)
	 * is not needed anymore
	 * 
	 * @param  this  The object containing this function pointer
	 * 
	 * @since  1.0
	 */
	LIBHASHSUM_1_NONNULL_
	void (*destroy)(struct libhashsum_hasher *this);

	/**
	 * The hash state
	 * 
	 * For internal use
	 * 
	 * @since  1.0
	 */
	union libhashsum_state state;
};


#if defined(__GNUC__)
# pragma GCC diagnostic pop
#endif


/**
 * 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 not recognised
 * @throws  EINVAL  `algorithm` requires parameters, and is therefore
 *                  not supported by this function (use dedicated
 *                  initialiser instead). (`algorithm` is `LIBHASHSUM_KECCAK`)
 * @throws  ENOSYS  Support for `algorithm` was excluded at compile time
 * @throws  ENOSYS  The `algorithm` requires a newer version of the library
 *                  that application was compiled for (the application
 *                  is however linked to new enough version of the library)
 *                  (specifically this means that the application's version
 *                  of `union libhashsum_state`, and thus also
 *                  `struct libhashsum_hasher`, is too small to store the state)
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_hasher(struct libhashsum_hasher *this, enum libhashsum_algorithm algorithm);

/**
 * Inspect a hashing algorithm string to identify
 * which algorithm it references
 * 
 * @param   algorithm_out  Output parameter for the hashing algorithm
 *                         identifier (set if 1 is returned)
 * @param   algorithm      The hashing algorithm as a string
 * @return                 1 if the algorithm was recognised, 0 otherwise
 * 
 * @since  1.0
 */
LIBHASHSUM_NONNULL_
int libhashsum_get_algorithm_from_string(enum libhashsum_algorithm *algorithm_out, const char *algorithm);

/**
 * 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 and parameters
 * @return             0 on success, -1 on failure
 * 
 * @throws  EINVAL  `algorithm` is not recognised or contains an invalid
 *                  parameter or an invalid combination of parameters
 * @throws  ENOSYS  Support for `algorithm` was excluded at compile time
 * @throws  ENOSYS  The `algorithm` requires a newer version of the library
 *                  that application was compiled for (the application
 *                  is however linked to new enough version of the library)
 *                  (specifically this means that the application's version
 *                  of `union libhashsum_state`, and thus also
 *                  `struct libhashsum_hasher`, is too small to store the state)
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_NONNULL_
int libhashsum_init_hasher_from_string(struct libhashsum_hasher *this, const char *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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_ripemd_320_hasher(struct libhashsum_hasher *this);

/* there is no `libhashsum_init_ripemd_hasher` because this can
 * be confused with the proprietary hash function RIPEMD, which
 * is the predecessor to RIPEMD-{128,160,256,320} */

/**
 * 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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @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)
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_sha2_hasher(struct libhashsum_hasher *this, unsigned algobits, size_t hashbits);

/**
 * Create an initialised state for Keccak-224
 * 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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_keccak_224_hasher(struct libhashsum_hasher *this);

/**
 * Create an initialised state for Keccak-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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_keccak_256_hasher(struct libhashsum_hasher *this);

/**
 * Create an initialised state for Keccak-384
 * 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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_keccak_384_hasher(struct libhashsum_hasher *this);

/**
 * Create an initialised state for Keccak-512
 * 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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_keccak_512_hasher(struct libhashsum_hasher *this);

/**
 * Create an initialised state for Keccak
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   ratebits  Bitrate (in bits), 0 for automatic
 * @param   capbits   Capacity in bits, 0 for automatic
 * @param   hashbits  Hash output size in bits, 0 for automatic
 * @param   squeezes  The number of squeezes to performed, 0 for automatic (which is 1)
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  (`ratebits`, `capbits`, `hashbits`) is invalid
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_keccak_hasher(struct libhashsum_hasher *this, size_t ratebits,
                                  size_t capbits, size_t hashbits, size_t squeezes);

/**
 * Create an initialised state for SHA3-224
 * 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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_sha3_224_hasher(struct libhashsum_hasher *this);

/**
 * Create an initialised state for SHA3-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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_sha3_256_hasher(struct libhashsum_hasher *this);

/**
 * Create an initialised state for SHA3-384
 * 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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_sha3_384_hasher(struct libhashsum_hasher *this);

/**
 * Create an initialised state for SHA3-512
 * 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
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_sha3_512_hasher(struct libhashsum_hasher *this);

/**
 * Create an initialised state for SHA3
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   hashbits  Hash output size in bits
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hashbits` is invalid (neither 224, 256, 384, nor 512)
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_sha3_hasher(struct libhashsum_hasher *this, size_t hashbits);

/**
 * Create an initialised state for SHAKE128
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   hashbits  Hash output size in bits, if 0, 128 is used
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hashbits` is too large
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_shake128_hasher(struct libhashsum_hasher *this, size_t hashbits);

/**
 * Create an initialised state for SHAKE256
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   hashbits  Hash output size in bits, if 0, 256 is used
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hashbits` is too large
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_shake256_hasher(struct libhashsum_hasher *this, size_t hashbits);

/**
 * Create an initialised state for SHAKE512
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   hashbits  Hash output size in bits, if 0, 512 is used
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hashbits` is too large
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_shake512_hasher(struct libhashsum_hasher *this, size_t hashbits);

/**
 * Create an initialised state for SHAKE
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   hcapbits  Half of the capacity, in bits (this is the
 *                    value added behind the function name)
 * @param   hashbits  Hash output size in bits, if 0, `hcapbits` is used
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hcapbits` is invalid (neither 128, 256, nor 512)
 * @throws  EINVAL  `hashbits` is too large
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_shake_hasher(struct libhashsum_hasher *this, size_t hcapbits, size_t hashbits);

/**
 * Create an initialised state for RawSHAKE128
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   hashbits  Hash output size in bits, if 0, 128 is used
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hashbits` is too large
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_rawshake128_hasher(struct libhashsum_hasher *this, size_t hashbits);

/**
 * Create an initialised state for RawSHAKE256
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   hashbits  Hash output size in bits, if 0, 256 is used
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hashbits` is too large
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_rawshake256_hasher(struct libhashsum_hasher *this, size_t hashbits);

/**
 * Create an initialised state for RawSHAKE512
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   hashbits  Hash output size in bits, if 0, 512 is used
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hashbits` is too large
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_rawshake512_hasher(struct libhashsum_hasher *this, size_t hashbits);

/**
 * Create an initialised state for RawSHAKE
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   hcapbits  Half of the capacity, in bits (this is the
 *                    value added behind the function name)
 * @param   hashbits  Hash output size in bits, if 0, `hcapbits` is used
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hcapbits` is invalid (neither 128, 256, nor 512)
 * @throws  EINVAL  `hashbits` is too large
 * @throws  ENOSYS  Support was excluded at compile time
 * @throws  ENOMEM  Not enough memory available
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_rawshake_hasher(struct libhashsum_hasher *this, size_t hcapbits, size_t hashbits);

/**
 * Create an initialised state for BLAKE224 (BLAKE, BLAKEs)
 * hashing and return hash functions and details
 * 
 * @param   this  The output parameter for the functions, details, and state
 * @param   salt  `NULL` (for all zeroes) or a 16-byte salt
 * @return        0 on success, -1 on failure
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_blake224_hasher(struct libhashsum_hasher *this, const void *salt);

/**
 * Create an initialised state for BLAKE256 (BLAKE, BLAKEs)
 * hashing and return hash functions and details
 * 
 * @param   this  The output parameter for the functions, details, and state
 * @param   salt  `NULL` (for all zeroes) or a 16-byte salt
 * @return        0 on success, -1 on failure
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_blake256_hasher(struct libhashsum_hasher *this, const void *salt);

/**
 * Create an initialised state for BLAKEs (BLAKE)
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   hashbits  Hash output size in bits
 * @param   salt      `NULL` (for all zeroes) or a 16-byte salt
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hashbits` is invalid (neither 224 nor 256)
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_blakes_hasher(struct libhashsum_hasher *this, size_t hashbits, const void *salt);

/**
 * Create an initialised state for BLAKE384 (BLAKE, BLAKEb)
 * hashing and return hash functions and details
 * 
 * @param   this  The output parameter for the functions, details, and state
 * @param   salt  `NULL` (for all zeroes) or a 32-byte salt
 * @return        0 on success, -1 on failure
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_blake384_hasher(struct libhashsum_hasher *this, const void *salt);

/**
 * Create an initialised state for BLAKE512 (BLAKE, BLAKEb)
 * hashing and return hash functions and details
 * 
 * @param   this  The output parameter for the functions, details, and state
 * @param   salt  `NULL` (for all zeroes) or a 32-byte salt
 * @return        0 on success, -1 on failure
 * 
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_blake512_hasher(struct libhashsum_hasher *this, const void *salt);

/**
 * Create an initialised state for BLAKEb (BLAKE)
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   hashbits  Hash output size in bits
 * @param   salt      `NULL` (for all zeroes) or a 32-byte salt
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hashbits` is invalid (neither 384 nor 512)
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_blakeb_hasher(struct libhashsum_hasher *this, size_t hashbits, const void *salt);

/**
 * Create an initialised state for BLAKE
 * hashing and return hash functions and details
 * 
 * @param   this       The output parameter for the functions, details, and state
 * @param   hashbits   Hash output size in bits
 * @param   salt       `NULL` (for all zeroes) or a salt
 * @param   saltbytes  The number of bytes in `salt` (ignored if `salt` is `NULL`),
 *                     shall be 16 for if `hashbits` is 224 or 256, and 32 if
 *                     `hashbits` is 384 or 512
 * @return             0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hashbits` is invalid (neither 224, 256, 384, nor 512)
 * @throws  EINVAL  `salt` is not `NULL` but `saltbytes` does not match
 *                  the expected value for the input `hashbits`
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_blake_hasher(struct libhashsum_hasher *this, size_t hashbits, const void *salt, size_t saltbytes);

/**
 * Create an initialised state for BLAKE2s (BLAKE2)
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   hashbits  Hash output size in bits, must be an multiple of 8 between
 *                    8 and 256 (inclusively), or 0 for the maximum size
 * @param   salt      `NULL` (for all zeroes) or a 8-byte salt
 * @param   pepper    `NULL` (for all zeroes) or a 8-byte pepper
 * @param   key       Key or `NULL` for unkeyed mode,
 * @param   keybits   The number of byts in `key` (0 if `key` is `NULL`),
 *                    which must be a multiple of 8 no greater than 256
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hashbits` is greater than 256
 * @throws  EINVAL  `hashbits` is not a multiple of 8
 * @throws  EINVAL  `keybits` is greater than 256
 * @throws  EINVAL  `keybits` is not a multiple of 8
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_blake2s_hasher(struct libhashsum_hasher *this, size_t hashbits, const void *salt,
                                   const void *pepper, const void *key, size_t keybits);

/**
 * Create an initialised state for BLAKE2b (BLAKE2)
 * hashing and return hash functions and details
 * 
 * @param   this      The output parameter for the functions, details, and state
 * @param   hashbits  Hash output size in bits, must be an multiple of 8 between
 *                    8 and 512 (inclusively), or 0 for the maximum size
 * @param   salt      `NULL` (for all zeroes) or a 16-byte salt
 * @param   pepper    `NULL` (for all zeroes) or a 16-byte pepper
 * @param   key       Key or `NULL` for unkeyed mode,
 * @param   keybits   The number of byts in `key` (0 if `key` is `NULL`),
 *                    which must be a multiple of 8 no greater than 512
 * @return            0 on success, -1 on failure
 * 
 * @throws  EINVAL  `hashbits` is greater than 512
 * @throws  EINVAL  `hashbits` is not a multiple of 8
 * @throws  EINVAL  `keybits` is greater than 512
 * @throws  EINVAL  `keybits` is not a multiple of 8
 * @throws  ENOSYS  Support was excluded at compile time
 * 
 * @since  1.0
 */
LIBHASHSUM_1_NONNULL_
int libhashsum_init_blake2b_hasher(struct libhashsum_hasher *this, size_t hashbits, const void *salt,
                                   const void *pepper, const void *key, size_t keybits);


#endif