pulled updates from main repository (had to remove patches to double hash)

This commit is contained in:
aegroto 2018-05-06 22:37:16 +02:00
commit cd131d4953
80 changed files with 1525 additions and 3831 deletions

View file

@ -53,6 +53,7 @@ template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT>() { retur
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT_LITE>() { return CRYPTONIGHT_LITE_MEMORY; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT_HEAVY>() { return CRYPTONIGHT_HEAVY_MEMORY; }
inline size_t cn_select_memory(Algo algorithm)
{
switch(algorithm)
@ -79,6 +80,7 @@ template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT>() { retur
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT_LITE>() { return CRYPTONIGHT_LITE_MASK; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT_HEAVY>() { return CRYPTONIGHT_HEAVY_MASK; }
inline uint32_t cn_select_mask(Algo algorithm)
{
switch(algorithm)
@ -105,6 +107,7 @@ template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT>() { retur
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_LITE>() { return CRYPTONIGHT_LITE_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_HEAVY>() { return CRYPTONIGHT_HEAVY_ITER; }
inline uint32_t cn_select_iter(Algo algorithm)
{
switch(algorithm)

View file

@ -84,6 +84,21 @@ const static uint8_t test_output_v1[160] = {
};
// Stellite (XTL)
const static uint8_t test_output_xtl[160] = {
0x8F, 0xE5, 0xF0, 0x5F, 0x02, 0x2A, 0x61, 0x7D, 0xE5, 0x3F, 0x79, 0x36, 0x4B, 0x25, 0xCB, 0xC3,
0xC0, 0x8E, 0x0E, 0x1F, 0xE3, 0xBE, 0x48, 0x57, 0x07, 0x03, 0xFE, 0xE1, 0xEC, 0x0E, 0xB0, 0xB1,
0x21, 0x26, 0xFF, 0x98, 0xE6, 0x86, 0x08, 0x5B, 0xC9, 0x96, 0x44, 0xA3, 0xB8, 0x4E, 0x28, 0x90,
0x76, 0xED, 0xAD, 0xB9, 0xAA, 0xAC, 0x01, 0x94, 0x1D, 0xBE, 0x3E, 0xEA, 0xAD, 0xEE, 0xB2, 0xCF,
0xB0, 0x43, 0x4B, 0x88, 0xFC, 0xB2, 0xF3, 0x82, 0x9D, 0xD7, 0xDF, 0x51, 0x97, 0x2C, 0x5A, 0xE3,
0xC7, 0x16, 0x0B, 0xC8, 0x7C, 0xB7, 0x2F, 0x1C, 0x55, 0x33, 0xCA, 0xE1, 0xEE, 0x08, 0xA4, 0x86,
0x60, 0xED, 0x6E, 0x9D, 0x2D, 0x05, 0x0D, 0x7D, 0x02, 0x49, 0x23, 0x39, 0x7C, 0xC3, 0x6D, 0x3D,
0x05, 0x51, 0x28, 0xF1, 0x9B, 0x3C, 0xDF, 0xC4, 0xEA, 0x8A, 0xA6, 0x6A, 0x3C, 0x8B, 0xE2, 0xAF,
0x47, 0x00, 0xFC, 0x36, 0xED, 0x50, 0xBB, 0xD2, 0x2E, 0x63, 0x4B, 0x93, 0x11, 0x0C, 0xA7, 0xBA,
0x32, 0x6E, 0x47, 0x4D, 0xCE, 0xCC, 0x82, 0x54, 0x1D, 0x06, 0xF8, 0x06, 0x86, 0xBD, 0x22, 0x48
};
#ifndef XMRIG_NO_AEON
const static uint8_t test_output_v0_lite[160] = {
0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E,
@ -112,6 +127,21 @@ const static uint8_t test_output_v1_lite[160] = {
0x8C, 0x2B, 0xA4, 0x1F, 0x60, 0x76, 0x39, 0xD7, 0xF6, 0x46, 0x77, 0x18, 0x20, 0xAD, 0xD4, 0xC9,
0x87, 0xF7, 0x37, 0xDA, 0xFD, 0xBA, 0xBA, 0xD2, 0xF2, 0x68, 0xDC, 0x26, 0x8D, 0x1B, 0x08, 0xC6
};
// IPBC
const static uint8_t test_output_ipbc_lite[160] = {
0xE4, 0x93, 0x8C, 0xAA, 0x59, 0x8D, 0x02, 0x8A, 0xB8, 0x6F, 0x25, 0xD2, 0xB1, 0x23, 0xD0, 0xD5,
0x33, 0xE3, 0x9F, 0x37, 0xAC, 0xE5, 0xF8, 0xEB, 0x7A, 0xE8, 0x40, 0xEB, 0x5D, 0xB1, 0x35, 0x5F,
0xB2, 0x47, 0x86, 0xF0, 0x7F, 0x6F, 0x4B, 0x55, 0x3E, 0xA1, 0xBB, 0xE8, 0xA1, 0x75, 0x00, 0x2D,
0x07, 0x9A, 0x21, 0x0E, 0xBD, 0x06, 0x6A, 0xB0, 0xFD, 0x96, 0x9E, 0xE6, 0xE4, 0x69, 0x67, 0xBB,
0x88, 0x45, 0x0B, 0x91, 0x0B, 0x7B, 0xCB, 0x21, 0x3C, 0x3C, 0x09, 0x30, 0x07, 0x71, 0x07, 0xD5,
0xB8, 0x2D, 0x83, 0x09, 0xAF, 0x7E, 0xB2, 0xA8, 0xAC, 0x25, 0xDC, 0x10, 0xF8, 0x63, 0x6A, 0xBC,
0x73, 0x01, 0x4E, 0xA8, 0x1C, 0xDA, 0x9A, 0x86, 0x17, 0xEC, 0xA8, 0xFB, 0xAA, 0x23, 0x23, 0x17,
0xE1, 0x32, 0x68, 0x9C, 0x4C, 0xF4, 0x08, 0xED, 0xB0, 0x15, 0xC3, 0xA9, 0x0F, 0xF0, 0xA2, 0x7E,
0xD9, 0xE4, 0x23, 0xA7, 0x9E, 0x91, 0xD8, 0x73, 0x94, 0xD6, 0x6C, 0x70, 0x9B, 0x8B, 0x72, 0x92,
0xA3, 0xA4, 0x0A, 0xE2, 0x3C, 0x0A, 0x34, 0x88, 0xA1, 0x6D, 0xFE, 0x02, 0x44, 0x60, 0x7B, 0x3D
};
#endif

View file

@ -35,6 +35,7 @@
#endif
#include "common/crypto/keccak.h"
#include "crypto/CryptoNight.h"
#include "crypto/CryptoNight_constants.h"
#include "crypto/CryptoNight_monero.h"
@ -43,7 +44,6 @@
extern "C"
{
#include "crypto/c_keccak.h"
#include "crypto/c_groestl.h"
#include "crypto/c_blake256.h"
#include "crypto/c_jh.h"
@ -389,6 +389,7 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
}
template<int SHIFT>
static inline void cryptonight_monero_tweak(uint64_t* mem_out, __m128i tmp)
{
mem_out[0] = EXTRACT64(tmp);
@ -398,12 +399,14 @@ static inline void cryptonight_monero_tweak(uint64_t* mem_out, __m128i tmp)
uint8_t x = vh >> 24;
static const uint16_t table = 0x7531;
vh ^= ((table >> ((((x >> 3) & 6) | (x & 1)) << 1)) & 0x3) << 28;
const uint8_t index = (((x >> SHIFT) & 6) | (x & 1)) << 1;
vh ^= ((table >> index) & 0x3) << 28;
mem_out[1] = vh;
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
@ -416,7 +419,7 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
return;
}
keccak(input, (int) size, ctx[0]->state, 200);
xmrig::keccak(input, size, ctx[0]->state);
VARIANT1_INIT(0)
@ -429,22 +432,27 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
uint64_t ah0 = h0[1] ^ h0[5];
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
uint64_t idx0 = h0[0] ^ h0[4];
void* mp = ((uint8_t*) l0) + ((idx0) & MASK);
uint64_t idx0 = al0;
void* mp = ((uint8_t*) l0) + (idx0 & MASK);
for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx;
if (SOFT_AES) {
cx = soft_aesenc((uint32_t*) mp, _mm_set_epi64x(ah0, al0));
} else {
cx = soft_aesenc((uint32_t*) mp, _mm_set_epi64x(ah0, al0));
}
else {
cx = _mm_load_si128((__m128i *) mp);
cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
}
_mm_store_si128((__m128i *) mp, _mm_xor_si128(bx0, cx));
VARIANT1_1(mp);
mp = ((uint8_t*) l0) + ((idx0 = EXTRACT64(cx)) & MASK);
if (VARIANT > 0) {
cryptonight_monero_tweak<VARIANT == xmrig::VARIANT_XTL ? 4 : 3>((uint64_t*) mp, _mm_xor_si128(bx0, cx));
} else {
_mm_store_si128((__m128i *) mp, _mm_xor_si128(bx0, cx));
}
mp = (void*) &l0[(idx0 = EXTRACT64(cx)) & MASK];
bx0 = cx;
uint64_t hi, lo, cl, ch;
@ -455,30 +463,39 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
al0 += hi;
ah0 += lo;
VARIANT1_2(ah0, 0);
((uint64_t*) mp)[0] = al0;
((uint64_t*) mp)[1] = ah0;
VARIANT1_2(ah0, 0);
ah0 ^= ch;
if (VARIANT > 0) {
if (VARIANT == xmrig::VARIANT_IPBC) {
((uint64_t*) mp)[1] = ah0 ^ tweak1_2_0 ^ al0;
}
else {
((uint64_t*) mp)[1] = ah0 ^ tweak1_2_0;
}
}
else {
((uint64_t*) mp)[1] = ah0;
}
al0 ^= cl;
mp = ((uint8_t*) l0) + ((al0) & MASK);
ah0 ^= ch;
mp = (void*) &l0[al0 & MASK];
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
int64_t n = ((int64_t*)mp)[0];
int32_t d = ((int32_t*)mp)[2];
int64_t n = ((int64_t*) mp)[0];
int32_t d = ((int32_t*) mp)[2];
int64_t q = n / (d | 0x5);
((int64_t*) mp)[0] = n ^ q;
((int64_t*) mp)[0] = n ^ q;
}
}
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx[0]->memory, (__m128i*) ctx[0]->state);
keccakf(h0, 24);
xmrig::keccakf(h0, 24);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
@ -491,8 +508,8 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
return;
}
keccak(input, (int) size, ctx[0]->state, 200);
keccak(input + size, (int) size, ctx[1]->state, 200);
xmrig::keccak(input, size, ctx[0]->state);
xmrig::keccak(input + size, size, ctx[1]->state);
VARIANT1_INIT(0);
VARIANT1_INIT(1);
@ -516,91 +533,109 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
uint64_t idx0 = al0;
uint64_t idx1 = al1;
void* mp0 = ((uint8_t*) l0) + ((idx0) & MASK);
void* mp1 = ((uint8_t*) l1) + ((idx1) & MASK);
for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx0, cx1;
if (SOFT_AES) {
cx0 = soft_aesenc((uint32_t*) mp0, _mm_set_epi64x(ah0, al0));
cx1 = soft_aesenc((uint32_t*) mp1, _mm_set_epi64x(ah1, al1));
} else {
cx0 = _mm_load_si128((__m128i *) mp0);
cx1 = _mm_load_si128((__m128i *)mp1);
cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0));
cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1));
}
else {
cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
}
if (VARIANT > 0) {
cryptonight_monero_tweak((uint64_t*)mp0, _mm_xor_si128(bx0, cx0));
cryptonight_monero_tweak((uint64_t*)mp1, _mm_xor_si128(bx1, cx1));
cryptonight_monero_tweak<VARIANT == xmrig::VARIANT_XTL ? 4 : 3>((uint64_t*)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
cryptonight_monero_tweak<VARIANT == xmrig::VARIANT_XTL ? 4 : 3>((uint64_t*)&l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
} else {
_mm_store_si128((__m128i *) mp0, _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i *) mp1, _mm_xor_si128(bx1, cx1));
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
}
mp0 = ((uint8_t*) l0) + ((idx0 = EXTRACT64(cx0)) & MASK);
mp1 = ((uint8_t*) l1) + ((idx1 = EXTRACT64(cx1)) & MASK);
idx0 = EXTRACT64(cx0);
idx1 = EXTRACT64(cx1);
bx0 = cx0;
bx1 = cx1;
uint64_t hi, lo, cl, ch;
cl = ((uint64_t*) mp0)[0];
ch = ((uint64_t*) mp0)[1];
cl = ((uint64_t*) &l0[idx0 & MASK])[0];
ch = ((uint64_t*) &l0[idx0 & MASK])[1];
lo = __umul128(idx0, cl, &hi);
al0 += hi;
ah0 += lo;
VARIANT1_2(ah0, 0);
((uint64_t*) mp0)[0] = al0;
((uint64_t*) mp0)[1] = ah0;
VARIANT1_2(ah0, 0);
((uint64_t*)&l0[idx0 & MASK])[0] = al0;
ah0 ^= ch;
al0 ^= cl;
mp0 = ((uint8_t*) l0) + ((al0) & MASK);
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
int64_t n = ((int64_t*)mp0)[0];
int32_t d = ((int32_t*)mp0)[2];
int64_t q = n / (d | 0x5);
((int64_t*) mp0)[0] = n ^ q;
if (VARIANT > 0) {
if (VARIANT == xmrig::VARIANT_IPBC) {
((uint64_t*)&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0 ^ al0;
}
else {
((uint64_t*)&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0;
}
}
else {
((uint64_t*)&l0[idx0 & MASK])[1] = ah0;
}
cl = ((uint64_t*) mp1)[0];
ch = ((uint64_t*) mp1)[1];
al0 ^= cl;
ah0 ^= ch;
idx0 = al0;
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
int64_t n = ((int64_t*)&l0[idx0 & MASK])[0];
int32_t d = ((int32_t*)&l0[idx0 & MASK])[2];
int64_t q = n / (d | 0x5);
((int64_t*)&l0[idx0 & MASK])[0] = n ^ q;
idx0 = d ^ q;
}
cl = ((uint64_t*) &l1[idx1 & MASK])[0];
ch = ((uint64_t*) &l1[idx1 & MASK])[1];
lo = __umul128(idx1, cl, &hi);
al1 += hi;
ah1 += lo;
VARIANT1_2(ah1, 1);
((uint64_t*) mp1)[0] = al1;
((uint64_t*) mp1)[1] = ah1;
VARIANT1_2(ah1, 1);
((uint64_t*)&l1[idx1 & MASK])[0] = al1;
if (VARIANT > 0) {
if (VARIANT == xmrig::VARIANT_IPBC) {
((uint64_t*)&l1[idx1 & MASK])[1] = ah1 ^ tweak1_2_1 ^ al1;
}
else {
((uint64_t*)&l1[idx1 & MASK])[1] = ah1 ^ tweak1_2_1;
}
}
else {
((uint64_t*)&l1[idx1 & MASK])[1] = ah1;
}
ah1 ^= ch;
al1 ^= cl;
mp1 = ((uint8_t*) l1) + ((al1) & MASK);
ah1 ^= ch;
idx1 = al1;
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
int64_t n = ((int64_t*)mp1)[0];
int32_t d = ((int32_t*)mp1)[2];
int64_t n = ((int64_t*)&l1[idx1 & MASK])[0];
int32_t d = ((int32_t*)&l1[idx1 & MASK])[2];
int64_t q = n / (d | 0x5);
((int64_t*)mp1)[0] = n ^ q;
((int64_t*)&l1[idx1 & MASK])[0] = n ^ q;
idx1 = d ^ q;
}
}
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) l0, (__m128i*) h0);
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) l1, (__m128i*) h1);
keccakf(h0, 24);
keccakf(h1, 24);
xmrig::keccakf(h0, 24);
xmrig::keccakf(h1, 24);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
extra_hashes[ctx[1]->state[0] & 3](ctx[1]->state, 200, output + 32);
@ -622,7 +657,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
b = _mm_xor_si128(b, c); \
\
if (VARIANT > 0) { \
cryptonight_monero_tweak(reinterpret_cast<uint64_t*>(ptr), b); \
cryptonight_monero_tweak<VARIANT == xmrig::VARIANT_XTL ? 4 : 3>(reinterpret_cast<uint64_t*>(ptr), b); \
} else { \
_mm_store_si128(ptr, b); \
}
@ -640,6 +675,10 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
\
if (VARIANT > 0) { \
_mm_store_si128(ptr, _mm_xor_si128(a, mc)); \
\
if (VARIANT == xmrig::VARIANT_IPBC) { \
((uint64_t*)ptr)[1] ^= ((uint64_t*)ptr)[0]; \
} \
} else { \
_mm_store_si128(ptr, a); \
} \
@ -677,7 +716,7 @@ inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t si
}
for (size_t i = 0; i < 3; i++) {
keccak(input + size * i, static_cast<int>(size), ctx[i]->state, 200);
xmrig::keccak(input + size * i, size, ctx[i]->state);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory));
}
@ -748,7 +787,7 @@ inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t si
for (size_t i = 0; i < 3; i++) {
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state));
keccakf(reinterpret_cast<uint64_t*>(ctx[i]->state), 24);
xmrig::keccakf(reinterpret_cast<uint64_t*>(ctx[i]->state), 24);
extra_hashes[ctx[i]->state[0] & 3](ctx[i]->state, 200, output + 32 * i);
}
}
@ -767,7 +806,7 @@ inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size
}
for (size_t i = 0; i < 4; i++) {
keccak(input + size * i, static_cast<int>(size), ctx[i]->state, 200);
xmrig::keccak(input + size * i, size, ctx[i]->state);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory));
}
@ -854,7 +893,7 @@ inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size
for (size_t i = 0; i < 4; i++) {
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state));
keccakf(reinterpret_cast<uint64_t*>(ctx[i]->state), 24);
xmrig::keccakf(reinterpret_cast<uint64_t*>(ctx[i]->state), 24);
extra_hashes[ctx[i]->state[0] & 3](ctx[i]->state, 200, output + 32 * i);
}
}
@ -873,7 +912,7 @@ inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t siz
}
for (size_t i = 0; i < 5; i++) {
keccak(input + size * i, static_cast<int>(size), ctx[i]->state, 200);
xmrig::keccak(input + size * i, size, ctx[i]->state);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory));
}
@ -975,7 +1014,7 @@ inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t siz
for (size_t i = 0; i < 5; i++) {
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state));
keccakf(reinterpret_cast<uint64_t*>(ctx[i]->state), 24);
xmrig::keccakf(reinterpret_cast<uint64_t*>(ctx[i]->state), 24);
extra_hashes[ctx[i]->state[0] & 3](ctx[i]->state, 200, output + 32 * i);
}
}

