00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "HashSip.h"
00012 #include <cstring>
00013
00014 #define SIP_BLOCK_SIZE 8
00015
00016 #define ROTL64(a,b) (((a)<<(b))|((a)>>(64-b)))
00017
00018 #define U8TO64_LE(p) *(const uint64_t *)(p)
00019
00020 #define SIPCOMPRESS(x0,x1,x2,x3) \
00021 x0 += x1; \
00022 x2 += x3; \
00023 x1 = ROTL64(x1,13); \
00024 x3 = ROTL64(x3,16); \
00025 x1 ^= x0; \
00026 x3 ^= x2; \
00027 x0 = ROTL64(x0,32); \
00028 x2 += x1; \
00029 x0 += x3; \
00030 x1 = ROTL64(x1,17); \
00031 x3 = ROTL64(x3,21); \
00032 x1 ^= x2; \
00033 x3 ^= x0; \
00034 x2 = ROTL64(x2,32);
00035
00036 ATSHash64Sip24::ATSHash64Sip24(void)
00037 {
00038 k0 = 0;
00039 k1 = 0;
00040 this->clear();
00041 }
00042
00043 ATSHash64Sip24::ATSHash64Sip24(const unsigned char key[16])
00044 {
00045 k0 = U8TO64_LE(key);
00046 k1 = U8TO64_LE(key + sizeof(k0));
00047 this->clear();
00048 }
00049
00050 ATSHash64Sip24::ATSHash64Sip24(uint64_t key0, uint64_t key1)
00051 {
00052 k0 = key0;
00053 k1 = key1;
00054 this->clear();
00055 }
00056
00057 void
00058 ATSHash64Sip24::update(const void *data, size_t len)
00059 {
00060 size_t i, blocks;
00061 unsigned char *m;
00062 uint64_t mi;
00063 uint8_t block_off = 0;
00064
00065 if (!finalized) {
00066 m = (unsigned char *) data;
00067 total_len += len;
00068
00069 if (len + block_buffer_len < SIP_BLOCK_SIZE) {
00070 memcpy(block_buffer + block_buffer_len, m, len);
00071 block_buffer_len += len;
00072 } else {
00073 if (block_buffer_len > 0) {
00074 block_off = SIP_BLOCK_SIZE - block_buffer_len;
00075 memcpy(block_buffer + block_buffer_len, m, block_off);
00076
00077 mi = U8TO64_LE(block_buffer);
00078 v3 ^= mi;
00079 SIPCOMPRESS(v0, v1, v2, v3);
00080 SIPCOMPRESS(v0, v1, v2, v3);
00081 v0 ^= mi;
00082 }
00083
00084 for (i = block_off, blocks = ((len - block_off) & ~(SIP_BLOCK_SIZE - 1)); i < blocks; i += SIP_BLOCK_SIZE) {
00085 mi = U8TO64_LE(m + i);
00086 v3 ^= mi;
00087 SIPCOMPRESS(v0, v1, v2, v3);
00088 SIPCOMPRESS(v0, v1, v2, v3);
00089 v0 ^= mi;
00090 }
00091
00092 block_buffer_len = (len - block_off) & (SIP_BLOCK_SIZE - 1);
00093 memcpy(block_buffer, m + block_off + blocks, block_buffer_len);
00094 }
00095 }
00096 }
00097
00098 void
00099 ATSHash64Sip24::final(void)
00100 {
00101 uint64_t last7;
00102 int i;
00103
00104 if (!finalized) {
00105 last7 = (uint64_t) (total_len & 0xff) << 56;
00106
00107 for (i = block_buffer_len - 1; i >= 0; i--) {
00108 last7 |= (uint64_t) block_buffer[i] << (i * 8);
00109 }
00110
00111 v3 ^= last7;
00112 SIPCOMPRESS(v0, v1, v2, v3);
00113 SIPCOMPRESS(v0, v1, v2, v3);
00114 v0 ^= last7;
00115 v2 ^= 0xff;
00116 SIPCOMPRESS(v0, v1, v2, v3);
00117 SIPCOMPRESS(v0, v1, v2, v3);
00118 SIPCOMPRESS(v0, v1, v2, v3);
00119 SIPCOMPRESS(v0, v1, v2, v3);
00120 hfinal = v0 ^ v1 ^ v2 ^ v3;
00121 finalized = true;
00122 }
00123 }
00124
00125 uint64_t
00126 ATSHash64Sip24::get(void) const
00127 {
00128 if (finalized) {
00129 return hfinal;
00130 } else {
00131 return 0;
00132 }
00133 }
00134
00135 void
00136 ATSHash64Sip24::clear(void)
00137 {
00138 v0 = k0 ^ 0x736f6d6570736575ull;
00139 v1 = k1 ^ 0x646f72616e646f6dull;
00140 v2 = k0 ^ 0x6c7967656e657261ull;
00141 v3 = k1 ^ 0x7465646279746573ull;
00142 finalized = false;
00143 total_len = 0;
00144 block_buffer_len = 0;
00145 }