#ifndef __TC_SHA256_H__ #define __TC_SHA256_H__ #include #include #ifdef __cplusplus extern "C" { #endif #define TC_SHA256_BLOCK_SIZE (64) #define TC_SHA256_DIGEST_SIZE (32) #define TC_SHA256_STATE_BLOCKS (TC_SHA256_DIGEST_SIZE/4) struct tc_sha256_state_struct { unsigned int iv[TC_SHA256_STATE_BLOCKS]; uint64_t bits_hashed; uint8_t leftover[TC_SHA256_BLOCK_SIZE]; size_t leftover_offset; }; typedef struct tc_sha256_state_struct *TCSha256State_t; /** * @brief SHA256 initialization procedure * Initializes s * @return returns TC_CRYPTO_SUCCESS (1) * returns TC_CRYPTO_FAIL (0) if s == NULL * @param s Sha256 state struct */ int tc_sha256_init(TCSha256State_t s); /** * @brief SHA256 update procedure * Hashes data_length bytes addressed by data into state s * @return returns TC_CRYPTO_SUCCESS (1) * returns TC_CRYPTO_FAIL (0) if: * s == NULL, * s->iv == NULL, * data == NULL * @note Assumes s has been initialized by tc_sha256_init * @warning The state buffer 'leftover' is left in memory after processing * If your application intends to have sensitive data in this * buffer, remind to erase it after the data has been processed * @param s Sha256 state struct * @param data message to hash * @param datalen length of message to hash */ int tc_sha256_update (TCSha256State_t s, const uint8_t *data, size_t datalen); /** * @brief SHA256 final procedure * Inserts the completed hash computation into digest * @return returns TC_CRYPTO_SUCCESS (1) * returns TC_CRYPTO_FAIL (0) if: * s == NULL, * s->iv == NULL, * digest == NULL * @note Assumes: s has been initialized by tc_sha256_init * digest points to at least TC_SHA256_DIGEST_SIZE bytes * @warning The state buffer 'leftover' is left in memory after processing * If your application intends to have sensitive data in this * buffer, remind to erase it after the data has been processed * @param digest unsigned eight bit integer * @param Sha256 state struct */ int tc_sha256_final(uint8_t *digest, TCSha256State_t s); /** * @brief Copy the the buffer 'from' to the buffer 'to'. * @return returns TC_CRYPTO_SUCCESS (1) * returns TC_CRYPTO_FAIL (0) if: * from_len > to_len. * * @param to OUT -- destination buffer * @param to_len IN -- length of destination buffer * @param from IN -- origin buffer * @param from_len IN -- length of origin buffer */ unsigned int _copy(uint8_t *to, unsigned int to_len, const uint8_t *from, unsigned int from_len); /** * @brief Set the value 'val' into the buffer 'to', 'len' times. * * @param to OUT -- destination buffer * @param val IN -- value to be set in 'to' * @param len IN -- number of times the value will be copied */ void _set(void *to, uint8_t val, unsigned int len); /* * @brief AES specific doubling function, which utilizes * the finite field used by AES. * @return Returns a^2 * * @param a IN/OUT -- value to be doubled */ uint8_t _double_byte(uint8_t a); /* * @brief Constant-time algorithm to compare if two sequences of bytes are equal * @return Returns 0 if equal, and non-zero otherwise * * @param a IN -- sequence of bytes a * @param b IN -- sequence of bytes b * @param size IN -- size of sequences a and b */ int _compare(const uint8_t *a, const uint8_t *b, size_t size); struct tc_hmac_state_struct { /* the internal state required by h */ struct tc_sha256_state_struct hash_state; /* HMAC key schedule */ uint8_t key[2*TC_SHA256_BLOCK_SIZE]; }; typedef struct tc_hmac_state_struct *TCHmacState_t; /** * @brief HMAC set key procedure * Configures ctx to use key * @return returns TC_CRYPTO_SUCCESS (1) * returns TC_CRYPTO_FAIL (0) if * ctx == NULL or * key == NULL or * key_size == 0 * @param ctx IN/OUT -- the struct tc_hmac_state_struct to initial * @param key IN -- the HMAC key to configure * @param key_size IN -- the HMAC key size */ int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key, unsigned int key_size); /** * @brief HMAC init procedure * Initializes ctx to begin the next HMAC operation * @return returns TC_CRYPTO_SUCCESS (1) * returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL * @param ctx IN/OUT -- struct tc_hmac_state_struct buffer to init */ int tc_hmac_init(TCHmacState_t ctx); /** * @brief HMAC update procedure * Mixes data_length bytes addressed by data into state * @return returns TC_CRYPTO_SUCCCESS (1) * returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL * @note Assumes state has been initialized by tc_hmac_init * @param ctx IN/OUT -- state of HMAC computation so far * @param data IN -- data to incorporate into state * @param data_length IN -- size of data in bytes */ int tc_hmac_update(TCHmacState_t ctx, const void *data, unsigned int data_length); /** * @brief HMAC final procedure * Writes the HMAC tag into the tag buffer * @return returns TC_CRYPTO_SUCCESS (1) * returns TC_CRYPTO_FAIL (0) if: * tag == NULL or * ctx == NULL or * key == NULL or * taglen != TC_SHA256_DIGEST_SIZE * @note ctx is erased before exiting. This should never be changed/removed. * @note Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes * state has been initialized by tc_hmac_init * @param tag IN/OUT -- buffer to receive computed HMAC tag * @param taglen IN -- size of tag in bytes * @param ctx IN/OUT -- the HMAC state for computing tag */ int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx); #ifdef __cplusplus } #endif #endif /* __TC_SHA256_H__ */