aboutsummaryrefslogblamecommitdiffstats
path: root/libsha2.h
blob: 51b8344c4cc56aadb119ff17d4dd685725b3188e (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13



                                                         
                  







                                  
 






































                                                               

                      
 











                                                                 
                                       
 


                                        
                                       










                                         
                                       



                                        
                                       








                                        
                                      



                                        
                                      










                                         
                                      



                                        
                                      








                                               













                                           








                                                                    
 






























                                                     

                     

                                                           




                                                   
                                                                         

   
                                      
   

                                                                       

                     
                                                    
      














                                                                 

   
                                                             
   

                                                                   

                     
                                                                 
      




                                                                       










                                                                           
                                                                                  











                                                                                      
                                                                                  












                                                      
                                                                










                                                                                        
                                                                       










                                                                                        
                                                                       











                                                           
                                                         
 









                                                                         
                                                                             











                                                                          
















                                                                                                                 





                                                                   
                                                                 
      




                                                                                 

   

                                    



                                                         



                                                   
                                                                                            








                                                  




                                                                 



                                                   
                                                                                            
 
























                                                                                                 

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

#include <errno.h>
#include <stdint.h>
#include <stddef.h>


/**
 * 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.
 */
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
		 */
		uint_least32_t b32[64];

		/**
		 * For 64-bit algorithms
		 */
		uint_least64_t b64[80];
	} k;

	/**
	 * Words
	 * 
	 * Does not need to be marshalled
	 */
	union {
		/**
		 * For 32-bit algorithms
		 */
		uint_least32_t b32[64];

		/**
		 * For 64-bit algorithms
		 */
		uint_least64_t b64[80];
	} w;

	/**
	 * Hashing values
	 */
	union {
		/**
		 * For 32-bit algorithms
		 */
		uint_least32_t b32[8];

		/**
		 * For 64-bit algorithms
		 */
		uint_least64_t b64[8];
	} h;

	/**
	 * Temporary hashing values
	 * 
	 * Does not need to be marshalled
	 */
	union {
		/**
		 * For 32-bit algorithms
		 */
		uint_least32_t b32[8];

		/**
		 * For 64-bit algorithms
		 */
		uint_least64_t b64[8];
	} work_h;

	/**
	 * Space for chunks to process, limited
	 * to 64 bytes on 32-bit algorithms
	 */
	unsigned char chunk[128];

	/**
	 * The size of the chunks, in bytes
	 */
	size_t chunk_size;

	/**
	 * The algorithm that is used
	 */
	enum libsha2_algorithm algorithm;

	int __padding1;
};


/**
 * Data structure that describes the state of a HMAC 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.
 */
struct libsha2_hmac_state {

	/**
	 * State of the underlaying hash function
	 */
	struct libsha2_state sha2_state;

	/**
	 * The output size of the underlaying
	 * hash algorithm, in bits
	 */
	size_t outsize;

	/**
	 * Whether `.sha2_state` has been initialised
	 * and whether the `ipad` has been feed into
	 * the algorithm
	 */
	unsigned char inited;

	/**
	 * Inner pad XOR processed key
	 */
	unsigned char ipad[128];

	/**
	 * Outer pad XOR processed key
	 */
	unsigned char opad[128];
};


/**
 * Initialise a state
 * 
 * @param   state      The state that should be initialised
 * @param   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 an algorithm
 * 
 * @param   algorithm  The hashing algorithm
 * @return             The number of bytes in the output, zero on error
 */
#if defined(__GNUC__)
__attribute__((__warn_unused_result__, __nothrow__))
#endif
inline size_t
libsha2_algorithm_output_size(enum libsha2_algorithm algorithm__)
{
	switch (algorithm__) {
	case LIBSHA2_224:     return 28;
	case LIBSHA2_256:     return 32;
	case LIBSHA2_384:     return 48;
	case LIBSHA2_512:     return 64;
	case LIBSHA2_512_224: return 28;
	case LIBSHA2_512_256: return 32;
	default:
		errno = EINVAL;
		return 0;
	}
}

/**
 * Get the output size of the algorithm specified for a state
 * 
 * @param   state  The state
 * @return         The number of bytes in the output, zero on error
 */
