|
|
@ -12,20 +12,6 @@ extern "C" { |
|
|
|
#include "cpu/c_keccak.h" |
|
|
|
#include "cpu/c_keccak.h" |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void cryptonight_store_variant(void* state, int variant) { |
|
|
|
|
|
|
|
if (variant == 1 || cryptonight_fork == 8) { |
|
|
|
|
|
|
|
// monero, and graft ?
|
|
|
|
|
|
|
|
const uint8_t tmp = ((const uint8_t*)(state))[11]; |
|
|
|
|
|
|
|
const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; |
|
|
|
|
|
|
|
((uint8_t*)(state))[11] = tmp ^ ((0x75310 >> index) & 0x30); |
|
|
|
|
|
|
|
} else if (variant == 2 && cryptonight_fork == 3) { |
|
|
|
|
|
|
|
// stellite
|
|
|
|
|
|
|
|
const uint8_t tmp = ((const uint8_t*)(state))[11]; |
|
|
|
|
|
|
|
const uint8_t index = (((tmp >> 4) & 6) | (tmp & 1)) << 1; |
|
|
|
|
|
|
|
((uint8_t*)(state))[11] = tmp ^ ((0x75312 >> index) & 0x30); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct cryptonight_ctx { |
|
|
|
struct cryptonight_ctx { |
|
|
|
uint8_t long_state[MEMORY]; |
|
|
|
uint8_t long_state[MEMORY]; |
|
|
|
union cn_slow_hash_state state; |
|
|
|
union cn_slow_hash_state state; |
|
|
@ -144,14 +130,14 @@ static void mul_sum_dst(const uint8_t* a, const uint8_t* b, const uint8_t* c, ui |
|
|
|
((uint64_t*) dst)[0] += ((uint64_t*) c)[0]; |
|
|
|
((uint64_t*) dst)[0] += ((uint64_t*) c)[0]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void mul_sum_xor_dst(const uint8_t* a, uint8_t* c, uint8_t* dst, const int variant, const uint64_t tweak1_2) { |
|
|
|
static void mul_sum_xor_dst(const uint8_t* a, uint8_t* c, uint8_t* dst, const int variant, const uint64_t tweak) { |
|
|
|
uint64_t hi, lo = mul128(((uint64_t*) a)[0], ((uint64_t*) dst)[0], &hi) + ((uint64_t*) c)[1]; |
|
|
|
uint64_t hi, lo = mul128(((uint64_t*) a)[0], ((uint64_t*) dst)[0], &hi) + ((uint64_t*) c)[1]; |
|
|
|
hi += ((uint64_t*) c)[0]; |
|
|
|
hi += ((uint64_t*) c)[0]; |
|
|
|
|
|
|
|
|
|
|
|
((uint64_t*) c)[0] = ((uint64_t*) dst)[0] ^ hi; |
|
|
|
((uint64_t*) c)[0] = ((uint64_t*) dst)[0] ^ hi; |
|
|
|
((uint64_t*) c)[1] = ((uint64_t*) dst)[1] ^ lo; |
|
|
|
((uint64_t*) c)[1] = ((uint64_t*) dst)[1] ^ lo; |
|
|
|
((uint64_t*) dst)[0] = hi; |
|
|
|
((uint64_t*) dst)[0] = hi; |
|
|
|
((uint64_t*) dst)[1] = variant ? lo ^ tweak1_2 : lo; |
|
|
|
((uint64_t*) dst)[1] = variant ? lo ^ tweak : lo; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void copy_block(uint8_t* dst, const uint8_t* src) { |
|
|
|
static void copy_block(uint8_t* dst, const uint8_t* src) { |
|
|
@ -169,22 +155,34 @@ static void xor_blocks_dst(const uint8_t* a, const uint8_t* b, uint8_t* dst) { |
|
|
|
((uint64_t*) dst)[1] = ((uint64_t*) a)[1] ^ ((uint64_t*) b)[1]; |
|
|
|
((uint64_t*) dst)[1] = ((uint64_t*) a)[1] ^ ((uint64_t*) b)[1]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int cryptonight_hash_ctx(void* output, const void* input, const size_t len, struct cryptonight_ctx* ctx, const int variant) |
|
|
|
static void cryptonight_store_variant(void* state, int variant) { |
|
|
|
|
|
|
|
if (variant == 1 || cryptonight_fork == 8) { |
|
|
|
|
|
|
|
// monero and graft
|
|
|
|
|
|
|
|
const uint8_t tmp = ((const uint8_t*)(state))[11]; |
|
|
|
|
|
|
|
const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; |
|
|
|
|
|
|
|
((uint8_t*)(state))[11] = tmp ^ ((0x75310 >> index) & 0x30); |
|
|
|
|
|
|
|
} else if (variant == 2 && cryptonight_fork == 3) { |
|
|
|
|
|
|
|
// stellite
|
|
|
|
|
|
|
|
const uint8_t tmp = ((const uint8_t*)(state))[11]; |
|
|
|
|
|
|
|
const uint8_t index = (((tmp >> 4) & 6) | (tmp & 1)) << 1; |
|
|
|
|
|
|
|
((uint8_t*)(state))[11] = tmp ^ ((0x75312 >> index) & 0x30); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void cryptonight_hash_ctx(void* output, const void* input, const size_t len, struct cryptonight_ctx* ctx, const int variant) |
|
|
|
{ |
|
|
|
{ |
|
|
|
size_t i, j; |
|
|
|
size_t i, j; |
|
|
|
if (variant && len < 43) |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
keccak_hash_process(&ctx->state.hs, (const uint8_t*) input, len); |
|
|
|
keccak_hash_process(&ctx->state.hs, (const uint8_t*) input, len); |
|
|
|
ctx->aes_ctx = (oaes_ctx*) oaes_alloc(); |
|
|
|
ctx->aes_ctx = (oaes_ctx*) oaes_alloc(); |
|
|
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|
|
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|
|
|
|
|
|
|
|
|
|
|
const uint64_t tweak1_2 = variant ? *((uint64_t*) (((uint8_t*)input) + 35)) ^ ctx->state.hs.w[24] : 0; |
|
|
|
const uint64_t tweak = variant ? *((uint64_t*) (((uint8_t*)input) + 35)) ^ ctx->state.hs.w[24] : 0; |
|
|
|
|
|
|
|
|
|
|
|
oaes_key_import_data(ctx->aes_ctx, ctx->state.hs.b, AES_KEY_SIZE); |
|
|
|
oaes_key_import_data(ctx->aes_ctx, ctx->state.hs.b, AES_KEY_SIZE); |
|
|
|
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) { |
|
|
|
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) { |
|
|
|
#undef RND |
|
|
|
#undef RND |
|
|
|
#define RND(p) aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * p], ctx->aes_ctx->key->exp_data); |
|
|
|
#define RND(p) aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * p], ctx->aes_ctx->key->exp_data); |
|
|
|
RND(0); |
|
|
|
RND(0); |
|
|
|
RND(1); |
|
|
|
RND(1); |
|
|
|
RND(2); |
|
|
|
RND(2); |
|
|
@ -204,23 +202,21 @@ static int cryptonight_hash_ctx(void* output, const void* input, const size_t le |
|
|
|
aesb_single_round(&ctx->long_state[j], ctx->c, ctx->a); |
|
|
|
aesb_single_round(&ctx->long_state[j], ctx->c, ctx->a); |
|
|
|
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j]); |
|
|
|
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j]); |
|
|
|
cryptonight_store_variant(&ctx->long_state[j], variant); |
|
|
|
cryptonight_store_variant(&ctx->long_state[j], variant); |
|
|
|
|
|
|
|
mul_sum_xor_dst(ctx->c, ctx->a, &ctx->long_state[e2i(ctx->c) * AES_BLOCK_SIZE], variant, tweak); |
|
|
|
mul_sum_xor_dst(ctx->c, ctx->a, &ctx->long_state[e2i(ctx->c) * AES_BLOCK_SIZE], variant, tweak1_2); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
j = e2i(ctx->a) * AES_BLOCK_SIZE; |
|
|
|
j = e2i(ctx->a) * AES_BLOCK_SIZE; |
|
|
|
aesb_single_round(&ctx->long_state[j], ctx->b, ctx->a); |
|
|
|
aesb_single_round(&ctx->long_state[j], ctx->b, ctx->a); |
|
|
|
xor_blocks_dst(ctx->b, ctx->c, &ctx->long_state[j]); |
|
|
|
xor_blocks_dst(ctx->b, ctx->c, &ctx->long_state[j]); |
|
|
|
cryptonight_store_variant(&ctx->long_state[j], variant); |
|
|
|
cryptonight_store_variant(&ctx->long_state[j], variant); |
|
|
|
|
|
|
|
mul_sum_xor_dst(ctx->b, ctx->a, &ctx->long_state[e2i(ctx->b) * AES_BLOCK_SIZE], variant, tweak); |
|
|
|
mul_sum_xor_dst(ctx->b, ctx->a, &ctx->long_state[e2i(ctx->b) * AES_BLOCK_SIZE], variant, tweak1_2); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|
|
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|
|
|
oaes_key_import_data(ctx->aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE); |
|
|
|
oaes_key_import_data(ctx->aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE); |
|
|
|
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) { |
|
|
|
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) { |
|
|
|
#undef RND |
|
|
|
#undef RND |
|
|
|
#define RND(p) xor_blocks(&ctx->text[p * AES_BLOCK_SIZE], &ctx->long_state[i + p * AES_BLOCK_SIZE]); \ |
|
|
|
#define RND(p) xor_blocks(&ctx->text[p * AES_BLOCK_SIZE], &ctx->long_state[i + p * AES_BLOCK_SIZE]); \ |
|
|
|
aesb_pseudo_round_mut(&ctx->text[p * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data); |
|
|
|
aesb_pseudo_round_mut(&ctx->text[p * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data); |
|
|
|
RND(0); |
|
|
|
RND(0); |
|
|
|
RND(1); |
|
|
|
RND(1); |
|
|
|
RND(2); |
|
|
|
RND(2); |
|
|
@ -238,15 +234,13 @@ static int cryptonight_hash_ctx(void* output, const void* input, const size_t le |
|
|
|
if (opt_debug) applog(LOG_DEBUG, "extra algo=%d", extra_algo); |
|
|
|
if (opt_debug) applog(LOG_DEBUG, "extra algo=%d", extra_algo); |
|
|
|
|
|
|
|
|
|
|
|
oaes_free((OAES_CTX **) &ctx->aes_ctx); |
|
|
|
oaes_free((OAES_CTX **) &ctx->aes_ctx); |
|
|
|
return 1; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int cryptonight_hash_variant(void* output, const void* input, size_t len, int variant) |
|
|
|
void cryptonight_hash_variant(void* output, const void* input, size_t len, int variant) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); |
|
|
|
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); |
|
|
|
int rc = cryptonight_hash_ctx(output, input, len, ctx, variant); |
|
|
|
cryptonight_hash_ctx(output, input, len, ctx, variant); |
|
|
|
free(ctx); |
|
|
|
free(ctx); |
|
|
|
return rc; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void cryptonight_hash(void* output, const void* input) |
|
|
|
void cryptonight_hash(void* output, const void* input) |
|
|
|