mirror of https://github.com/PurpleI2P/i2pd.git
orignal
7 years ago
5 changed files with 656 additions and 0 deletions
@ -0,0 +1,147 @@ |
|||||||
|
#include "ChaCha20.h" |
||||||
|
|
||||||
|
/**
|
||||||
|
This code is licensed under the MCGSI Public License |
||||||
|
Copyright 2018 Jeff Becker |
||||||
|
|
||||||
|
Kovri go write your own code |
||||||
|
|
||||||
|
*/ |
||||||
|
namespace i2p |
||||||
|
{ |
||||||
|
namespace crypto |
||||||
|
{ |
||||||
|
namespace chacha |
||||||
|
{ |
||||||
|
constexpr int rounds = 20; |
||||||
|
constexpr std::size_t blocksize = 64; |
||||||
|
|
||||||
|
void u32t8le(uint32_t v, uint8_t * p) |
||||||
|
{ |
||||||
|
p[0] = v & 0xff; |
||||||
|
p[1] = (v >> 8) & 0xff; |
||||||
|
p[2] = (v >> 16) & 0xff; |
||||||
|
p[3] = (v >> 24) & 0xff; |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t u8t32le(const uint8_t * p) |
||||||
|
{ |
||||||
|
uint32_t value = p[3]; |
||||||
|
|
||||||
|
value = (value << 8) | p[2]; |
||||||
|
value = (value << 8) | p[1]; |
||||||
|
value = (value << 8) | p[0]; |
||||||
|
|
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t rotl32(uint32_t x, int n) |
||||||
|
{ |
||||||
|
return x << n | (x >> (-n & 31)); |
||||||
|
} |
||||||
|
|
||||||
|
void quarterround(uint32_t *x, int a, int b, int c, int d) |
||||||
|
{ |
||||||
|
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16); |
||||||
|
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12); |
||||||
|
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8); |
||||||
|
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7); |
||||||
|
} |
||||||
|
|
||||||
|
struct State_t |
||||||
|
{ |
||||||
|
State_t() {}; |
||||||
|
State_t(State_t &&) = delete; |
||||||
|
|
||||||
|
State_t & operator += (const State_t & other) |
||||||
|
{ |
||||||
|
for(int i = 0; i < 16; i++) |
||||||
|
data[i] += other.data[i]; |
||||||
|
return *this; |
||||||
|
} |
||||||
|
|
||||||
|
void Copy(const State_t & other) |
||||||
|
{ |
||||||
|
memcpy(data, other.data, sizeof(uint32_t) * 16); |
||||||
|
} |
||||||
|
uint32_t data[16]; |
||||||
|
}; |
||||||
|
|
||||||
|
struct Block_t |
||||||
|
{ |
||||||
|
Block_t() {}; |
||||||
|
Block_t(Block_t &&) = delete; |
||||||
|
|
||||||
|
uint8_t data[blocksize]; |
||||||
|
|
||||||
|
void operator << (const State_t & st) |
||||||
|
{ |
||||||
|
int i; |
||||||
|
for (i = 0; i < 16; i++) |
||||||
|
u32t8le(st.data[i], data + (i << 2)); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
void block(const State_t &input, Block_t & block, int rounds) |
||||||
|
{ |
||||||
|
int i; |
||||||
|
State_t x; |
||||||
|
x.Copy(input); |
||||||
|
|
||||||
|
for (i = rounds; i > 0; i -= 2) |
||||||
|
{ |
||||||
|
quarterround(x.data, 0, 4, 8, 12); |
||||||
|
quarterround(x.data, 1, 5, 9, 13); |
||||||
|
quarterround(x.data, 2, 6, 10, 14); |
||||||
|
quarterround(x.data, 3, 7, 11, 15); |
||||||
|
quarterround(x.data, 0, 5, 10, 15); |
||||||
|
quarterround(x.data, 1, 6, 11, 12); |
||||||
|
quarterround(x.data, 2, 7, 8, 13); |
||||||
|
quarterround(x.data, 3, 4, 9, 14); |
||||||
|
} |
||||||
|
x += input; |
||||||
|
block << x; |
||||||
|
|
||||||
|
} |
||||||
|
} // namespace chacha
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter) |
||||||
|
{ |
||||||
|
chacha::State_t state; |
||||||
|
chacha::Block_t block; |
||||||
|
size_t i, j; |
||||||
|
|
||||||
|
state.data[0] = 0x61707865; |
||||||
|
state.data[1] = 0x3320646e; |
||||||
|
state.data[2] = 0x79622d32; |
||||||
|
state.data[3] = 0x6b206574; |
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) |
||||||
|
state.data[4 + i] = chacha::u8t32le(key + i * 4); |
||||||
|
|
||||||
|
|
||||||
|
state.data[12] = counter; |
||||||
|
|
||||||
|
for (i = 0; i < 3; i++) |
||||||
|
state.data[13 + i] = chacha::u8t32le(nonce + i * 4); |
||||||
|
|
||||||
|
|
||||||
|
for (i = 0; i < sz; i += chacha::blocksize) |
||||||
|
{ |
||||||
|
chacha::block(state, block, chacha::rounds); |
||||||
|
state.data[12]++; |
||||||
|
for (j = i; j < i + chacha::blocksize; j++) |
||||||
|
{ |
||||||
|
if (j >= sz) break; |
||||||
|
buf[j] ^= block.data[j - i]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
/**
|
||||||
|
This code is licensed under the MCGSI Public License |
||||||
|
Copyright 2018 Jeff Becker |
||||||
|
|
||||||
|
Kovri go write your own code |
||||||
|
|
||||||
|
*/ |
||||||
|
#ifndef LIBI2PD_CHACHA20_H |
||||||
|
#define LIBI2PD_CHACHA20_H |
||||||
|
#include <cstdint> |
||||||
|
#include <cstring> |
||||||
|
|
||||||
|
namespace i2p |
||||||
|
{ |
||||||
|
namespace crypto |
||||||
|
{ |
||||||
|
const std::size_t CHACHA20_KEY_BYTES = 32; |
||||||
|
const std::size_t CHACHA20_NOUNCE_BYTES = 12; |
||||||
|
|
||||||
|
/** encrypt buf in place with chacha20 */ |
||||||
|
void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter=1); |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,303 @@ |
|||||||
|
#include "Poly1305.h" |
||||||
|
#include "CPU.h" |
||||||
|
#include <immintrin.h> |
||||||
|
/**
|
||||||
|
This code is licensed under the MCGSI Public License |
||||||
|
Copyright 2018 Jeff Becker |
||||||
|
|
||||||
|
Kovri go write your own code |
||||||
|
|
||||||
|
*/ |
||||||
|
namespace i2p |
||||||
|
{ |
||||||
|
namespace crypto |
||||||
|
{ |
||||||
|
#if 0 |
||||||
|
#ifdef __AVX2__ |
||||||
|
struct Poly1305_AVX2 |
||||||
|
{ |
||||||
|
Poly1305_AVX2(const uint32_t *& k) |
||||||
|
{ |
||||||
|
__asm__ |
||||||
|
( |
||||||
|
"VMOVNTDQA %[key0], %%ymm0 \n" |
||||||
|
"VMOVNTDQA 32%[key0], %%ymm1 \n" |
||||||
|
: |
||||||
|
: |
||||||
|
[key0]"m"(k) |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
~Poly1305_AVX2() |
||||||
|
{ |
||||||
|
// clear out registers
|
||||||
|
__asm__ |
||||||
|
( |
||||||
|
"VZEROALL\n" |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
void Update(const uint8_t * buf, size_t sz) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void Finish(uint32_t *& out) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_t leftover; |
||||||
|
|
||||||
|
}; |
||||||
|
#endif |
||||||
|
#endif |
||||||
|
namespace poly1305 |
||||||
|
{ |
||||||
|
|
||||||
|
struct LongBlock |
||||||
|
{ |
||||||
|
unsigned long data[17]; |
||||||
|
operator unsigned long * () |
||||||
|
{ |
||||||
|
return data; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
struct Block |
||||||
|
{ |
||||||
|
unsigned char data[17]; |
||||||
|
|
||||||
|
operator uint8_t * () |
||||||
|
{ |
||||||
|
return data; |
||||||
|
} |
||||||
|
|
||||||
|
Block & operator += (const Block & other) |
||||||
|
{ |
||||||
|
unsigned short u; |
||||||
|
unsigned int i; |
||||||
|
for(u = 0, i = 0; i < 17; i++) |
||||||
|
{ |
||||||
|
u += (unsigned short) data[i] + (unsigned short) other.data[i]; |
||||||
|
data[i] = (unsigned char) u & 0xff; |
||||||
|
u >>= 8; |
||||||
|
} |
||||||
|
return *this; |
||||||
|
} |
||||||
|
|
||||||
|
Block & operator %=(const LongBlock & other) |
||||||
|
{ |
||||||
|
unsigned long u; |
||||||
|
unsigned int i; |
||||||
|
u = 0; |
||||||
|
for (i = 0; i < 16; i++) { |
||||||
|
u += other.data[i]; |
||||||
|
data[i] = (unsigned char)u & 0xff; |
||||||
|
u >>= 8; |
||||||
|
} |
||||||
|
u += other.data[16]; |
||||||
|
data[16] = (unsigned char)u & 0x03; |
||||||
|
u >>= 2; |
||||||
|
u += (u << 2); |
||||||
|
for (i = 0; i < 16; i++) { |
||||||
|
u += data[i]; |
||||||
|
data[i] = (unsigned char)u & 0xff; |
||||||
|
u >>= 8; |
||||||
|
} |
||||||
|
data[16] += (unsigned char)u; |
||||||
|
return *this; |
||||||
|
} |
||||||
|
|
||||||
|
Block & operator = (const Block & other) |
||||||
|
{ |
||||||
|
memcpy(data, other.data, sizeof(data)); |
||||||
|
return *this; |
||||||
|
} |
||||||
|
|
||||||
|
Block & operator ~ () |
||||||
|
{ |
||||||
|
static const Block minusp = { |
||||||
|
0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
||||||
|
0xfc |
||||||
|
}; |
||||||
|
Block orig; |
||||||
|
unsigned char neg; |
||||||
|
unsigned int i; |
||||||
|
orig = *this; |
||||||
|
*this += minusp; |
||||||
|
neg = -(data[16] >> 7); |
||||||
|
for(i = 0; i < 17; i++) |
||||||
|
data[i] ^= neg & (orig.data[i] ^ data[i]); |
||||||
|
|
||||||
|
return *this; |
||||||
|
} |
||||||
|
|
||||||
|
void PutKey(const uint8_t * key) |
||||||
|
{ |
||||||
|
data[0] = key[0] & 0xff; |
||||||
|
data[1] = key[1] & 0xff; |
||||||
|
data[2] = key[2] & 0xff; |
||||||
|
data[3] = key[3] & 0x0f; |
||||||
|
data[4] = key[4] & 0xfc; |
||||||
|
data[5] = key[5] & 0xff; |
||||||
|
data[6] = key[6] & 0xff; |
||||||
|
data[7] = key[7] & 0x0f; |
||||||
|
data[8] = key[8] & 0xfc; |
||||||
|
data[9] = key[9] & 0xff; |
||||||
|
data[10] = key[10] & 0xff; |
||||||
|
data[11] = key[11] & 0x0f; |
||||||
|
data[12] = key[12] & 0xfc; |
||||||
|
data[13] = key[13] & 0xff; |
||||||
|
data[14] = key[14] & 0xff; |
||||||
|
data[15] = key[15] & 0x0f; |
||||||
|
data[16] = 0; |
||||||
|
} |
||||||
|
|
||||||
|
void Put(const uint8_t * d, uint8_t last=0) |
||||||
|
{ |
||||||
|
memcpy(data, d, 17); |
||||||
|
data[16] = last; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
struct Buffer |
||||||
|
{ |
||||||
|
uint8_t data[POLY1305_BLOCK_BYTES]; |
||||||
|
|
||||||
|
operator uint8_t * () |
||||||
|
{ |
||||||
|
return data; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
struct Poly1305 |
||||||
|
{ |
||||||
|
|
||||||
|
Poly1305(const uint8_t * key) : m_Leftover(0), m_H{0}, m_Final(0) |
||||||
|
{ |
||||||
|
m_R.PutKey(key); |
||||||
|
m_Pad.Put(key + 16); |
||||||
|
} |
||||||
|
|
||||||
|
void Update(const uint8_t * buf, size_t sz) |
||||||
|
{ |
||||||
|
// process leftover
|
||||||
|
if(m_Leftover) |
||||||
|
{ |
||||||
|
size_t want = POLY1305_BLOCK_BYTES - m_Leftover; |
||||||
|
if(want > sz) want = sz; |
||||||
|
memcpy(m_Buffer + m_Leftover, buf, want); |
||||||
|
sz -= want; |
||||||
|
buf += want; |
||||||
|
m_Leftover += want; |
||||||
|
if(m_Leftover < POLY1305_BLOCK_BYTES) return; |
||||||
|
Blocks(m_Buffer, POLY1305_BLOCK_BYTES); |
||||||
|
m_Leftover = 0; |
||||||
|
} |
||||||
|
// process blocks
|
||||||
|
if(sz >= POLY1305_BLOCK_BYTES) |
||||||
|
{ |
||||||
|
size_t want = (sz & ~(POLY1305_BLOCK_BYTES - 1)); |
||||||
|
Blocks(buf, want); |
||||||
|
buf += want; |
||||||
|
sz -= want; |
||||||
|
} |
||||||
|
// leftover
|
||||||
|
if(sz) |
||||||
|
{ |
||||||
|
memcpy(m_Buffer+m_Leftover, buf, sz); |
||||||
|
m_Leftover += sz; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void Blocks(const uint8_t * buf, size_t sz) |
||||||
|
{ |
||||||
|
const unsigned char hi = m_Final ^ 1; |
||||||
|
while (sz >= POLY1305_BLOCK_BYTES) { |
||||||
|
|
||||||
|
unsigned long u; |
||||||
|
|
||||||
|
unsigned int i, j; |
||||||
|
m_Msg.Put(buf, hi); |
||||||
|
/* h += m */ |
||||||
|
m_H += m_Msg; |
||||||
|
|
||||||
|
/* h *= r */ |
||||||
|
for (i = 0; i < 17; i++) { |
||||||
|
u = 0; |
||||||
|
for (j = 0; j <= i ; j++) { |
||||||
|
u += (unsigned short)m_H.data[j] * m_R.data[i - j]; |
||||||
|
} |
||||||
|
for (j = i + 1; j < 17; j++) { |
||||||
|
unsigned long v = (unsigned short)m_H.data[j] * m_R.data[i + 17 - j]; |
||||||
|
v = ((v << 8) + (v << 6)); /* v *= (5 << 6); */ |
||||||
|
u += v; |
||||||
|
} |
||||||
|
m_HR[i] = u; |
||||||
|
} |
||||||
|
/* (partial) h %= p */ |
||||||
|
m_H %= m_HR; |
||||||
|
buf += POLY1305_BLOCK_BYTES; |
||||||
|
sz -= POLY1305_BLOCK_BYTES; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void Finish(uint32_t *& out) |
||||||
|
{ |
||||||
|
// process leftovers
|
||||||
|
if(m_Leftover) |
||||||
|
{ |
||||||
|
size_t idx = m_Leftover; |
||||||
|
m_Buffer[idx++] = 1; |
||||||
|
for(; idx < POLY1305_BLOCK_BYTES; idx++) |
||||||
|
m_Buffer[idx] = 0; |
||||||
|
m_Final = 1; |
||||||
|
Blocks(m_Buffer, POLY1305_BLOCK_BYTES); |
||||||
|
} |
||||||
|
|
||||||
|
// freeze H
|
||||||
|
~m_H; |
||||||
|
// add pad
|
||||||
|
m_H += m_Pad; |
||||||
|
// copy digest
|
||||||
|
memcpy(out, m_H, 16); |
||||||
|
} |
||||||
|
|
||||||
|
size_t m_Leftover; |
||||||
|
poly1305::Buffer m_Buffer; |
||||||
|
poly1305::Block m_H; |
||||||
|
poly1305::Block m_R; |
||||||
|
poly1305::Block m_Pad; |
||||||
|
poly1305::Block m_Msg; |
||||||
|
poly1305::LongBlock m_HR; |
||||||
|
uint8_t m_Final; |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
void Poly1305HMAC(uint32_t * out, const uint32_t * key, const uint8_t * buf, std::size_t sz) |
||||||
|
{ |
||||||
|
#if 0 |
||||||
|
#ifdef __AVX2__ |
||||||
|
if(i2p::cpu::avx2) |
||||||
|
{ |
||||||
|
Poly1305_AVX2 p(key); |
||||||
|
p.Update(buf, sz); |
||||||
|
p.Finish(out); |
||||||
|
} |
||||||
|
else |
||||||
|
#endif |
||||||
|
#endif |
||||||
|
{ |
||||||
|
const uint8_t * k = (const uint8_t *) key; |
||||||
|
Poly1305 p(k); |
||||||
|
p.Update(buf, sz); |
||||||
|
p.Finish(out); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
/**
|
||||||
|
This code is licensed under the MCGSI Public License |
||||||
|
Copyright 2018 Jeff Becker |
||||||
|
|
||||||
|
Kovri go write your own code |
||||||
|
|
||||||
|
*/ |
||||||
|
#ifndef LIBI2PD_POLY1305_H |
||||||
|
#define LIBI2PD_POLY1305_H |
||||||
|
#include <cstdint> |
||||||
|
#include <cstring> |
||||||
|
|
||||||
|
namespace i2p |
||||||
|
{ |
||||||
|
namespace crypto |
||||||
|
{ |
||||||
|
const std::size_t POLY1305_DIGEST_BYTES = 16; |
||||||
|
const std::size_t POLY1305_DIGEST_DWORDS = 4; |
||||||
|
const std::size_t POLY1305_KEY_BYTES = 32; |
||||||
|
const std::size_t POLY1305_KEY_DWORDS = 8; |
||||||
|
const std::size_t POLY1305_BLOCK_BYTES = 16; |
||||||
|
|
||||||
|
void Poly1305HMAC(uint32_t * out, const uint32_t * key, const uint8_t * buf, std::size_t sz); |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,152 @@ |
|||||||
|
/**
|
||||||
|
This code is licensed under the MCGSI Public License |
||||||
|
Copyright 2018 Jeff Becker |
||||||
|
|
||||||
|
Kovri go write your own code |
||||||
|
|
||||||
|
*/ |
||||||
|
#ifndef SIPHASH_H |
||||||
|
#define SIPHASH_H |
||||||
|
|
||||||
|
#include <cstdint> |
||||||
|
|
||||||
|
namespace i2p |
||||||
|
{ |
||||||
|
namespace crypto |
||||||
|
{ |
||||||
|
namespace siphash |
||||||
|
{ |
||||||
|
constexpr int crounds = 2; |
||||||
|
constexpr int drounds = 4; |
||||||
|
|
||||||
|
uint64_t rotl(const uint64_t & x, int b) |
||||||
|
{ |
||||||
|
uint64_t ret = x << b; |
||||||
|
ret |= x >> (64 - b); |
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
void u32to8le(const uint32_t & v, uint8_t * p) |
||||||
|
{ |
||||||
|
p[0] = (uint8_t) v; |
||||||
|
p[1] = (uint8_t) (v >> 8); |
||||||
|
p[2] = (uint8_t) (v >> 16); |
||||||
|
p[3] = (uint8_t) (v >> 24); |
||||||
|
} |
||||||
|
|
||||||
|
void u64to8le(const uint64_t & v, uint8_t * p) |
||||||
|
{ |
||||||
|
p[0] = v & 0xff; |
||||||
|
p[1] = (v >> 8) & 0xff; |
||||||
|
p[2] = (v >> 16) & 0xff; |
||||||
|
p[3] = (v >> 24) & 0xff; |
||||||
|
p[4] = (v >> 32) & 0xff; |
||||||
|
p[5] = (v >> 40) & 0xff; |
||||||
|
p[6] = (v >> 48) & 0xff; |
||||||
|
p[7] = (v >> 56) & 0xff; |
||||||
|
} |
||||||
|
|
||||||
|
uint64_t u8to64le(const uint8_t * p) |
||||||
|
{ |
||||||
|
uint64_t i = 0; |
||||||
|
int idx = 0; |
||||||
|
while(idx < 8) |
||||||
|
{ |
||||||
|
i |= ((uint64_t) p[idx]) << (idx * 8); |
||||||
|
++idx; |
||||||
|
} |
||||||
|
return i; |
||||||
|
} |
||||||
|
|
||||||
|
void round(uint64_t & _v0, uint64_t & _v1, uint64_t & _v2, uint64_t & _v3) |
||||||
|
{ |
||||||
|
_v0 += _v1; |
||||||
|
_v1 = rotl(_v1, 13); |
||||||
|
_v1 ^= _v0; |
||||||
|
_v0 = rotl(_v0, 32); |
||||||
|
_v2 += _v3; |
||||||
|
_v3 = rotl(_v3, 16); |
||||||
|
_v3 ^= _v2; |
||||||
|
_v0 += _v3; |
||||||
|
_v3 = rotl(_v3, 21); |
||||||
|
_v3 ^= _v0; |
||||||
|
_v2 += _v1; |
||||||
|
_v1 = rotl(_v1, 17); |
||||||
|
_v1 ^= _v2; |
||||||
|
_v2 = rotl(_v2, 32); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** hashsz must be 8 or 16 */ |
||||||
|
template<std::size_t hashsz> |
||||||
|
void Siphash(uint8_t * h, const uint8_t * buf, std::size_t bufsz, const uint8_t * key) |
||||||
|
{ |
||||||
|
uint64_t v0 = 0x736f6d6570736575ULL; |
||||||
|
uint64_t v1 = 0x646f72616e646f6dULL; |
||||||
|
uint64_t v2 = 0x6c7967656e657261ULL; |
||||||
|
uint64_t v3 = 0x7465646279746573ULL; |
||||||
|
const uint64_t k0 = siphash::u8to64le(key); |
||||||
|
const uint64_t k1 = siphash::u8to64le(key + 8); |
||||||
|
uint64_t msg; |
||||||
|
int i; |
||||||
|
const uint8_t * end = buf + bufsz - (bufsz % sizeof(uint64_t)); |
||||||
|
auto left = bufsz & 7; |
||||||
|
uint64_t b = ((uint64_t)bufsz) << 56; |
||||||
|
v3 ^= k1; |
||||||
|
v2 ^= k0; |
||||||
|
v1 ^= k1; |
||||||
|
v0 ^= k0; |
||||||
|
|
||||||
|
if(hashsz == 16) v1 ^= 0xee; |
||||||
|
|
||||||
|
while(buf != end) |
||||||
|
{ |
||||||
|
msg = siphash::u8to64le(buf); |
||||||
|
v3 ^= msg; |
||||||
|
for(i = 0; i < siphash::crounds; ++i) |
||||||
|
siphash::round(v0, v1, v2, v3); |
||||||
|
|
||||||
|
v0 ^= msg; |
||||||
|
buf += 8; |
||||||
|
} |
||||||
|
|
||||||
|
while(left) |
||||||
|
{ |
||||||
|
--left; |
||||||
|
b |= ((uint64_t)(buf[left])) << (left * 8); |
||||||
|
} |
||||||
|
|
||||||
|
v3 ^= b; |
||||||
|
|
||||||
|
for(i = 0; i < siphash::crounds; ++i) |
||||||
|
siphash::round(v0, v1, v2, v3); |
||||||
|
|
||||||
|
v0 ^= b; |
||||||
|
|
||||||
|
|
||||||
|
if(hashsz == 16) |
||||||
|
v2 ^= 0xee; |
||||||
|
else |
||||||
|
v2 ^= 0xff; |
||||||
|
|
||||||
|
for(i = 0; i < siphash::drounds; ++i) |
||||||
|
siphash::round(v0, v1, v2, v3); |
||||||
|
|
||||||
|
b = v0 ^ v1 ^ v2 ^ v3; |
||||||
|
|
||||||
|
siphash::u64to8le(b, h); |
||||||
|
|
||||||
|
if(hashsz == 8) return; |
||||||
|
|
||||||
|
v1 ^= 0xdd; |
||||||
|
|
||||||
|
for (i = 0; i < siphash::drounds; ++i) |
||||||
|
siphash::round(v0, v1, v2, v3); |
||||||
|
|
||||||
|
b = v0 ^ v1 ^ v2 ^ v3; |
||||||
|
siphash::u64to8le(b, h + 8); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
Loading…
Reference in new issue