1 /* COPYING ****************************************************************** 2 For copyright and licensing terms, see the file named COPYING. 3 // ************************************************************************** 4 */ 5 6 #include <stdint.h> 7 8 class CubeHash { 9 public: 10 unsigned char hashval[512/8]; 11 12 // tunable parameters as per Dan Bernstein's 2009-09 NIST submission CubeHash(unsigned int i,unsigned int r,unsigned int b,unsigned int f,unsigned int h)13 CubeHash(unsigned int i, unsigned int r, unsigned int b, unsigned int f, unsigned int h) : 14 initial_rounds(i), 15 block_rounds(r), 16 final_rounds(f), 17 bytes_per_block(b), 18 hashbytelen((h + 7) / 8), 19 byte_pos(0) 20 { 21 Init(); 22 } 23 Update(const unsigned char * data,std::size_t databytelen)24 void Update(const unsigned char *data, std::size_t databytelen) 25 { 26 while (databytelen > 0) { 27 const uint32_t u(uint32_t(*data) << (8U * (byte_pos % 4U))); 28 x[byte_pos / 4U] ^= u; 29 ++data; 30 --databytelen; 31 ++byte_pos; 32 if (byte_pos == bytes_per_block) { 33 transform(block_rounds); 34 byte_pos = 0U; 35 } 36 } 37 } 38 Final()39 void Final() 40 { 41 const uint32_t u(uint32_t(128) << (8U * (byte_pos % 4U))); 42 x[byte_pos / 4U] ^= u; 43 transform(block_rounds); 44 x[31U] ^= 1U; 45 transform(final_rounds); 46 for (unsigned i = 0;i < hashbytelen;++i) 47 hashval[i] = static_cast<unsigned char>(x[i / 4U] >> (8U * (i % 4U))); 48 } 49 50 protected: 51 const unsigned int initial_rounds; 52 const unsigned int block_rounds; 53 const unsigned int final_rounds; 54 const unsigned int bytes_per_block; 55 const unsigned int hashbytelen; 56 unsigned int byte_pos; ///< number of bytes read into x from current block 57 uint32_t x[32]; 58 ROTATE(uint32_t a,uint32_t b)59 uint32_t ROTATE(uint32_t a, uint32_t b) { return (a << b) | (a >> (32U - b)); } 60 transform(unsigned int rounds)61 void transform(unsigned int rounds) 62 { 63 enum { HALF_LENGTH = (sizeof x/sizeof *x) / 2 }; 64 uint32_t y[HALF_LENGTH]; 65 66 for (unsigned r = rounds;r > 0;--r) { 67 for (unsigned i = 0;i < HALF_LENGTH;++i) x[i + HALF_LENGTH] += x[i]; 68 for (unsigned i = 0;i < HALF_LENGTH;++i) y[i ^ 8] = x[i]; 69 for (unsigned i = 0;i < HALF_LENGTH;++i) x[i] = ROTATE(y[i],7); 70 for (unsigned i = 0;i < HALF_LENGTH;++i) x[i] ^= x[i + HALF_LENGTH]; 71 for (unsigned i = 0;i < HALF_LENGTH;++i) y[i ^ 2] = x[i + HALF_LENGTH]; 72 for (unsigned i = 0;i < HALF_LENGTH;++i) x[i + HALF_LENGTH] = y[i]; 73 for (unsigned i = 0;i < HALF_LENGTH;++i) x[i + HALF_LENGTH] += x[i]; 74 for (unsigned i = 0;i < HALF_LENGTH;++i) y[i ^ 4] = x[i]; 75 for (unsigned i = 0;i < HALF_LENGTH;++i) x[i] = ROTATE(y[i],11); 76 for (unsigned i = 0;i < HALF_LENGTH;++i) x[i] ^= x[i + HALF_LENGTH]; 77 for (unsigned i = 0;i < HALF_LENGTH;++i) y[i ^ 1] = x[i + HALF_LENGTH]; 78 for (unsigned i = 0;i < HALF_LENGTH;++i) x[i + HALF_LENGTH] = y[i]; 79 } 80 } 81 Init()82 void Init() 83 { 84 if (hashbytelen < 1 || hashbytelen > 64 || hashbytelen > (sizeof hashval/sizeof *hashval)) 85 throw "invalid hash length"; 86 if (!initial_rounds || !block_rounds || !final_rounds) 87 throw "invalid number of rounds"; 88 if (bytes_per_block < 1 || bytes_per_block > (4U * (sizeof x/sizeof *x))) 89 throw "invalid number of bytes per block"; 90 91 x[0] = hashbytelen; 92 x[1] = bytes_per_block; 93 x[2] = block_rounds; 94 for (unsigned i = 3;i < (sizeof x/sizeof *x);++i) x[i] = 0; 95 transform(initial_rounds); 96 } 97 }; 98