#if defined(__GNUC__)
__attribute__((__warn_unused_result__, __nothrow__, __nonnull__))
#endif
inline size_t
libsha2_state_output_size(const struct libsha2_state *restrict state__)
{
	return libsha2_algorithm_output_size(state__->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 void *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 void *, size_t, void *);

/**
 * 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, void *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 void *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 void *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(void *restrict, const char *restrict);

/**
 * Marshal a state into a buffer
 * 
 * @param   state  The state to marshal
 * @param   buf    Output buffer, `NULL` to only return the required size
 * @return         The number of bytes marshalled to `buf`
 */
#if defined(__GNUC__)
__attribute__((__leaf__, __nonnull__(1), __nothrow__))
#endif
size_t libsha2_marshal(const struct libsha2_state *restrict, void *restrict);

/**
 * Unmarshal a state from a buffer
 * 
 * @param   state    Output parameter for the unmarshalled state
 * @param   buf      The buffer from which the state shall be unmarshalled
 * @param   bufsize  The maximum number of bytes that can be unmarshalled
 * @return           The number of read bytes, 0 on failure
 */
#if defined(__GNUC__)
__attribute__((__leaf__, __nonnull__, __nothrow__))
#endif
size_t libsha2_unmarshal(struct libsha2_state *restrict, const void *restrict, size_t);

/**
 * Initialise an HMAC state
 * 
 * @param   state        The state that should be initialised
 * @param   algorithm    The hashing algorithm
 * @param   key          The key
 * @param   key_length   The length of key, in bits
 * @return               Zero on success, -1 on error
 */
#if defined(__GNUC__)
__attribute__((__leaf__, __nonnull__, __nothrow__))
#endif
int libsha2_hmac_init(struct libsha2_hmac_state *restrict, enum libsha2_algorithm, const void *restrict, size_t);

/**
 * Get the output size of the algorithm specified for an HMAC state
 * 
 * @param   state  The state
 * @return         The number of bytes in the output, zero on error
 */
#if defined(__GNUC__)
__attribute__((__warn_unused_result__, __nothrow__, __nonnull__))
#endif
inline size_t
libsha2_hmac_state_output_size(const struct libsha2_hmac_state *restrict state__)
{
	return libsha2_algorithm_output_size(state__->sha2_state.algorithm);
}

/**
 * Feed data into the HMAC algorithm
 * 
 * @param  state  The state of the algorithm
 * @param  data   Data to feed into the algorithm
 * @param  n      The number of bytes to feed into the
 *                algorithm, this must be a multiple of 8
 */
#if defined(__GNUC__)
__attribute__((__leaf__, __nonnull__, __nothrow__))
#endif
void libsha2_hmac_update(struct libsha2_hmac_state *restrict, const void *restrict, size_t);

/**
 * Feed data into the HMAC algorithm and
 * get the result
 * 
 * The state of the algorithm will be reset and
 * `libsha2_hmac_update` and `libsha2_hmac_update`
 * can be called again
 * 
 * @param  state   The state of the algorithm
 * @param  data    Data to feed into the algorithm
 * @param  n       The number of bytes to feed into the algorithm
 * @param  output  The output buffer for the hash, it will be as
 *                 large as for the underlaying hash algorithm
 */
#if defined(__GNUC__)
__attribute__((__leaf__, __nonnull__, __nothrow__))
#endif
void libsha2_hmac_digest(struct libsha2_hmac_state *restrict, const void *, size_t, void *);

/**
 * Marshal an HMAC state into a buffer
 * 
 * @param   state  The state to marshal
 * @param   buf    Output buffer, `NULL` to only return the required size
 * @return         The number of bytes marshalled to `buf`
 */
#if defined(__GNUC__)
__attribute__((__leaf__, __nonnull__(1), __nothrow__))
#endif
size_t libsha2_hmac_marshal(const struct libsha2_hmac_state *restrict, void *restrict);

/**
 * Unmarshal an HMAC state from a buffer
 * 
 * @param   state    Output parameter for the unmarshalled state
 * @param   buf      The buffer from which the state shall be unmarshalled
 * @param   bufsize  The maximum number of bytes that can be unmarshalled
 * @return           The number of read bytes, 0 on failure
 */
#if defined(__GNUC__)
__attribute__((__leaf__, __nonnull__, __nothrow__))
#endif
size_t libsha2_hmac_unmarshal(struct libsha2_hmac_state *restrict, const void *restrict, size_t);


#endif