View file

@ -1,176 +0,0 @@
// keccak.c
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
// A baseline Keccak (3rd round) implementation.
#include <stdint.h>
#include <memory.h>
#define HASH_DATA_AREA 136
#define KECCAK_ROUNDS 24
#ifndef ROTL64
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
#endif
const uint64_t keccakf_rndc[24] =
{
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
};
// update the state with given number of rounds
void keccakf(uint64_t st[25], int rounds)
{
int i, j, round;
uint64_t t, bc[5];
for (round = 0; round < rounds; ++round) {
// Theta
bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
bc[1] = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21];
bc[2] = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22];
bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
for (i = 0; i < 5; ++i) {
t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
st[i ] ^= t;
st[i + 5] ^= t;
st[i + 10] ^= t;
st[i + 15] ^= t;
st[i + 20] ^= t;
}
// Rho Pi
t = st[1];
st[ 1] = ROTL64(st[ 6], 44);
st[ 6] = ROTL64(st[ 9], 20);
st[ 9] = ROTL64(st[22], 61);
st[22] = ROTL64(st[14], 39);
st[14] = ROTL64(st[20], 18);
st[20] = ROTL64(st[ 2], 62);
st[ 2] = ROTL64(st[12], 43);
st[12] = ROTL64(st[13], 25);
st[13] = ROTL64(st[19], 8);
st[19] = ROTL64(st[23], 56);
st[23] = ROTL64(st[15], 41);
st[15] = ROTL64(st[ 4], 27);
st[ 4] = ROTL64(st[24], 14);
st[24] = ROTL64(st[21], 2);
st[21] = ROTL64(st[ 8], 55);
st[ 8] = ROTL64(st[16], 45);
st[16] = ROTL64(st[ 5], 36);
st[ 5] = ROTL64(st[ 3], 28);
st[ 3] = ROTL64(st[18], 21);
st[18] = ROTL64(st[17], 15);
st[17] = ROTL64(st[11], 10);
st[11] = ROTL64(st[ 7], 6);
st[ 7] = ROTL64(st[10], 3);
st[10] = ROTL64(t, 1);
// Chi
// unrolled loop, where only last iteration is different
j = 0;
bc[0] = st[j ];
bc[1] = st[j + 1];
st[j ] ^= (~st[j + 1]) & st[j + 2];
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
st[j + 3] ^= (~st[j + 4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
j = 5;
bc[0] = st[j ];
bc[1] = st[j + 1];
st[j ] ^= (~st[j + 1]) & st[j + 2];
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
st[j + 3] ^= (~st[j + 4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
j = 10;
bc[0] = st[j ];
bc[1] = st[j + 1];
st[j ] ^= (~st[j + 1]) & st[j + 2];
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
st[j + 3] ^= (~st[j + 4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
j = 15;
bc[0] = st[j ];
bc[1] = st[j + 1];
st[j ] ^= (~st[j + 1]) & st[j + 2];
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
st[j + 3] ^= (~st[j + 4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
j = 20;
bc[0] = st[j ];
bc[1] = st[j + 1];
bc[2] = st[j + 2];
bc[3] = st[j + 3];
bc[4] = st[j + 4];
st[j ] ^= (~bc[1]) & bc[2];
st[j + 1] ^= (~bc[2]) & bc[3];
st[j + 2] ^= (~bc[3]) & bc[4];
st[j + 3] ^= (~bc[4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
// Iota
st[0] ^= keccakf_rndc[round];
}
}
// compute a keccak hash (md) of given byte length from "in"
typedef uint64_t state_t[25];
void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen)
{
state_t st;
uint8_t temp[144];
int i, rsiz, rsizw;
rsiz = sizeof(state_t) == mdlen ? HASH_DATA_AREA : 200 - 2 * mdlen;
rsizw = rsiz / 8;
memset(st, 0, sizeof(st));
for ( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) {
for (i = 0; i < rsizw; i++)
st[i] ^= ((uint64_t *) in)[i];
keccakf(st, KECCAK_ROUNDS);
}
// last block and padding
memcpy(temp, in, inlen);
temp[inlen++] = 1;
memset(temp + inlen, 0, rsiz - inlen);
temp[rsiz - 1] |= 0x80;
for (i = 0; i < rsizw; i++)
st[i] ^= ((uint64_t *) temp)[i];
keccakf(st, KECCAK_ROUNDS);
memcpy(md, st, mdlen);
}
void keccak1600(const uint8_t *in, int inlen, uint8_t *md)
{
keccak(in, inlen, md, sizeof(state_t));
}

View file

@ -1,26 +0,0 @@
// keccak.h
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
#ifndef KECCAK_H
#define KECCAK_H
#include <stdint.h>
#include <string.h>
#ifndef KECCAK_ROUNDS
#define KECCAK_ROUNDS 24
#endif
#ifndef ROTL64
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
#endif
// compute a keccak hash (md) of given byte length from "in"
int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen);
// update the state
void keccakf(uint64_t st[25], int norounds);
void keccak1600(const uint8_t *in, int inlen, uint8_t *md);
#endif