Improved Flex algo speed

This commit is contained in:
MoneroOcean 2024-05-29 03:07:40 +03:00
parent 0ec9860f49
commit 35ede29509
31 changed files with 33 additions and 4787 deletions

View file

@ -132,16 +132,6 @@ set(SOURCES_CRYPTO
src/crypto/common/Nonce.cpp
src/crypto/common/VirtualMemory.cpp
src/crypto/flex/flex.cpp
src/crypto/flex/cryptonote/cryptonight_dark.c
src/crypto/flex/cryptonote/cryptonight_dark_lite.c
src/crypto/flex/cryptonote/cryptonight_fast.c
src/crypto/flex/cryptonote/cryptonight_lite.c
src/crypto/flex/cryptonote/cryptonight_turtle.c
src/crypto/flex/cryptonote/cryptonight_turtle_lite.c
src/crypto/flex/cryptonote/crypto/oaes_lib.c
src/crypto/flex/cryptonote/crypto/aesb.c
src/crypto/flex/cryptonote/crypto/hash.c
src/crypto/flex/cryptonote/crypto/c_keccak.c
)
if (WITH_MO_BENCHMARK)

View file

@ -76,8 +76,14 @@ static inline void do_skein_hash(const uint8_t *input, size_t len, uint8_t *outp
xmr_skein(input, output);
}
static inline void do_flex_skein_hash(const uint8_t* input, size_t len, uint8_t* output) {
int r = skein_hash(512, input, 8 * len, (uint8_t*)output);
assert(SKEIN_SUCCESS == r);
}
void (* const extra_hashes[4])(const uint8_t *, size_t, uint8_t *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
void (* const extra_hashes_flex[3])(const uint8_t *, size_t, uint8_t *) = {do_blake_hash, do_groestl_hash, do_flex_skein_hash};
#if (defined(__i386__) || defined(_M_IX86)) && !(defined(__clang__) && defined(__clang_major__) && (__clang_major__ >= 15))
@ -853,7 +859,10 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
cn_implode_scratchpad<ALGO, SOFT_AES, interleave>(ctx[0]);
keccakf(h0, 24);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
if (height == 101) // Flex algo ugly hack
extra_hashes_flex[ctx[0]->state[0] & 2](ctx[0]->state, 200, output);
else
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
}
@ -1125,7 +1134,10 @@ inline void cryptonight_single_hash_asm(const uint8_t *__restrict__ input, size_
cn_implode_scratchpad<ALGO, false, 0>(ctx[0]);
keccakf(reinterpret_cast<uint64_t*>(ctx[0]->state), 24);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
if (height == 101) // Flex algo ugly hack
extra_hashes_flex[ctx[0]->state[0] & 2](ctx[0]->state, 200, output);
else
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
}
@ -1253,7 +1265,10 @@ static NOINLINE void cryptonight_single_hash_gr_sse41(const uint8_t* __restrict_
cn_implode_scratchpad<ALGO, false, 0>(ctx[0]);
keccakf(reinterpret_cast<uint64_t*>(ctx[0]->state), 24);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
if (height == 101) // Flex algo ugly hack
extra_hashes_flex[ctx[0]->state[0] & 2](ctx[0]->state, 200, output);
else
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
}

View file

@ -1,177 +0,0 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation.
This software is provided 'as is' with no explicit or implied warranties
in respect of its operation, including, but not limited to, correctness
and fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
*/
#include <stdint.h>
#if defined(__cplusplus)
extern "C"
{
#endif
#define TABLE_ALIGN 32
#define WPOLY 0x011b
#define N_COLS 4
#define AES_BLOCK_SIZE 16
#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2))
#if defined(_MSC_VER)
#define ALIGN __declspec(align(TABLE_ALIGN))
#elif defined(__GNUC__)
#define ALIGN __attribute__ ((aligned(16)))
#else
#define ALIGN
#endif
#define rf1(r,c) (r)
#define word_in(x,c) (*((uint32_t*)(x)+(c)))
#define word_out(x,c,v) (*((uint32_t*)(x)+(c)) = (v))
#define s(x,c) x[c]
#define si(y,x,c) (s(y,c) = word_in(x, c))
#define so(y,x,c) word_out(y, c, s(x,c))
#define state_in(y,x) si(y,x,0); si(y,x,1); si(y,x,2); si(y,x,3)
#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
#define to_byte(x) ((x) & 0xff)
#define bval(x,n) to_byte((x) >> (8 * (n)))
#define fwd_var(x,r,c)\
( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
: r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\
: r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
: ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))
#define sb_data(w) {\
w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
#define rc_data(w) {\
w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\
w(0x1b), w(0x36) }
#define bytes2word(b0, b1, b2, b3) (((uint32_t)(b3) << 24) | \
((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0))
#define h0(x) (x)
#define w0(p) bytes2word(p, 0, 0, 0)
#define w1(p) bytes2word(0, p, 0, 0)
#define w2(p) bytes2word(0, 0, p, 0)
#define w3(p) bytes2word(0, 0, 0, p)
#define u0(p) bytes2word(f2(p), p, p, f3(p))
#define u1(p) bytes2word(f3(p), f2(p), p, p)
#define u2(p) bytes2word(p, f3(p), f2(p), p)
#define u3(p) bytes2word(p, p, f3(p), f2(p))
#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p))
#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p))
#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p))
#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p))
#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY))
#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY))
#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) ^ (((x>>5) & 4) * WPOLY))
#define f3(x) (f2(x) ^ x)
#define f9(x) (f8(x) ^ x)
#define fb(x) (f8(x) ^ f2(x) ^ x)
#define fd(x) (f8(x) ^ f4(x) ^ x)
#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
#define t_dec(m,n) t_##m##n
#define t_set(m,n) t_##m##n
#define t_use(m,n) t_##m##n
#define d_4(t,n,b,e,f,g,h) ALIGN const t n[4][256] = { b(e), b(f), b(g), b(h) }
#define four_tables(x,tab,vf,rf,c) \
(tab[0][bval(vf(x,0,c),rf(0,c))] \
^ tab[1][bval(vf(x,1,c),rf(1,c))] \
^ tab[2][bval(vf(x,2,c),rf(2,c))] \
^ tab[3][bval(vf(x,3,c),rf(3,c))])
d_4(uint32_t, t_dec(f,n), sb_data, u0, u1, u2, u3);
void aesb_single_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey)
{
uint32_t b0[4], b1[4];
const uint32_t *kp = (uint32_t *) expandedKey;
state_in(b0, in);
round(fwd_rnd, b1, b0, kp);
state_out(out, b1);
}
void aesb_pseudo_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey)
{
uint32_t b0[4], b1[4];
const uint32_t *kp = (uint32_t *) expandedKey;
state_in(b0, in);
round(fwd_rnd, b1, b0, kp);
round(fwd_rnd, b0, b1, kp + 1 * N_COLS);
round(fwd_rnd, b1, b0, kp + 2 * N_COLS);
round(fwd_rnd, b0, b1, kp + 3 * N_COLS);
round(fwd_rnd, b1, b0, kp + 4 * N_COLS);
round(fwd_rnd, b0, b1, kp + 5 * N_COLS);
round(fwd_rnd, b1, b0, kp + 6 * N_COLS);
round(fwd_rnd, b0, b1, kp + 7 * N_COLS);
round(fwd_rnd, b1, b0, kp + 8 * N_COLS);
round(fwd_rnd, b0, b1, kp + 9 * N_COLS);
state_out(out, b0);
}
#if defined(__cplusplus)
}
#endif

View file

@ -1,43 +0,0 @@
#ifndef _BLAKE256_H_
#define _BLAKE256_H_
#include <stdint.h>
typedef struct {
uint32_t h[8], s[4], t[2];
int buflen, nullt;
uint8_t buf[64];
} state;
typedef struct {
state inner;
state outer;
} hmac_state;
void blake256_init(state *);
void blake224_init(state *);
void blake256_update(state *, const uint8_t *, uint64_t);
void blake224_update(state *, const uint8_t *, uint64_t);
void blake256_final(state *, uint8_t *);
void blake224_final(state *, uint8_t *);
void blake256_hash(uint8_t *, const uint8_t *, uint64_t);
void blake224_hash(uint8_t *, const uint8_t *, uint64_t);
/* HMAC functions: */
void hmac_blake256_init(hmac_state *, const uint8_t *, uint64_t);
void hmac_blake224_init(hmac_state *, const uint8_t *, uint64_t);
void hmac_blake256_update(hmac_state *, const uint8_t *, uint64_t);
void hmac_blake224_update(hmac_state *, const uint8_t *, uint64_t);
void hmac_blake256_final(hmac_state *, uint8_t *);
void hmac_blake224_final(hmac_state *, uint8_t *);
void hmac_blake256_hash(uint8_t *, const uint8_t *, uint64_t, const uint8_t *, uint64_t);
void hmac_blake224_hash(uint8_t *, const uint8_t *, uint64_t, const uint8_t *, uint64_t);
#endif /* _BLAKE256_H_ */

View file

@ -1,56 +0,0 @@
#pragma once
/*
#include "crypto_uint8.h"
#include "crypto_uint32.h"
#include "crypto_uint64.h"
#include "crypto_hash.h"
typedef crypto_uint8 uint8_t;
typedef crypto_uint32 uint32_t;
typedef crypto_uint64 uint64_t;
*/
#include <stdint.h>
#include "hash.h"
/* some sizes (number of bytes) */
#define ROWS 8
#define LENGTHFIELDLEN ROWS
#define COLS512 8
#define SIZE512 (ROWS*COLS512)
#define ROUNDS512 10
#define HASH_BIT_LEN 256
#define ROTL32(v, n) ((((v)<<(n))|((v)>>(32-(n))))&li_32(ffffffff))
#define li_32(h) 0x##h##u
#define EXT_BYTE(var,n) ((uint8_t)((uint32_t)(var) >> (8*n)))
#define u32BIG(a) \
((ROTL32(a,8) & li_32(00FF00FF)) | \
(ROTL32(a,24) & li_32(FF00FF00)))
/* NIST API begin */
typedef struct {
uint32_t chaining[SIZE512/sizeof(uint32_t)]; /* actual state */
uint32_t block_counter1,
block_counter2; /* message block counter(s) */
BitSequence buffer[SIZE512]; /* data buffer */
int buf_ptr; /* data buffer pointer */
int bits_in_last_byte; /* no. of message bits in last byte of
data buffer */
} hashState;
/*void Init(hashState*);
void Update(hashState*, const BitSequence*, DataLength);
void Final(hashState*, BitSequence*); */
void groestl(const BitSequence*, DataLength, BitSequence*);
/* NIST API end */
/*
int crypto_hash(unsigned char *out,
const unsigned char *in,
unsigned long long len);
*/

View file

@ -1,20 +0,0 @@
/*This program gives the 64-bit optimized bitslice implementation of JH using ANSI C
--------------------------------
Performance
Microprocessor: Intel CORE 2 processor (Core 2 Duo Mobile T6600 2.2GHz)
Operating System: 64-bit Ubuntu 10.04 (Linux kernel 2.6.32-22-generic)
Speed for long message:
1) 45.8 cycles/byte compiler: Intel C++ Compiler 11.1 compilation option: icc -O2
2) 56.8 cycles/byte compiler: gcc 4.4.3 compilation option: gcc -O3
--------------------------------
Last Modified: January 16, 2011
*/
#pragma once
#include "hash.h"
typedef enum {SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2} HashReturn;
HashReturn jh_hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval);

View file

@ -1,112 +0,0 @@
// keccak.c
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
// A baseline Keccak (3rd round) implementation.
#include "hash-ops.h"
#include "c_keccak.h"
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
};
const int keccakf_rotc[24] =
{
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
};
const int keccakf_piln[24] =
{
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
};
// 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
for (i = 0; i < 5; i++)
bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20];
for (i = 0; i < 5; i++) {
t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
for (j = 0; j < 25; j += 5)
st[j + i] ^= t;
}
// Rho Pi
t = st[1];
for (i = 0; i < 24; i++) {
j = keccakf_piln[i];
bc[0] = st[j];
st[j] = ROTL64(t, keccakf_rotc[i]);
t = bc[0];
}
// Chi
for (j = 0; j < 25; j += 5) {
for (i = 0; i < 5; i++)
bc[i] = st[j + i];
for (i = 0; i < 5; i++)
st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
}
// Iota
st[0] ^= keccakf_rndc[round];
}
}
// compute a keccak hash (md) of given byte length from "in"
typedef uint64_t state_t[25];
int 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);
return 0;
}
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

View file

@ -1,186 +0,0 @@
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <cstddef>
#include <mutex>
#include <vector>
#include "common/pod-class.h"
#include "generic-ops.h"
#include "hash.h"
namespace crypto {
extern "C" {
#include "random.h"
}
extern std::mutex random_lock;
#pragma pack(push, 1)
POD_CLASS ec_point {
char data[32];
};
POD_CLASS ec_scalar {
char data[32];
};
POD_CLASS public_key: ec_point {
friend class crypto_ops;
};
POD_CLASS secret_key: ec_scalar {
friend class crypto_ops;
};
POD_CLASS key_derivation: ec_point {
friend class crypto_ops;
};
POD_CLASS key_image: ec_point {
friend class crypto_ops;
};
POD_CLASS signature {
ec_scalar c, r;
friend class crypto_ops;
};
#pragma pack(pop)
static_assert(sizeof(ec_point) == 32 && sizeof(ec_scalar) == 32 &&
sizeof(public_key) == 32 && sizeof(secret_key) == 32 &&
sizeof(key_derivation) == 32 && sizeof(key_image) == 32 &&
sizeof(signature) == 64, "Invalid structure size");
class crypto_ops {
crypto_ops();
crypto_ops(const crypto_ops &);
void operator=(const crypto_ops &);
~crypto_ops();
static void generate_keys(public_key &, secret_key &);
friend void generate_keys(public_key &, secret_key &);
static bool check_key(const public_key &);
friend bool check_key(const public_key &);
static bool secret_key_to_public_key(const secret_key &, public_key &);
friend bool secret_key_to_public_key(const secret_key &, public_key &);
static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
static void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
static bool check_signature(const hash &, const public_key &, const signature &);
friend bool check_signature(const hash &, const public_key &, const signature &);
static void generate_key_image(const public_key &, const secret_key &, key_image &);
friend void generate_key_image(const public_key &, const secret_key &, key_image &);
static void generate_ring_signature(const hash &, const key_image &,
const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *);
friend void generate_ring_signature(const hash &, const key_image &,
const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *);
static bool check_ring_signature(const hash &, const key_image &,
const public_key *const *, std::size_t, const signature *);
friend bool check_ring_signature(const hash &, const key_image &,
const public_key *const *, std::size_t, const signature *);
};
/* Generate a value filled with random bytes.
*/
template<typename T>
typename std::enable_if<std::is_pod<T>::value, T>::type rand() {
typename std::remove_cv<T>::type res;
std::lock_guard<std::mutex> lock(random_lock);
generate_random_bytes(sizeof(T), &res);
return res;
}
/* Generate a new key pair
*/
inline void generate_keys(public_key &pub, secret_key &sec) {
crypto_ops::generate_keys(pub, sec);
}
/* Check a public key. Returns true if it is valid, false otherwise.
*/
inline bool check_key(const public_key &key) {
return crypto_ops::check_key(key);
}
/* Checks a private key and computes the corresponding public key.
*/
inline bool secret_key_to_public_key(const secret_key &sec, public_key &pub) {
return crypto_ops::secret_key_to_public_key(sec, pub);
}
/* To generate an ephemeral key used to send money to:
* * The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in "extra" field.
* * Both the sender and the receiver generate key derivation from the transaction key, the receivers' "view" key and the output index.
* * The sender uses key derivation and the receivers' "spend" key to derive an ephemeral public key.
* * The receiver can either derive the public key (to check that the transaction is addressed to him) or the private key (to spend the money).
*/
inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) {
return crypto_ops::generate_key_derivation(key1, key2, derivation);
}
inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index,
const public_key &base, public_key &derived_key) {
return crypto_ops::derive_public_key(derivation, output_index, base, derived_key);
}
inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index,
const secret_key &base, secret_key &derived_key) {
crypto_ops::derive_secret_key(derivation, output_index, base, derived_key);
}
/* Generation and checking of a standard signature.
*/
inline void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
crypto_ops::generate_signature(prefix_hash, pub, sec, sig);
}
inline bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) {
return crypto_ops::check_signature(prefix_hash, pub, sig);
}
/* To send money to a key:
* * The sender generates an ephemeral key and includes it in transaction output.
* * To spend the money, the receiver generates a key image from it.
* * Then he selects a bunch of outputs, including the one he spends, and uses them to generate a ring signature.
* To check the signature, it is necessary to collect all the keys that were used to generate it. To detect double spends, it is necessary to check that each key image is used at most once.
*/
inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
crypto_ops::generate_key_image(pub, sec, image);
}
inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
const public_key *const *pubs, std::size_t pubs_count,
const secret_key &sec, std::size_t sec_index,
signature *sig) {
crypto_ops::generate_ring_signature(prefix_hash, image, pubs, pubs_count, sec, sec_index, sig);
}
inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
const public_key *const *pubs, std::size_t pubs_count,
const signature *sig) {
return crypto_ops::check_ring_signature(prefix_hash, image, pubs, pubs_count, sig);
}
/* Variants with vector<const public_key *> parameters.
*/
inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
const std::vector<const public_key *> &pubs,
const secret_key &sec, std::size_t sec_index,
signature *sig) {
generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig);
}
inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
const std::vector<const public_key *> &pubs,
const signature *sig) {
return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig);
}
}
CRYPTO_MAKE_COMPARABLE(public_key)
CRYPTO_MAKE_HASHABLE(key_image)
CRYPTO_MAKE_COMPARABLE(signature)

View file

@ -1,57 +0,0 @@
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#if !defined(__cplusplus)
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "int-util.h"
static inline void *padd(void *p, size_t i) {
return (char *) p + i;
}
static inline const void *cpadd(const void *p, size_t i) {
return (const char *) p + i;
}
static inline void place_length(uint8_t *buffer, size_t bufsize, size_t length) {
if (sizeof(size_t) == 4) {
*(uint32_t *) padd(buffer, bufsize - 4) = swap32be(length);
} else {
*(uint64_t *) padd(buffer, bufsize - 8) = swap64be(length);
}
}
#pragma pack(push, 1)
union hash_state {
uint8_t b[200];
uint64_t w[25];
};
#pragma pack(pop)
void hash_permutation(union hash_state *state);
void hash_process(union hash_state *state, const uint8_t *buf, size_t count);
#endif
enum {
HASH_SIZE = 64,
HASH_DATA_AREA = 136
};
void cn_fast_hash(const void *data, size_t length, char *hash);
void cn_slow_hash(const void *data, size_t length, char *hash);
void hash_extra_blake(const void *data, size_t length, char *hash);
void hash_extra_groestl(const void *data, size_t length, char *hash);
void hash_extra_jh(const void *data, size_t length, char *hash);
void hash_extra_skein(const void *data, size_t length, char *hash);
void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash);

View file

@ -1,24 +0,0 @@
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "hash-ops.h"
#include "c_keccak.h"
void hash_permutation(union hash_state *state) {
keccakf((uint64_t*)state, 24);
}
void hash_process(union hash_state *state, const uint8_t *buf, size_t count) {
keccak1600(buf, count, (uint8_t*)state);
}
void cn_fast_hash(const void *data, size_t length, char *hash) {
union hash_state state;
hash_process(&state, data, length);
memcpy(hash, &state, HASH_SIZE);
}

View file

@ -1,22 +0,0 @@
#pragma once
#include "hash-ops.h"
typedef unsigned char BitSequence;
typedef unsigned long long DataLength;
#ifdef __cplusplus
#include <string>
typedef std::string blobdata;
namespace crypto {
#pragma pack(push, 1)
class hash {
char data[HASH_SIZE];
};
#pragma pack(pop)
}
#endif

View file

@ -1,230 +0,0 @@
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
/*
* Create GNU compatible endian macros. We use the values for __LITTLE_ENDIAN
* and __BIG_ENDIAN based on endian.h.
*/
#ifdef __sun
#include <sys/byteorder.h>
#define LITTLE_ENDIAN 1234
#define BIG_ENDIAN 4321
#ifdef _LITTLE_ENDIAN
#define BYTE_ORDER LITTLE_ENDIAN
#else
#define BYTE_ORDER BIG_ENDIAN
#endif /* _LITTLE_ENDIAN */
#endif /* __sun */
#if defined(_MSC_VER)
#include <stdlib.h>
//instead of #include <sys/param.h>
// assume little-endian on Windows
#define LITTLE_ENDIAN 1234
#define BIG_ENDIAN 4321
#define BYTE_ORDER LITTLE_ENDIAN
static inline uint32_t rol32(uint32_t x, int r) {
static_assert(sizeof(uint32_t) == sizeof(unsigned int), "this code assumes 32-bit integers");
return _rotl(x, r);
}
static inline uint64_t rol64(uint64_t x, int r) {
return _rotl64(x, r);
}
#else
#include <sys/param.h>
static inline uint32_t rol32(uint32_t x, int r) {
return (x << (r & 31)) | (x >> (-r & 31));
}
static inline uint64_t rol64(uint64_t x, int r) {
return (x << (r & 63)) | (x >> (-r & 63));
}
#endif
static inline uint64_t hi_dword(uint64_t val) {
return val >> 32;
}
static inline uint64_t lo_dword(uint64_t val) {
return val & 0xFFFFFFFF;
}
static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi) {
// multiplier = ab = a * 2^32 + b
// multiplicand = cd = c * 2^32 + d
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
uint64_t a = hi_dword(multiplier);
uint64_t b = lo_dword(multiplier);
uint64_t c = hi_dword(multiplicand);
uint64_t d = lo_dword(multiplicand);
uint64_t ac = a * c;
uint64_t ad = a * d;
uint64_t bc = b * c;
uint64_t bd = b * d;
uint64_t adbc = ad + bc;
uint64_t adbc_carry = adbc < ad ? 1 : 0;
// multiplier * multiplicand = product_hi * 2^64 + product_lo
uint64_t product_lo = bd + (adbc << 32);
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
*product_hi = ac + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
assert(ac <= *product_hi);
return product_lo;
}
static inline uint64_t div_with_reminder(uint64_t dividend, uint32_t divisor, uint32_t* remainder) {
dividend |= ((uint64_t)*remainder) << 32;
*remainder = dividend % divisor;
return dividend / divisor;
}
// Long division with 2^32 base
static inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t* quotient_hi, uint64_t* quotient_lo) {
uint64_t dividend_dwords[4];
uint32_t remainder = 0;
dividend_dwords[3] = hi_dword(dividend_hi);
dividend_dwords[2] = lo_dword(dividend_hi);
dividend_dwords[1] = hi_dword(dividend_lo);
dividend_dwords[0] = lo_dword(dividend_lo);
*quotient_hi = div_with_reminder(dividend_dwords[3], divisor, &remainder) << 32;
*quotient_hi |= div_with_reminder(dividend_dwords[2], divisor, &remainder);
*quotient_lo = div_with_reminder(dividend_dwords[1], divisor, &remainder) << 32;
*quotient_lo |= div_with_reminder(dividend_dwords[0], divisor, &remainder);
return remainder;
}
#define IDENT32(x) ((uint32_t) (x))
#define IDENT64(x) ((uint64_t) (x))
#define SWAP32(x) ((((uint32_t) (x) & 0x000000ff) << 24) | \
(((uint32_t) (x) & 0x0000ff00) << 8) | \
(((uint32_t) (x) & 0x00ff0000) >> 8) | \
(((uint32_t) (x) & 0xff000000) >> 24))
#define SWAP64(x) ((((uint64_t) (x) & 0x00000000000000ff) << 56) | \
(((uint64_t) (x) & 0x000000000000ff00) << 40) | \
(((uint64_t) (x) & 0x0000000000ff0000) << 24) | \
(((uint64_t) (x) & 0x00000000ff000000) << 8) | \
(((uint64_t) (x) & 0x000000ff00000000) >> 8) | \
(((uint64_t) (x) & 0x0000ff0000000000) >> 24) | \
(((uint64_t) (x) & 0x00ff000000000000) >> 40) | \
(((uint64_t) (x) & 0xff00000000000000) >> 56))
static inline uint32_t ident32(uint32_t x) { return x; }
static inline uint64_t ident64(uint64_t x) { return x; }
static inline uint32_t swap32(uint32_t x) {
x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8);
return (x << 16) | (x >> 16);
}
static inline uint64_t swap64(uint64_t x) {
x = ((x & 0x00ff00ff00ff00ff) << 8) | ((x & 0xff00ff00ff00ff00) >> 8);
x = ((x & 0x0000ffff0000ffff) << 16) | ((x & 0xffff0000ffff0000) >> 16);
return (x << 32) | (x >> 32);
}
#if defined(__GNUC__)
#define UNUSED __attribute__((unused))
#else
#define UNUSED
#endif
static inline void mem_inplace_ident(void *mem UNUSED, size_t n UNUSED) { }
#undef UNUSED
static inline void mem_inplace_swap32(void *mem, size_t n) {
size_t i;
for (i = 0; i < n; i++) {
((uint32_t *) mem)[i] = swap32(((const uint32_t *) mem)[i]);
}
}
static inline void mem_inplace_swap64(void *mem, size_t n) {
size_t i;
for (i = 0; i < n; i++) {
((uint64_t *) mem)[i] = swap64(((const uint64_t *) mem)[i]);
}
}
static inline void memcpy_ident32(void *dst, const void *src, size_t n) {
memcpy(dst, src, 4 * n);
}
static inline void memcpy_ident64(void *dst, const void *src, size_t n) {
memcpy(dst, src, 8 * n);
}
static inline void memcpy_swap32(void *dst, const void *src, size_t n) {
size_t i;
for (i = 0; i < n; i++) {
((uint32_t *) dst)[i] = swap32(((const uint32_t *) src)[i]);
}
}
static inline void memcpy_swap64(void *dst, const void *src, size_t n) {
size_t i;
for (i = 0; i < n; i++) {
((uint64_t *) dst)[i] = swap64(((const uint64_t *) src)[i]);
}
}
#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN)
#if __STDC_VERSION__ - 0 >= 201112L
static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled");
#else
#error "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled"
#endif
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
#define SWAP32LE IDENT32
#define SWAP32BE SWAP32
#define swap32le ident32
#define swap32be swap32
#define mem_inplace_swap32le mem_inplace_ident
#define mem_inplace_swap32be mem_inplace_swap32
#define memcpy_swap32le memcpy_ident32
#define memcpy_swap32be memcpy_swap32
#define SWAP64LE IDENT64
#define SWAP64BE SWAP64
#define swap64le ident64
#define swap64be swap64
#define mem_inplace_swap64le mem_inplace_ident
#define mem_inplace_swap64be mem_inplace_swap64
#define memcpy_swap64le memcpy_ident64
#define memcpy_swap64be memcpy_swap64
#endif
#if BYTE_ORDER == BIG_ENDIAN
#define SWAP32BE IDENT32
#define SWAP32LE SWAP32
#define swap32be ident32
#define swap32le swap32
#define mem_inplace_swap32be mem_inplace_ident
#define mem_inplace_swap32le mem_inplace_swap32
#define memcpy_swap32be memcpy_ident32
#define memcpy_swap32le memcpy_swap32
#define SWAP64BE IDENT64
#define SWAP64LE SWAP64
#define swap64be ident64
#define swap64le swap64
#define mem_inplace_swap64be mem_inplace_ident
#define mem_inplace_swap64le mem_inplace_swap64
#define memcpy_swap64be memcpy_ident64
#define memcpy_swap64le memcpy_swap64
#endif

View file

@ -1,50 +0,0 @@
/*
* ---------------------------------------------------------------------------
* OpenAES License
* ---------------------------------------------------------------------------
* Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------
*/
#ifndef _OAES_CONFIG_H
#define _OAES_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
//#ifndef OAES_HAVE_ISAAC
//#define OAES_HAVE_ISAAC 1
//#endif // OAES_HAVE_ISAAC
//#ifndef OAES_DEBUG
//#define OAES_DEBUG 0
//#endif // OAES_DEBUG
#ifdef __cplusplus
}
#endif
#endif // _OAES_CONFIG_H

File diff suppressed because it is too large Load diff

View file

@ -1,215 +0,0 @@
/*
* ---------------------------------------------------------------------------
* OpenAES License
* ---------------------------------------------------------------------------
* Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------
*/
#ifndef _OAES_LIB_H
#define _OAES_LIB_H
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
# ifdef OAES_SHARED
# ifdef oaes_lib_EXPORTS
# define OAES_API __declspec(dllexport)
# else
# define OAES_API __declspec(dllimport)
# endif
# else
# define OAES_API
# endif
#else
# define OAES_API
#endif // WIN32
#define OAES_VERSION "0.8.1"
#define OAES_BLOCK_SIZE 16
typedef void OAES_CTX;
typedef enum
{
OAES_RET_FIRST = 0,
OAES_RET_SUCCESS = 0,
OAES_RET_UNKNOWN,
OAES_RET_ARG1,
OAES_RET_ARG2,
OAES_RET_ARG3,
OAES_RET_ARG4,
OAES_RET_ARG5,
OAES_RET_NOKEY,
OAES_RET_MEM,
OAES_RET_BUF,
OAES_RET_HEADER,
OAES_RET_COUNT
} OAES_RET;
/*
* oaes_set_option() takes one of these values for its [option] parameter
* some options accept either an optional or a required [value] parameter
*/
// no option
#define OAES_OPTION_NONE 0
// enable ECB mode, disable CBC mode
#define OAES_OPTION_ECB 1
// enable CBC mode, disable ECB mode
// value is optional, may pass uint8_t iv[OAES_BLOCK_SIZE] to specify
// the value of the initialization vector, iv
#define OAES_OPTION_CBC 2
#ifdef OAES_DEBUG
typedef int ( * oaes_step_cb ) (
const uint8_t state[OAES_BLOCK_SIZE],
const char * step_name,
int step_count,
void * user_data );
// enable state stepping mode
// value is required, must pass oaes_step_cb to receive the state at each step
#define OAES_OPTION_STEP_ON 4
// disable state stepping mode
#define OAES_OPTION_STEP_OFF 8
#endif // OAES_DEBUG
typedef uint16_t OAES_OPTION;
typedef struct _oaes_key
{
size_t data_len;
uint8_t *data;
size_t exp_data_len;
uint8_t *exp_data;
size_t num_keys;
size_t key_base;
} oaes_key;
typedef struct _oaes_ctx
{
#ifdef OAES_HAVE_ISAAC
randctx * rctx;
#endif // OAES_HAVE_ISAAC
#ifdef OAES_DEBUG
oaes_step_cb step_cb;
#endif // OAES_DEBUG
oaes_key * key;
OAES_OPTION options;
uint8_t iv[OAES_BLOCK_SIZE];
} oaes_ctx;
/*
* // usage:
*
* OAES_CTX * ctx = oaes_alloc();
* .
* .
* .
* {
* oaes_gen_key_xxx( ctx );
* {
* oaes_key_export( ctx, _buf, &_buf_len );
* // or
* oaes_key_export_data( ctx, _buf, &_buf_len );\
* }
* }
* // or
* {
* oaes_key_import( ctx, _buf, _buf_len );
* // or
* oaes_key_import_data( ctx, _buf, _buf_len );
* }
* .
* .
* .
* oaes_encrypt( ctx, m, m_len, c, &c_len );
* .
* .
* .
* oaes_decrypt( ctx, c, c_len, m, &m_len );
* .
* .
* .
* oaes_free( &ctx );
*/
OAES_API OAES_CTX * oaes_alloc(void);
OAES_API OAES_RET oaes_free( OAES_CTX ** ctx );
OAES_API OAES_RET oaes_set_option( OAES_CTX * ctx,
OAES_OPTION option, const void * value );
OAES_API OAES_RET oaes_key_gen_128( OAES_CTX * ctx );
OAES_API OAES_RET oaes_key_gen_192( OAES_CTX * ctx );
OAES_API OAES_RET oaes_key_gen_256( OAES_CTX * ctx );
// export key with header information
// set data == NULL to get the required data_len
OAES_API OAES_RET oaes_key_export( OAES_CTX * ctx,
uint8_t * data, size_t * data_len );
// directly export the data from key
// set data == NULL to get the required data_len
OAES_API OAES_RET oaes_key_export_data( OAES_CTX * ctx,
uint8_t * data, size_t * data_len );
// import key with header information
OAES_API OAES_RET oaes_key_import( OAES_CTX * ctx,
const uint8_t * data, size_t data_len );
// directly import data into key
OAES_API OAES_RET oaes_key_import_data( OAES_CTX * ctx,
const uint8_t * data, size_t data_len );
// set c == NULL to get the required c_len
OAES_API OAES_RET oaes_encrypt( OAES_CTX * ctx,
const uint8_t * m, size_t m_len, uint8_t * c, size_t * c_len );
// set m == NULL to get the required m_len
OAES_API OAES_RET oaes_decrypt( OAES_CTX * ctx,
const uint8_t * c, size_t c_len, uint8_t * m, size_t * m_len );
// set buf == NULL to get the required buf_len
OAES_API OAES_RET oaes_sprintf(
char * buf, size_t * buf_len, const uint8_t * data, size_t data_len );
OAES_API OAES_RET oaes_encryption_round( const uint8_t * key, uint8_t * c );
OAES_API OAES_RET oaes_pseudo_encrypt_ecb( OAES_CTX * ctx, uint8_t * c );
#ifdef __cplusplus
}
#endif
#endif // _OAES_LIB_H

View file

@ -1,168 +0,0 @@
#ifndef VARIANT2_INT_SQRT_H
#define VARIANT2_INT_SQRT_H
#include <math.h>
#include <float.h>
#define VARIANT2_INTEGER_MATH_SQRT_STEP_SSE2() \
do { \
const __m128i exp_double_bias = _mm_set_epi64x(0, 1023ULL << 52); \
__m128d x = _mm_castsi128_pd(_mm_add_epi64(_mm_cvtsi64_si128(sqrt_input >> 12), exp_double_bias)); \
x = _mm_sqrt_sd(_mm_setzero_pd(), x); \
sqrt_result = (uint64_t)(_mm_cvtsi128_si64(_mm_sub_epi64(_mm_castpd_si128(x), exp_double_bias))) >> 19; \
} while(0)
#define VARIANT2_INTEGER_MATH_SQRT_STEP_FP64() \
do { \
sqrt_result = sqrt(sqrt_input + 18446744073709551616.0) * 2.0 - 8589934592.0; \
} while(0)
//#define VARIANT2_INTEGER_MATH_SQRT_STEP_REF() \
// sqrt_result = integer_square_root_v2(sqrt_input)
// Reference implementation of the integer square root for Cryptonight variant 2
// Computes integer part of "sqrt(2^64 + n) * 2 - 2^33"
//
// In other words, given 64-bit unsigned integer n:
// 1) Write it as x = 1.NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN000... in binary (1 <= x < 2, all 64 bits of n are used)
// 2) Calculate sqrt(x) = 1.0RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR... (1 <= sqrt(x) < sqrt(2), so it will always start with "1.0" in binary)
// 3) Take 32 bits that come after "1.0" and return them as a 32-bit unsigned integer, discard all remaining bits
//
// Some sample inputs and outputs:
//
// Input | Output | Exact value of "sqrt(2^64 + n) * 2 - 2^33"
// -----------------|------------|-------------------------------------------
// 0 | 0 | 0
// 2^32 | 0 | 0.99999999994179233909330885695244...
// 2^32 + 1 | 1 | 1.0000000001746229827200734316305...
// 2^50 | 262140 | 262140.00012206565608606978175873...
// 2^55 + 20963331 | 8384515 | 8384515.9999999997673963974959744...
// 2^55 + 20963332 | 8384516 | 8384516
// 2^62 + 26599786 | 1013904242 | 1013904242.9999999999479374853545...
// 2^62 + 26599787 | 1013904243 | 1013904243.0000000001561875439364...
// 2^64 - 1 | 3558067407 | 3558067407.9041987696409179931096...
// The reference implementation as it is now uses only unsigned int64 arithmetic, so it can't have undefined behavior
// It was tested once for all edge cases and confirmed correct
//
// !!! Note: if you're modifying this code, uncomment the test in monero/tests/hash/main.cpp !!!
//
/*
static inline uint64_t integer_square_root_v2(uint64_t n)
{
uint64_t r = 1ULL << 63;
for (uint64_t bit = 1ULL << 60; bit; bit >>= 2)
{
const bool b = (n < r + bit);
const uint64_t n_next = n - (r + bit);
const uint64_t r_next = r + bit * 2;
n = b ? n : n_next;
r = b ? r : r_next;
r >>= 1;
}
return r * 2 + ((n > r) ? 1 : 0);
}
*/
/*
VARIANT2_INTEGER_MATH_SQRT_FIXUP checks that "r" is an integer part of "sqrt(2^64 + sqrt_input) * 2 - 2^33" and adds or subtracts 1 if needed
It's hard to understand how it works, so here is a full calculation of formulas used in VARIANT2_INTEGER_MATH_SQRT_FIXUP
The following inequalities must hold for r if it's an integer part of "sqrt(2^64 + sqrt_input) * 2 - 2^33":
1) r <= sqrt(2^64 + sqrt_input) * 2 - 2^33
2) r + 1 > sqrt(2^64 + sqrt_input) * 2 - 2^33
We need to check them using only unsigned integer arithmetic to avoid rounding errors and undefined behavior
First inequality: r <= sqrt(2^64 + sqrt_input) * 2 - 2^33
-----------------------------------------------------------------------------------
r <= sqrt(2^64 + sqrt_input) * 2 - 2^33
r + 2^33 <= sqrt(2^64 + sqrt_input) * 2
r/2 + 2^32 <= sqrt(2^64 + sqrt_input)
(r/2 + 2^32)^2 <= 2^64 + sqrt_input
Rewrite r as r = s * 2 + b (s = trunc(r/2), b is 0 or 1)
((s*2+b)/2 + 2^32)^2 <= 2^64 + sqrt_input
(s*2+b)^2/4 + 2*2^32*(s*2+b)/2 + 2^64 <= 2^64 + sqrt_input
(s*2+b)^2/4 + 2*2^32*(s*2+b)/2 <= sqrt_input
(s*2+b)^2/4 + 2^32*r <= sqrt_input
(s^2*4+2*s*2*b+b^2)/4 + 2^32*r <= sqrt_input
s^2+s*b+b^2/4 + 2^32*r <= sqrt_input
s*(s+b) + b^2/4 + 2^32*r <= sqrt_input
Let r2 = s*(s+b) + r*2^32
r2 + b^2/4 <= sqrt_input
If this inequality doesn't hold, then we must decrement r: IF "r2 + b^2/4 > sqrt_input" THEN r = r - 1
b can be 0 or 1
If b is 0 then we need to compare "r2 > sqrt_input"
If b is 1 then b^2/4 = 0.25, so we need to compare "r2 + 0.25 > sqrt_input"
Since both r2 and sqrt_input are integers, we can safely replace it with "r2 + 1 > sqrt_input"
-----------------------------------------------------------------------------------
Both cases can be merged to a single expression "r2 + b > sqrt_input"
-----------------------------------------------------------------------------------
There will be no overflow when calculating "r2 + b", so it's safe to compare with sqrt_input:
r2 + b = s*(s+b) + r*2^32 + b
The largest value s, b and r can have is s = 1779033703, b = 1, r = 3558067407 when sqrt_input = 2^64 - 1
r2 + b <= 1779033703*1779033704 + 3558067407*2^32 + 1 = 18446744068217447385 < 2^64
Second inequality: r + 1 > sqrt(2^64 + sqrt_input) * 2 - 2^33
-----------------------------------------------------------------------------------
r + 1 > sqrt(2^64 + sqrt_input) * 2 - 2^33
r + 1 + 2^33 > sqrt(2^64 + sqrt_input) * 2
((r+1)/2 + 2^32)^2 > 2^64 + sqrt_input
Rewrite r as r = s * 2 + b (s = trunc(r/2), b is 0 or 1)
((s*2+b+1)/2 + 2^32)^2 > 2^64 + sqrt_input
(s*2+b+1)^2/4 + 2*(s*2+b+1)/2*2^32 + 2^64 > 2^64 + sqrt_input
(s*2+b+1)^2/4 + (s*2+b+1)*2^32 > sqrt_input
(s*2+b+1)^2/4 + (r+1)*2^32 > sqrt_input
(s*2+(b+1))^2/4 + r*2^32 + 2^32 > sqrt_input
(s^2*4+2*s*2*(b+1)+(b+1)^2)/4 + r*2^32 + 2^32 > sqrt_input
s^2+s*(b+1)+(b+1)^2/4 + r*2^32 + 2^32 > sqrt_input
s*(s+b) + s + (b+1)^2/4 + r*2^32 + 2^32 > sqrt_input
Let r2 = s*(s+b) + r*2^32
r2 + s + (b+1)^2/4 + 2^32 > sqrt_input
r2 + 2^32 + (b+1)^2/4 > sqrt_input - s
If this inequality doesn't hold, then we must decrement r: IF "r2 + 2^32 + (b+1)^2/4 <= sqrt_input - s" THEN r = r - 1
b can be 0 or 1
If b is 0 then we need to compare "r2 + 2^32 + 1/4 <= sqrt_input - s" which is equal to "r2 + 2^32 < sqrt_input - s" because all numbers here are integers
If b is 1 then (b+1)^2/4 = 1, so we need to compare "r2 + 2^32 + 1 <= sqrt_input - s" which is also equal to "r2 + 2^32 < sqrt_input - s"
-----------------------------------------------------------------------------------
Both cases can be merged to a single expression "r2 + 2^32 < sqrt_input - s"
-----------------------------------------------------------------------------------
There will be no overflow when calculating "r2 + 2^32":
r2 + 2^32 = s*(s+b) + r*2^32 + 2^32 = s*(s+b) + (r+1)*2^32
The largest value s, b and r can have is s = 1779033703, b = 1, r = 3558067407 when sqrt_input = 2^64 - 1
r2 + b <= 1779033703*1779033704 + 3558067408*2^32 = 18446744072512414680 < 2^64
There will be no integer overflow when calculating "sqrt_input - s", i.e. "sqrt_input >= s" at all times:
s = trunc(r/2) = trunc(sqrt(2^64 + sqrt_input) - 2^32) < sqrt(2^64 + sqrt_input) - 2^32 + 1
sqrt_input > sqrt(2^64 + sqrt_input) - 2^32 + 1
sqrt_input + 2^32 - 1 > sqrt(2^64 + sqrt_input)
(sqrt_input + 2^32 - 1)^2 > sqrt_input + 2^64
sqrt_input^2 + 2*sqrt_input*(2^32 - 1) + (2^32-1)^2 > sqrt_input + 2^64
sqrt_input^2 + sqrt_input*(2^33 - 2) + (2^32-1)^2 > sqrt_input + 2^64
sqrt_input^2 + sqrt_input*(2^33 - 3) + (2^32-1)^2 > 2^64
sqrt_input^2 + sqrt_input*(2^33 - 3) + 2^64-2^33+1 > 2^64
sqrt_input^2 + sqrt_input*(2^33 - 3) - 2^33 + 1 > 0
This inequality is true if sqrt_input > 1 and it's easy to check that s = 0 if sqrt_input is 0 or 1, so there will be no integer overflow
*/
#define VARIANT2_INTEGER_MATH_SQRT_FIXUP(r) \
do { \
const uint64_t s = r >> 1; \
const uint64_t b = r & 1; \
const uint64_t r2 = (uint64_t)(s) * (s + b) + (r << 32); \
r += ((r2 + b > sqrt_input) ? -1 : 0) + ((r2 + (1ULL << 32) < sqrt_input - s) ? 1 : 0); \
} while(0)
#endif

View file

@ -1,301 +0,0 @@
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// Portions Copyright (c) 2018 The Monero developers
// Portions Copyright (c) 2018 The TurtleCoin Developers
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "crypto/oaes_lib.h"
#include "crypto/c_keccak.h"
#include "crypto/c_groestl.h"
#include "crypto/c_blake256.h"
#include "crypto/c_jh.h"
#include "../../cn/c_skein.h"
#include "crypto/int-util.h"
#include "crypto/hash-ops.h"
#include "crypto/variant2_int_sqrt.h"
#if defined(_MSC_VER)
#include <malloc.h>
#endif
#define MEMORY 524288 /* 512KB - 2^19 */
#define ITER 262144 /* 2^18 */
#define ITER_DIV 131072 /* 2^17 */
#define AES_BLOCK_SIZE 16
#define AES_KEY_SIZE 32 /*16*/
#define INIT_SIZE_BLK 8
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE)
#define CN_INIT (MEMORY / INIT_SIZE_BYTE)
#define CN_AES_INIT (MEMORY / AES_BLOCK_SIZE)
#define VARIANT1_1(p) \
do if (variant == 1) \
{ \
const uint8_t tmp = ((const uint8_t*)(p))[11]; \
static const uint32_t table = 0x75310; \
const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \
((uint8_t*)(p))[11] = tmp ^ ((table >> index) & 0x30); \
} while(0)
#define VARIANT1_2(p) \
do if (variant == 1) \
{ \
((uint64_t*)p)[1] ^= tweak1_2; \
} while(0)
#define VARIANT1_INIT() \
if (variant == 1 && len < 43) \
{ \
fprintf(stderr, "Cryptonight variant 1 needs at least 43 bytes of data"); \
_exit(1); \
} \
const uint64_t tweak1_2 = (variant == 1) ? *(const uint64_t*)(((const uint8_t*)input)+35) ^ ctx->state.hs.w[24] : 0
#define U64(p) ((uint64_t*)(p))
#define VARIANT2_INIT(b, state) \
uint64_t division_result; \
uint64_t sqrt_result; \
do if (variant >= 2) \
{ \
U64(b)[2] = state.hs.w[8] ^ state.hs.w[10]; \
U64(b)[3] = state.hs.w[9] ^ state.hs.w[11]; \
division_result = state.hs.w[12]; \
sqrt_result = state.hs.w[13]; \
} while (0)
#define VARIANT2_SHUFFLE_ADD(base_ptr, offset, a, b) \
do if (variant >= 2) \
{ \
uint64_t* chunk1 = U64((base_ptr) + ((offset) ^ 0x10)); \
uint64_t* chunk2 = U64((base_ptr) + ((offset) ^ 0x20)); \
uint64_t* chunk3 = U64((base_ptr) + ((offset) ^ 0x30)); \
\
const uint64_t chunk1_old[2] = { chunk1[0], chunk1[1] }; \
\
chunk1[0] = chunk3[0] + U64(b + 16)[0]; \
chunk1[1] = chunk3[1] + U64(b + 16)[1]; \
\
chunk3[0] = chunk2[0] + U64(a)[0]; \
chunk3[1] = chunk2[1] + U64(a)[1]; \
\
chunk2[0] = chunk1_old[0] + U64(b)[0]; \
chunk2[1] = chunk1_old[1] + U64(b)[1]; \
} while (0)
#define VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr) \
((uint64_t*)(b))[0] ^= division_result ^ (sqrt_result << 32); \
{ \
const uint64_t dividend = ((uint64_t*)(ptr))[1]; \
const uint32_t divisor = (((uint32_t*)(ptr))[0] + (uint32_t)(sqrt_result << 1)) | 0x80000001UL; \
division_result = ((uint32_t)(dividend / divisor)) + \
(((uint64_t)(dividend % divisor)) << 32); \
} \
const uint64_t sqrt_input = ((uint64_t*)(ptr))[0] + division_result
#define VARIANT2_INTEGER_MATH(b, ptr) \
do if (variant >= 2) \
{ \
VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr); \
VARIANT2_INTEGER_MATH_SQRT_STEP_FP64(); \
VARIANT2_INTEGER_MATH_SQRT_FIXUP(sqrt_result); \
} while (0)
#define VARIANT2_2() \
do if (variant >= 2) { \
((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x10)))[0] ^= hi; \
((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x10)))[1] ^= lo; \
hi ^= ((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x20)))[0]; \
lo ^= ((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x20)))[1]; \
} while (0)
#pragma pack(push, 1)
union cn_slow_hash_state {
union hash_state hs;
struct {
uint8_t k[64];
uint8_t init[INIT_SIZE_BYTE];
};
};
#pragma pack(pop)
static void do_dark_blake_hash(const void* input, size_t len, char* output) {
blake256_hash((uint8_t*)output, input, len);
}
void do_dark_groestl_hash(const void* input, size_t len, char* output) {
groestl(input, len * 8, (uint8_t*)output);
}
static void do_dark_jh_hash(const void* input, size_t len, char* output) {
int r = jh_hash(HASH_SIZE * 8, input, 8 * len, (uint8_t*)output);
assert(SUCCESS == r);
}
static void do_dark_skein_hash(const void* input, size_t len, char* output) {
int r = skein_hash(8 * HASH_SIZE, input, 8 * len, (uint8_t*)output);
assert(SKEIN_SUCCESS == r);
}
static void (* const extra_hashes[3])(const void *, size_t, char *) = {
do_dark_blake_hash, do_dark_groestl_hash, do_dark_skein_hash
};
extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
static inline size_t e2i(const uint8_t* a) {
return (*((uint64_t*) a) / AES_BLOCK_SIZE) & (CN_AES_INIT - 1);
}
static void mul(const uint8_t* a, const uint8_t* b, uint8_t* res) {
((uint64_t*) res)[1] = mul128(((uint64_t*) a)[0], ((uint64_t*) b)[0], (uint64_t*) res);
}
static void sum_half_blocks(uint8_t* a, const uint8_t* b) {
uint64_t a0, a1, b0, b1;
a0 = SWAP64LE(((uint64_t*) a)[0]);
a1 = SWAP64LE(((uint64_t*) a)[1]);
b0 = SWAP64LE(((uint64_t*) b)[0]);
b1 = SWAP64LE(((uint64_t*) b)[1]);
a0 += b0;
a1 += b1;
((uint64_t*) a)[0] = SWAP64LE(a0);
((uint64_t*) a)[1] = SWAP64LE(a1);
}
static inline void copy_block(uint8_t* dst, const uint8_t* src) {
((uint64_t*) dst)[0] = ((uint64_t*) src)[0];
((uint64_t*) dst)[1] = ((uint64_t*) src)[1];
}
static void swap_blocks(uint8_t* a, uint8_t* b) {
size_t i;
uint8_t t;
for (i = 0; i < AES_BLOCK_SIZE; i++) {
t = a[i];
a[i] = b[i];
b[i] = t;
}
}
static inline void xor_blocks(uint8_t* a, const uint8_t* b) {
((uint64_t*) a)[0] ^= ((uint64_t*) b)[0];
((uint64_t*) a)[1] ^= ((uint64_t*) b)[1];
}
static inline void xor_blocks_dst(const uint8_t* a, const uint8_t* b, uint8_t* dst) {
((uint64_t*) dst)[0] = ((uint64_t*) a)[0] ^ ((uint64_t*) b)[0];
((uint64_t*) dst)[1] = ((uint64_t*) a)[1] ^ ((uint64_t*) b)[1];
}
struct cryptonightdark_ctx {
uint8_t long_state[MEMORY];
union cn_slow_hash_state state;
uint8_t text[INIT_SIZE_BYTE];
uint8_t a[AES_BLOCK_SIZE];
uint8_t b[AES_BLOCK_SIZE * 2];
uint8_t c[AES_BLOCK_SIZE];
uint8_t aes_key[AES_KEY_SIZE];
oaes_ctx* aes_ctx;
};
void cryptonightdark_hash(const char* input, char* output, uint32_t len, int variant) {
#if defined(_MSC_VER)
struct cryptonightdark_ctx *ctx = _malloca(sizeof(struct cryptonightdark_ctx));
#else
struct cryptonightdark_ctx *ctx = alloca(sizeof(struct cryptonightdark_ctx));
#endif
hash_process(&ctx->state.hs, (const uint8_t*) input, len);
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
memcpy(ctx->aes_key, ctx->state.hs.b, AES_KEY_SIZE);
ctx->aes_ctx = (oaes_ctx*) oaes_alloc();
size_t i, j;
VARIANT1_INIT();
VARIANT2_INIT(ctx->b, ctx->state);
oaes_key_import_data(ctx->aes_ctx, ctx->aes_key, AES_KEY_SIZE);
for (i = 0; i < CN_INIT; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
aesb_pseudo_round(&ctx->text[AES_BLOCK_SIZE * j],
&ctx->text[AES_BLOCK_SIZE * j],
ctx->aes_ctx->key->exp_data);
}
memcpy(&ctx->long_state[i * INIT_SIZE_BYTE], ctx->text, INIT_SIZE_BYTE);
}
for (i = 0; i < 16; i++) {
ctx->a[i] = ctx->state.k[i] ^ ctx->state.k[32 + i];
ctx->b[i] = ctx->state.k[16 + i] ^ ctx->state.k[48 + i];
}
for (i = 0; i < ITER_DIV; i++) {
/* Dependency chain: address -> read value ------+
* written value <-+ hard function (AES or MUL) <+
* next address <-+
*/
/* Iteration 1 */
j = e2i(ctx->a);
aesb_single_round(&ctx->long_state[j * AES_BLOCK_SIZE], ctx->c, ctx->a);
VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b);
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j * AES_BLOCK_SIZE]);
VARIANT1_1((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
/* Iteration 2 */
j = e2i(ctx->c);
uint64_t* dst = (uint64_t*)&ctx->long_state[j * AES_BLOCK_SIZE];
uint64_t t[2];
t[0] = dst[0];
t[1] = dst[1];
VARIANT2_INTEGER_MATH(t, ctx->c);
uint64_t hi;
uint64_t lo = mul128(((uint64_t*)ctx->c)[0], t[0], &hi);
VARIANT2_2();
VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b);
((uint64_t*)ctx->a)[0] += hi;
((uint64_t*)ctx->a)[1] += lo;
dst[0] = ((uint64_t*)ctx->a)[0];
dst[1] = ((uint64_t*)ctx->a)[1];
((uint64_t*)ctx->a)[0] ^= t[0];
((uint64_t*)ctx->a)[1] ^= t[1];
VARIANT1_2((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
copy_block(ctx->b + AES_BLOCK_SIZE, ctx->b);
copy_block(ctx->b, ctx->c);
}
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
oaes_key_import_data(ctx->aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE);
for (i = 0; i < CN_INIT; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
xor_blocks(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
aesb_pseudo_round(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->text[j * AES_BLOCK_SIZE],
ctx->aes_ctx->key->exp_data);
}
}
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
hash_permutation(&ctx->state.hs);
/*memcpy(hash, &state, 32);*/
extra_hashes[ctx->state.hs.b[0] & 2](&ctx->state, 200, output);
oaes_free((OAES_CTX **) &ctx->aes_ctx);
}
void cryptonightdark_fast_hash(const char* input, char* output, uint32_t len) {
union hash_state state;
hash_process(&state, (const uint8_t*) input, len);
memcpy(output, &state, HASH_SIZE);
}

View file

@ -1,17 +0,0 @@
#ifndef CRYPTONIGHTDARK_H
#define CRYPTONIGHTDARK_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void cryptonightdark_hash(const char* input, char* output, uint32_t len, int variant);
void cryptonightdark_fast_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,301 +0,0 @@
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// Portions Copyright (c) 2018 The Monero developers
// Portions Copyright (c) 2018 The darkCoin Developers
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "crypto/oaes_lib.h"
#include "crypto/c_keccak.h"
#include "crypto/c_groestl.h"
#include "crypto/c_blake256.h"
#include "crypto/c_jh.h"
#include "../../cn/c_skein.h"
#include "crypto/int-util.h"
#include "crypto/hash-ops.h"
#include "crypto/variant2_int_sqrt.h"
#if defined(_MSC_VER)
#include <malloc.h>
#endif
#define MEMORY 524288 /* 512KB - 2^19 */
#define ITER 262144 /* 2^18 */
#define ITER_DIV 131072 /* 2^17 */
#define AES_BLOCK_SIZE 16
#define AES_KEY_SIZE 32 /*16*/
#define INIT_SIZE_BLK 8
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE)
#define CN_INIT (MEMORY / INIT_SIZE_BYTE)
#define CN_AES_INIT (MEMORY / AES_BLOCK_SIZE) / 2
#define VARIANT1_1(p) \
do if (variant == 1) \
{ \
const uint8_t tmp = ((const uint8_t*)(p))[11]; \
static const uint32_t table = 0x75310; \
const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \
((uint8_t*)(p))[11] = tmp ^ ((table >> index) & 0x30); \
} while(0)
#define VARIANT1_2(p) \
do if (variant == 1) \
{ \
((uint64_t*)p)[1] ^= tweak1_2; \
} while(0)
#define VARIANT1_INIT() \
if (variant == 1 && len < 43) \
{ \
fprintf(stderr, "Cryptonight variant 1 needs at least 43 bytes of data"); \
_exit(1); \
} \
const uint64_t tweak1_2 = (variant == 1) ? *(const uint64_t*)(((const uint8_t*)input)+35) ^ ctx->state.hs.w[24] : 0
#define U64(p) ((uint64_t*)(p))
#define VARIANT2_INIT(b, state) \
uint64_t division_result; \
uint64_t sqrt_result; \
do if (variant >= 2) \
{ \
U64(b)[2] = state.hs.w[8] ^ state.hs.w[10]; \
U64(b)[3] = state.hs.w[9] ^ state.hs.w[11]; \
division_result = state.hs.w[12]; \
sqrt_result = state.hs.w[13]; \
} while (0)
#define VARIANT2_SHUFFLE_ADD(base_ptr, offset, a, b) \
do if (variant >= 2) \
{ \
uint64_t* chunk1 = U64((base_ptr) + ((offset) ^ 0x10)); \
uint64_t* chunk2 = U64((base_ptr) + ((offset) ^ 0x20)); \
uint64_t* chunk3 = U64((base_ptr) + ((offset) ^ 0x30)); \
\
const uint64_t chunk1_old[2] = { chunk1[0], chunk1[1] }; \
\
chunk1[0] = chunk3[0] + U64(b + 16)[0]; \
chunk1[1] = chunk3[1] + U64(b + 16)[1]; \
\
chunk3[0] = chunk2[0] + U64(a)[0]; \
chunk3[1] = chunk2[1] + U64(a)[1]; \
\
chunk2[0] = chunk1_old[0] + U64(b)[0]; \
chunk2[1] = chunk1_old[1] + U64(b)[1]; \
} while (0)
#define VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr) \
((uint64_t*)(b))[0] ^= division_result ^ (sqrt_result << 32); \
{ \
const uint64_t dividend = ((uint64_t*)(ptr))[1]; \
const uint32_t divisor = (((uint32_t*)(ptr))[0] + (uint32_t)(sqrt_result << 1)) | 0x80000001UL; \
division_result = ((uint32_t)(dividend / divisor)) + \
(((uint64_t)(dividend % divisor)) << 32); \
} \
const uint64_t sqrt_input = ((uint64_t*)(ptr))[0] + division_result
#define VARIANT2_INTEGER_MATH(b, ptr) \
do if (variant >= 2) \
{ \
VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr); \
VARIANT2_INTEGER_MATH_SQRT_STEP_FP64(); \
VARIANT2_INTEGER_MATH_SQRT_FIXUP(sqrt_result); \
} while (0)
#define VARIANT2_2() \
do if (variant >= 2) { \
((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x10)))[0] ^= hi; \
((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x10)))[1] ^= lo; \
hi ^= ((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x20)))[0]; \
lo ^= ((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x20)))[1]; \
} while (0)
#pragma pack(push, 1)
union cn_slow_hash_state {
union hash_state hs;
struct {
uint8_t k[64];
uint8_t init[INIT_SIZE_BYTE];
};
};
#pragma pack(pop)
static void do_dark_lite_blake_hash(const void* input, size_t len, char* output) {
blake256_hash((uint8_t*)output, input, len);
}
void do_dark_lite_groestl_hash(const void* input, size_t len, char* output) {
groestl(input, len * 8, (uint8_t*)output);
}
static void do_dark_lite_jh_hash(const void* input, size_t len, char* output) {
int r = jh_hash(HASH_SIZE * 8, input, 8 * len, (uint8_t*)output);
assert(SUCCESS == r);
}
static void do_dark_lite_skein_hash(const void* input, size_t len, char* output) {
int r = skein_hash(8 * HASH_SIZE, input, 8 * len, (uint8_t*)output);
assert(SKEIN_SUCCESS == r);
}
static void (* const extra_hashes[3])(const void *, size_t, char *) = {
do_dark_lite_blake_hash, do_dark_lite_groestl_hash, do_dark_lite_skein_hash
};
extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
static inline size_t e2i(const uint8_t* a) {
return (*((uint64_t*) a) / AES_BLOCK_SIZE) & (CN_AES_INIT - 1);
}
static void mul(const uint8_t* a, const uint8_t* b, uint8_t* res) {
((uint64_t*) res)[1] = mul128(((uint64_t*) a)[0], ((uint64_t*) b)[0], (uint64_t*) res);
}
static void sum_half_blocks(uint8_t* a, const uint8_t* b) {
uint64_t a0, a1, b0, b1;
a0 = SWAP64LE(((uint64_t*) a)[0]);
a1 = SWAP64LE(((uint64_t*) a)[1]);
b0 = SWAP64LE(((uint64_t*) b)[0]);
b1 = SWAP64LE(((uint64_t*) b)[1]);
a0 += b0;
a1 += b1;
((uint64_t*) a)[0] = SWAP64LE(a0);
((uint64_t*) a)[1] = SWAP64LE(a1);
}
static inline void copy_block(uint8_t* dst, const uint8_t* src) {
((uint64_t*) dst)[0] = ((uint64_t*) src)[0];
((uint64_t*) dst)[1] = ((uint64_t*) src)[1];
}
static void swap_blocks(uint8_t* a, uint8_t* b) {
size_t i;
uint8_t t;
for (i = 0; i < AES_BLOCK_SIZE; i++) {
t = a[i];
a[i] = b[i];
b[i] = t;
}
}
static inline void xor_blocks(uint8_t* a, const uint8_t* b) {
((uint64_t*) a)[0] ^= ((uint64_t*) b)[0];
((uint64_t*) a)[1] ^= ((uint64_t*) b)[1];
}
static inline void xor_blocks_dst(const uint8_t* a, const uint8_t* b, uint8_t* dst) {
((uint64_t*) dst)[0] = ((uint64_t*) a)[0] ^ ((uint64_t*) b)[0];
((uint64_t*) dst)[1] = ((uint64_t*) a)[1] ^ ((uint64_t*) b)[1];
}
struct cryptonightdarklite_ctx {
uint8_t long_state[MEMORY];
union cn_slow_hash_state state;
uint8_t text[INIT_SIZE_BYTE];
uint8_t a[AES_BLOCK_SIZE];
uint8_t b[AES_BLOCK_SIZE * 2];
uint8_t c[AES_BLOCK_SIZE];
uint8_t aes_key[AES_KEY_SIZE];
oaes_ctx* aes_ctx;
};
void cryptonightdarklite_hash(const char* input, char* output, uint32_t len, int variant) {
#if defined(_MSC_VER)
struct cryptonightdarklite_ctx *ctx = _malloca(sizeof(struct cryptonightdarklite_ctx));
#else
struct cryptonightdarklite_ctx *ctx = alloca(sizeof(struct cryptonightdarklite_ctx));
#endif
hash_process(&ctx->state.hs, (const uint8_t*) input, len);
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
memcpy(ctx->aes_key, ctx->state.hs.b, AES_KEY_SIZE);
ctx->aes_ctx = (oaes_ctx*) oaes_alloc();
size_t i, j;
VARIANT1_INIT();
VARIANT2_INIT(ctx->b, ctx->state);
oaes_key_import_data(ctx->aes_ctx, ctx->aes_key, AES_KEY_SIZE);
for (i = 0; i < CN_INIT; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
aesb_pseudo_round(&ctx->text[AES_BLOCK_SIZE * j],
&ctx->text[AES_BLOCK_SIZE * j],
ctx->aes_ctx->key->exp_data);
}
memcpy(&ctx->long_state[i * INIT_SIZE_BYTE], ctx->text, INIT_SIZE_BYTE);
}
for (i = 0; i < 16; i++) {
ctx->a[i] = ctx->state.k[i] ^ ctx->state.k[32 + i];
ctx->b[i] = ctx->state.k[16 + i] ^ ctx->state.k[48 + i];
}
for (i = 0; i < ITER_DIV; i++) {
/* Dependency chain: address -> read value ------+
* written value <-+ hard function (AES or MUL) <+
* next address <-+
*/
/* Iteration 1 */
j = e2i(ctx->a);
aesb_single_round(&ctx->long_state[j * AES_BLOCK_SIZE], ctx->c, ctx->a);
VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b);
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j * AES_BLOCK_SIZE]);
VARIANT1_1((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
/* Iteration 2 */
j = e2i(ctx->c);
uint64_t* dst = (uint64_t*)&ctx->long_state[j * AES_BLOCK_SIZE];
uint64_t t[2];
t[0] = dst[0];
t[1] = dst[1];
VARIANT2_INTEGER_MATH(t, ctx->c);
uint64_t hi;
uint64_t lo = mul128(((uint64_t*)ctx->c)[0], t[0], &hi);
VARIANT2_2();
VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b);
((uint64_t*)ctx->a)[0] += hi;
((uint64_t*)ctx->a)[1] += lo;
dst[0] = ((uint64_t*)ctx->a)[0];
dst[1] = ((uint64_t*)ctx->a)[1];
((uint64_t*)ctx->a)[0] ^= t[0];
((uint64_t*)ctx->a)[1] ^= t[1];
VARIANT1_2((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
copy_block(ctx->b + AES_BLOCK_SIZE, ctx->b);
copy_block(ctx->b, ctx->c);
}
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
oaes_key_import_data(ctx->aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE);
for (i = 0; i < CN_INIT; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
xor_blocks(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
aesb_pseudo_round(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->text[j * AES_BLOCK_SIZE],
ctx->aes_ctx->key->exp_data);
}
}
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
hash_permutation(&ctx->state.hs);
/*memcpy(hash, &state, 32);*/
extra_hashes[ctx->state.hs.b[0] & 2](&ctx->state, 200, output);
oaes_free((OAES_CTX **) &ctx->aes_ctx);
}
void cryptonightdarklite_fast_hash(const char* input, char* output, uint32_t len) {
union hash_state state;
hash_process(&state, (const uint8_t*) input, len);
memcpy(output, &state, HASH_SIZE);
}

View file

@ -1,17 +0,0 @@
#ifndef CRYPTONIGHTDARKLITE_H
#define CRYPTONIGHTDARKLITE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void cryptonightdarklite_hash(const char* input, char* output, uint32_t len, int variant);
void cryptonightdarklite_fast_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,298 +0,0 @@
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// Portions Copyright (c) 2018 The Monero developers
// Portions Copyright (c) 2018 The TurtleCoin Developers
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "crypto/oaes_lib.h"
#include "crypto/c_keccak.h"
#include "crypto/c_groestl.h"
#include "crypto/c_blake256.h"
#include "crypto/c_jh.h"
#include "../../cn/c_skein.h"
#include "crypto/int-util.h"
#include "crypto/hash-ops.h"
#include "crypto/variant2_int_sqrt.h"
#if defined(_MSC_VER)
#include <malloc.h>
#endif
#define MEMORY 2097152 /* 2 MiB 2^21 */
#define ITER 524288 /* 2^19 */
#define ITER_DIV 262144 /* 2^18 */
#define AES_BLOCK_SIZE 16
#define AES_KEY_SIZE 32 /*16*/
#define INIT_SIZE_BLK 8
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE)
#define CN_INIT (MEMORY / INIT_SIZE_BYTE)
#define CN_AES_INIT (MEMORY / AES_BLOCK_SIZE)
#define VARIANT1_1(p) \
do if (variant == 1) \
{ \
const uint8_t tmp = ((const uint8_t*)(p))[11]; \
static const uint32_t table = 0x75310; \
const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \
((uint8_t*)(p))[11] = tmp ^ ((table >> index) & 0x30); \
} while(0)
#define VARIANT1_2(p) \
do if (variant == 1) \
{ \
((uint64_t*)p)[1] ^= tweak1_2; \
} while(0)
#define VARIANT1_INIT() \
if (variant == 1 && len < 43) \
{ \
fprintf(stderr, "Cryptonight variant 1 needs at least 43 bytes of data"); \
_exit(1); \
} \
const uint64_t tweak1_2 = (variant == 1) ? *(const uint64_t*)(((const uint8_t*)input)+35) ^ ctx->state.hs.w[24] : 0
#define U64(p) ((uint64_t*)(p))
#define VARIANT2_INIT(b, state) \
uint64_t division_result; \
uint64_t sqrt_result; \
do if (variant >= 2) \
{ \
U64(b)[2] = state.hs.w[8] ^ state.hs.w[10]; \
U64(b)[3] = state.hs.w[9] ^ state.hs.w[11]; \
division_result = state.hs.w[12]; \
sqrt_result = state.hs.w[13]; \
} while (0)
#define VARIANT2_SHUFFLE_ADD(base_ptr, offset, a, b) \
do if (variant >= 2) \
{ \
uint64_t* chunk1 = U64((base_ptr) + ((offset) ^ 0x10)); \
uint64_t* chunk2 = U64((base_ptr) + ((offset) ^ 0x20)); \
uint64_t* chunk3 = U64((base_ptr) + ((offset) ^ 0x30)); \
\
const uint64_t chunk1_old[2] = { chunk1[0], chunk1[1] }; \
\
chunk1[0] = chunk3[0] + U64(b + 16)[0]; \
chunk1[1] = chunk3[1] + U64(b + 16)[1]; \
\
chunk3[0] = chunk2[0] + U64(a)[0]; \
chunk3[1] = chunk2[1] + U64(a)[1]; \
\
chunk2[0] = chunk1_old[0] + U64(b)[0]; \
chunk2[1] = chunk1_old[1] + U64(b)[1]; \
} while (0)
#define VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr) \
((uint64_t*)(b))[0] ^= division_result ^ (sqrt_result << 32); \
{ \
const uint64_t dividend = ((uint64_t*)(ptr))[1]; \
const uint32_t divisor = (((uint32_t*)(ptr))[0] + (uint32_t)(sqrt_result << 1)) | 0x80000001UL; \
division_result = ((uint32_t)(dividend / divisor)) + \
(((uint64_t)(dividend % divisor)) << 32); \
} \
const uint64_t sqrt_input = ((uint64_t*)(ptr))[0] + division_result
#define VARIANT2_INTEGER_MATH(b, ptr) \
do if (variant >= 2) \
{ \
VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr); \
VARIANT2_INTEGER_MATH_SQRT_STEP_FP64(); \
VARIANT2_INTEGER_MATH_SQRT_FIXUP(sqrt_result); \
} while (0)
#define VARIANT2_2() \
do if (variant >= 2) { \
((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x10)))[0] ^= hi; \
((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x10)))[1] ^= lo; \
hi ^= ((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x20)))[0]; \
lo ^= ((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x20)))[1]; \
} while (0)
#pragma pack(push, 1)
union cn_slow_hash_state {
union hash_state hs;
struct {
uint8_t k[64];
uint8_t init[INIT_SIZE_BYTE];
};
};
#pragma pack(pop)
static void do_fast_blake_hash(const void* input, size_t len, char* output) {
blake256_hash((uint8_t*)output, input, len);
}
void do_fast_groestl_hash(const void* input, size_t len, char* output) {
groestl(input, len * 8, (uint8_t*)output);
}
static void do_fast_jh_hash(const void* input, size_t len, char* output) {
int r = jh_hash(HASH_SIZE * 8, input, 8 * len, (uint8_t*)output);
assert(SUCCESS == r);
}
static void do_fast_skein_hash(const void* input, size_t len, char* output) {
int r = skein_hash(8 * HASH_SIZE, input, 8 * len, (uint8_t*)output);
assert(SKEIN_SUCCESS == r);
}
static void (* const extra_hashes[3])(const void *, size_t, char *) = {
do_fast_blake_hash, do_fast_groestl_hash, do_fast_skein_hash
};
extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
static inline size_t e2i(const uint8_t* a) {
return (*((uint64_t*) a) / AES_BLOCK_SIZE) & (CN_AES_INIT - 1);
}
static void mul(const uint8_t* a, const uint8_t* b, uint8_t* res) {
((uint64_t*) res)[1] = mul128(((uint64_t*) a)[0], ((uint64_t*) b)[0], (uint64_t*) res);
}
static void sum_half_blocks(uint8_t* a, const uint8_t* b) {
uint64_t a0, a1, b0, b1;
a0 = SWAP64LE(((uint64_t*) a)[0]);
a1 = SWAP64LE(((uint64_t*) a)[1]);
b0 = SWAP64LE(((uint64_t*) b)[0]);
b1 = SWAP64LE(((uint64_t*) b)[1]);
a0 += b0;
a1 += b1;
((uint64_t*) a)[0] = SWAP64LE(a0);
((uint64_t*) a)[1] = SWAP64LE(a1);
}
static inline void copy_block(uint8_t* dst, const uint8_t* src) {
((uint64_t*) dst)[0] = ((uint64_t*) src)[0];
((uint64_t*) dst)[1] = ((uint64_t*) src)[1];
}
static void swap_blocks(uint8_t* a, uint8_t* b) {
size_t i;
uint8_t t;
for (i = 0; i < AES_BLOCK_SIZE; i++) {
t = a[i];
a[i] = b[i];
b[i] = t;
}
}
static inline void xor_blocks(uint8_t* a, const uint8_t* b) {
((uint64_t*) a)[0] ^= ((uint64_t*) b)[0];
((uint64_t*) a)[1] ^= ((uint64_t*) b)[1];
}
static inline void xor_blocks_dst(const uint8_t* a, const uint8_t* b, uint8_t* dst) {
((uint64_t*) dst)[0] = ((uint64_t*) a)[0] ^ ((uint64_t*) b)[0];
((uint64_t*) dst)[1] = ((uint64_t*) a)[1] ^ ((uint64_t*) b)[1];
}
struct cryptonightfast_ctx {
uint8_t long_state[MEMORY];
union cn_slow_hash_state state;
uint8_t text[INIT_SIZE_BYTE];
uint8_t a[AES_BLOCK_SIZE];
uint8_t b[AES_BLOCK_SIZE * 2];
uint8_t c[AES_BLOCK_SIZE];
uint8_t aes_key[AES_KEY_SIZE];
oaes_ctx* aes_ctx;
};
void cryptonightfast_hash(const char* input, char* output, uint32_t len, int variant) {
struct cryptonightfast_ctx *ctx = malloc(sizeof(struct cryptonightfast_ctx));
hash_process(&ctx->state.hs, (const uint8_t*) input, len);
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
memcpy(ctx->aes_key, ctx->state.hs.b, AES_KEY_SIZE);
ctx->aes_ctx = (oaes_ctx*) oaes_alloc();
size_t i, j;
VARIANT1_INIT();
VARIANT2_INIT(ctx->b, ctx->state);
oaes_key_import_data(ctx->aes_ctx, ctx->aes_key, AES_KEY_SIZE);
for (i = 0; i < CN_INIT; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
aesb_pseudo_round(&ctx->text[AES_BLOCK_SIZE * j],
&ctx->text[AES_BLOCK_SIZE * j],
ctx->aes_ctx->key->exp_data);
}
memcpy(&ctx->long_state[i * INIT_SIZE_BYTE], ctx->text, INIT_SIZE_BYTE);
}
for (i = 0; i < 16; i++) {
ctx->a[i] = ctx->state.k[i] ^ ctx->state.k[32 + i];
ctx->b[i] = ctx->state.k[16 + i] ^ ctx->state.k[48 + i];
}
for (i = 0; i < ITER_DIV; i++) {
/* Dependency chain: address -> read value ------+
* written value <-+ hard function (AES or MUL) <+
* next address <-+
*/
/* Iteration 1 */
j = e2i(ctx->a);
aesb_single_round(&ctx->long_state[j * AES_BLOCK_SIZE], ctx->c, ctx->a);
VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b);
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j * AES_BLOCK_SIZE]);
VARIANT1_1((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
/* Iteration 2 */
j = e2i(ctx->c);
uint64_t* dst = (uint64_t*)&ctx->long_state[j * AES_BLOCK_SIZE];
uint64_t t[2];
t[0] = dst[0];
t[1] = dst[1];
VARIANT2_INTEGER_MATH(t, ctx->c);
uint64_t hi;
uint64_t lo = mul128(((uint64_t*)ctx->c)[0], t[0], &hi);
VARIANT2_2();
VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b);
((uint64_t*)ctx->a)[0] += hi;
((uint64_t*)ctx->a)[1] += lo;
dst[0] = ((uint64_t*)ctx->a)[0];
dst[1] = ((uint64_t*)ctx->a)[1];
((uint64_t*)ctx->a)[0] ^= t[0];
((uint64_t*)ctx->a)[1] ^= t[1];
VARIANT1_2((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
copy_block(ctx->b + AES_BLOCK_SIZE, ctx->b);
copy_block(ctx->b, ctx->c);
}
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
oaes_key_import_data(ctx->aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE);
for (i = 0; i < CN_INIT; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
xor_blocks(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
aesb_pseudo_round(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->text[j * AES_BLOCK_SIZE],
ctx->aes_ctx->key->exp_data);
}
}
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
hash_permutation(&ctx->state.hs);
/*memcpy(hash, &state, 32);*/
extra_hashes[ctx->state.hs.b[0] & 2](&ctx->state, 200, output);
oaes_free((OAES_CTX **) &ctx->aes_ctx);
free(ctx);
}
void cryptonightfast_fast_hash(const char* input, char* output, uint32_t len) {
union hash_state state;
hash_process(&state, (const uint8_t*) input, len);
memcpy(output, &state, HASH_SIZE);
}

View file

@ -1,17 +0,0 @@
#ifndef CRYPTONIGHTFAST_H
#define CRYPTONIGHTFAST_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void cryptonightfast_hash(const char* input, char* output, uint32_t len, int variant);
void cryptonightfast_fast_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,301 +0,0 @@
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// Portions Copyright (c) 2018 The Monero developers
// Portions Copyright (c) 2018 The TurtleCoin Developers
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "crypto/oaes_lib.h"
#include "crypto/c_keccak.h"
#include "crypto/c_groestl.h"
#include "crypto/c_blake256.h"
#include "crypto/c_jh.h"
#include "../../cn/c_skein.h"
#include "crypto/int-util.h"
#include "crypto/hash-ops.h"
#include "crypto/variant2_int_sqrt.h"
#if defined(_MSC_VER)
#include <malloc.h>
#endif
#define MEMORY 1048576 /* 1 MiB - 2^20 */
#define ITER 524288 /* 2^19 */
#define ITER_DIV 262144 /* 2^18 */
#define AES_BLOCK_SIZE 16
#define AES_KEY_SIZE 32 /*16*/
#define INIT_SIZE_BLK 8
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE)
#define CN_INIT (MEMORY / INIT_SIZE_BYTE)
#define CN_AES_INIT (MEMORY / AES_BLOCK_SIZE)
#define VARIANT1_1(p) \
do if (variant == 1) \
{ \
const uint8_t tmp = ((const uint8_t*)(p))[11]; \
static const uint32_t table = 0x75310; \
const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \
((uint8_t*)(p))[11] = tmp ^ ((table >> index) & 0x30); \
} while(0)
#define VARIANT1_2(p) \
do if (variant == 1) \
{ \
((uint64_t*)p)[1] ^= tweak1_2; \
} while(0)
#define VARIANT1_INIT() \
if (variant == 1 && len < 43) \
{ \
fprintf(stderr, "Cryptonight variant 1 needs at least 43 bytes of data"); \
_exit(1); \
} \
const uint64_t tweak1_2 = (variant == 1) ? *(const uint64_t*)(((const uint8_t*)input)+35) ^ ctx->state.hs.w[24] : 0
#define U64(p) ((uint64_t*)(p))
#define VARIANT2_INIT(b, state) \
uint64_t division_result; \
uint64_t sqrt_result; \
do if (variant >= 2) \
{ \
U64(b)[2] = state.hs.w[8] ^ state.hs.w[10]; \
U64(b)[3] = state.hs.w[9] ^ state.hs.w[11]; \
division_result = state.hs.w[12]; \
sqrt_result = state.hs.w[13]; \
} while (0)
#define VARIANT2_SHUFFLE_ADD(base_ptr, offset, a, b) \
do if (variant >= 2) \
{ \
uint64_t* chunk1 = U64((base_ptr) + ((offset) ^ 0x10)); \
uint64_t* chunk2 = U64((base_ptr) + ((offset) ^ 0x20)); \
uint64_t* chunk3 = U64((base_ptr) + ((offset) ^ 0x30)); \
\
const uint64_t chunk1_old[2] = { chunk1[0], chunk1[1] }; \
\
chunk1[0] = chunk3[0] + U64(b + 16)[0]; \
chunk1[1] = chunk3[1] + U64(b + 16)[1]; \
\
chunk3[0] = chunk2[0] + U64(a)[0]; \
chunk3[1] = chunk2[1] + U64(a)[1]; \
\
chunk2[0] = chunk1_old[0] + U64(b)[0]; \
chunk2[1] = chunk1_old[1] + U64(b)[1]; \
} while (0)
#define VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr) \
((uint64_t*)(b))[0] ^= division_result ^ (sqrt_result << 32); \
{ \
const uint64_t dividend = ((uint64_t*)(ptr))[1]; \
const uint32_t divisor = (((uint32_t*)(ptr))[0] + (uint32_t)(sqrt_result << 1)) | 0x80000001UL; \
division_result = ((uint32_t)(dividend / divisor)) + \
(((uint64_t)(dividend % divisor)) << 32); \
} \
const uint64_t sqrt_input = ((uint64_t*)(ptr))[0] + division_result
#define VARIANT2_INTEGER_MATH(b, ptr) \
do if (variant >= 2) \
{ \
VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr); \
VARIANT2_INTEGER_MATH_SQRT_STEP_FP64(); \
VARIANT2_INTEGER_MATH_SQRT_FIXUP(sqrt_result); \
} while (0)
#define VARIANT2_2() \
do if (variant >= 2) { \
((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x10)))[0] ^= hi; \
((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x10)))[1] ^= lo; \
hi ^= ((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x20)))[0]; \
lo ^= ((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x20)))[1]; \
} while (0)
#pragma pack(push, 1)
union cn_slow_hash_state {
union hash_state hs;
struct {
uint8_t k[64];
uint8_t init[INIT_SIZE_BYTE];
};
};
#pragma pack(pop)
static void do_lite_blake_hash(const void* input, size_t len, char* output) {
blake256_hash((uint8_t*)output, input, len);
}
void do_lite_groestl_hash(const void* input, size_t len, char* output) {
groestl(input, len * 8, (uint8_t*)output);
}
static void do_lite_jh_hash(const void* input, size_t len, char* output) {
int r = jh_hash(HASH_SIZE * 8, input, 8 * len, (uint8_t*)output);
assert(SUCCESS == r);
}
static void do_lite_skein_hash(const void* input, size_t len, char* output) {
int r = skein_hash(8 * HASH_SIZE, input, 8 * len, (uint8_t*)output);
assert(SKEIN_SUCCESS == r);
}
static void (* const extra_hashes[3])(const void *, size_t, char *) = {
do_lite_blake_hash, do_lite_groestl_hash, do_lite_skein_hash
};
extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
static inline size_t e2i(const uint8_t* a) {
return (*((uint64_t*) a) / AES_BLOCK_SIZE) & (CN_AES_INIT - 1);
}
static void mul(const uint8_t* a, const uint8_t* b, uint8_t* res) {
((uint64_t*) res)[1] = mul128(((uint64_t*) a)[0], ((uint64_t*) b)[0], (uint64_t*) res);
}
static void sum_half_blocks(uint8_t* a, const uint8_t* b) {
uint64_t a0, a1, b0, b1;
a0 = SWAP64LE(((uint64_t*) a)[0]);
a1 = SWAP64LE(((uint64_t*) a)[1]);
b0 = SWAP64LE(((uint64_t*) b)[0]);
b1 = SWAP64LE(((uint64_t*) b)[1]);
a0 += b0;
a1 += b1;
((uint64_t*) a)[0] = SWAP64LE(a0);
((uint64_t*) a)[1] = SWAP64LE(a1);
}
static inline void copy_block(uint8_t* dst, const uint8_t* src) {
((uint64_t*) dst)[0] = ((uint64_t*) src)[0];
((uint64_t*) dst)[1] = ((uint64_t*) src)[1];
}
static void swap_blocks(uint8_t* a, uint8_t* b) {
size_t i;
uint8_t t;
for (i = 0; i < AES_BLOCK_SIZE; i++) {
t = a[i];
a[i] = b[i];
b[i] = t;
}
}
static inline void xor_blocks(uint8_t* a, const uint8_t* b) {
((uint64_t*) a)[0] ^= ((uint64_t*) b)[0];
((uint64_t*) a)[1] ^= ((uint64_t*) b)[1];
}
static inline void xor_blocks_dst(const uint8_t* a, const uint8_t* b, uint8_t* dst) {
((uint64_t*) dst)[0] = ((uint64_t*) a)[0] ^ ((uint64_t*) b)[0];
((uint64_t*) dst)[1] = ((uint64_t*) a)[1] ^ ((uint64_t*) b)[1];
}
struct cryptonightlite_ctx {
uint8_t long_state[MEMORY];
union cn_slow_hash_state state;
uint8_t text[INIT_SIZE_BYTE];
uint8_t a[AES_BLOCK_SIZE];
uint8_t b[AES_BLOCK_SIZE * 2];
uint8_t c[AES_BLOCK_SIZE];
uint8_t aes_key[AES_KEY_SIZE];
oaes_ctx* aes_ctx;
};
void cryptonightlite_hash(const char* input, char* output, uint32_t len, int variant) {
#if defined(_MSC_VER)
struct cryptonightlite_ctx *ctx = _malloca(sizeof(struct cryptonightlite_ctx));
#else
struct cryptonightlite_ctx *ctx = alloca(sizeof(struct cryptonightlite_ctx));
#endif
hash_process(&ctx->state.hs, (const uint8_t*) input, len);
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
memcpy(ctx->aes_key, ctx->state.hs.b, AES_KEY_SIZE);
ctx->aes_ctx = (oaes_ctx*) oaes_alloc();
size_t i, j;
VARIANT1_INIT();
VARIANT2_INIT(ctx->b, ctx->state);
oaes_key_import_data(ctx->aes_ctx, ctx->aes_key, AES_KEY_SIZE);
for (i = 0; i < CN_INIT; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
aesb_pseudo_round(&ctx->text[AES_BLOCK_SIZE * j],
&ctx->text[AES_BLOCK_SIZE * j],
ctx->aes_ctx->key->exp_data);
}
memcpy(&ctx->long_state[i * INIT_SIZE_BYTE], ctx->text, INIT_SIZE_BYTE);
}
for (i = 0; i < 16; i++) {
ctx->a[i] = ctx->state.k[i] ^ ctx->state.k[32 + i];
ctx->b[i] = ctx->state.k[16 + i] ^ ctx->state.k[48 + i];
}
for (i = 0; i < ITER_DIV; i++) {
/* Dependency chain: address -> read value ------+
* written value <-+ hard function (AES or MUL) <+
* next address <-+
*/
/* Iteration 1 */
j = e2i(ctx->a);
aesb_single_round(&ctx->long_state[j * AES_BLOCK_SIZE], ctx->c, ctx->a);
VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b);
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j * AES_BLOCK_SIZE]);
VARIANT1_1((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
/* Iteration 2 */
j = e2i(ctx->c);
uint64_t* dst = (uint64_t*)&ctx->long_state[j * AES_BLOCK_SIZE];
uint64_t t[2];
t[0] = dst[0];
t[1] = dst[1];
VARIANT2_INTEGER_MATH(t, ctx->c);
uint64_t hi;
uint64_t lo = mul128(((uint64_t*)ctx->c)[0], t[0], &hi);
VARIANT2_2();
VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b);
((uint64_t*)ctx->a)[0] += hi;
((uint64_t*)ctx->a)[1] += lo;
dst[0] = ((uint64_t*)ctx->a)[0];
dst[1] = ((uint64_t*)ctx->a)[1];
((uint64_t*)ctx->a)[0] ^= t[0];
((uint64_t*)ctx->a)[1] ^= t[1];
VARIANT1_2((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
copy_block(ctx->b + AES_BLOCK_SIZE, ctx->b);
copy_block(ctx->b, ctx->c);
}
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
oaes_key_import_data(ctx->aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE);
for (i = 0; i < CN_INIT; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
xor_blocks(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
aesb_pseudo_round(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->text[j * AES_BLOCK_SIZE],
ctx->aes_ctx->key->exp_data);
}
}
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
hash_permutation(&ctx->state.hs);
/*memcpy(hash, &state, 32);*/
extra_hashes[ctx->state.hs.b[0] & 2](&ctx->state, 200, output);
oaes_free((OAES_CTX **) &ctx->aes_ctx);
}
void cryptonightlite_fast_hash(const char* input, char* output, uint32_t len) {
union hash_state state;
hash_process(&state, (const uint8_t*) input, len);
memcpy(output, &state, HASH_SIZE);
}

View file

@ -1,17 +0,0 @@
#ifndef CRYPTONIGHTLITE_H
#define CRYPTONIGHTLITE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void cryptonightlite_hash(const char* input, char* output, uint32_t len, int variant);
void cryptonightlite_fast_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,301 +0,0 @@
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// Portions Copyright (c) 2018 The Monero developers
// Portions Copyright (c) 2018 The TurtleCoin Developers
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "crypto/oaes_lib.h"
#include "crypto/c_keccak.h"
#include "crypto/c_groestl.h"
#include "crypto/c_blake256.h"
#include "crypto/c_jh.h"
#include "../../cn/c_skein.h"
#include "crypto/int-util.h"
#include "crypto/hash-ops.h"
#include "crypto/variant2_int_sqrt.h"
#if defined(_MSC_VER)
#include <malloc.h>
#endif
#define MEMORY 262144 /* 256KB - 2^18 */
#define ITER 131072 /* 2^17 */
#define ITER_DIV 65536 /* 2^16 */
#define AES_BLOCK_SIZE 16
#define AES_KEY_SIZE 32 /*16*/
#define INIT_SIZE_BLK 8
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE)
#define CN_INIT (MEMORY / INIT_SIZE_BYTE)
#define CN_AES_INIT (MEMORY / AES_BLOCK_SIZE)
#define VARIANT1_1(p) \
do if (variant == 1) \
{ \
const uint8_t tmp = ((const uint8_t*)(p))[11]; \
static const uint32_t table = 0x75310; \
const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \
((uint8_t*)(p))[11] = tmp ^ ((table >> index) & 0x30); \
} while(0)
#define VARIANT1_2(p) \
do if (variant == 1) \
{ \
((uint64_t*)p)[1] ^= tweak1_2; \
} while(0)
#define VARIANT1_INIT() \
if (variant == 1 && len < 43) \
{ \
fprintf(stderr, "Cryptonight variant 1 needs at least 43 bytes of data"); \
_exit(1); \
} \
const uint64_t tweak1_2 = (variant == 1) ? *(const uint64_t*)(((const uint8_t*)input)+35) ^ ctx->state.hs.w[24] : 0
#define U64(p) ((uint64_t*)(p))
#define VARIANT2_INIT(b, state) \
uint64_t division_result; \
uint64_t sqrt_result; \
do if (variant >= 2) \
{ \
U64(b)[2] = state.hs.w[8] ^ state.hs.w[10]; \
U64(b)[3] = state.hs.w[9] ^ state.hs.w[11]; \
division_result = state.hs.w[12]; \
sqrt_result = state.hs.w[13]; \
} while (0)
#define VARIANT2_SHUFFLE_ADD(base_ptr, offset, a, b) \
do if (variant >= 2) \
{ \
uint64_t* chunk1 = U64((base_ptr) + ((offset) ^ 0x10)); \
uint64_t* chunk2 = U64((base_ptr) + ((offset) ^ 0x20)); \
uint64_t* chunk3 = U64((base_ptr) + ((offset) ^ 0x30)); \
\
const uint64_t chunk1_old[2] = { chunk1[0], chunk1[1] }; \
\
chunk1[0] = chunk3[0] + U64(b + 16)[0]; \
chunk1[1] = chunk3[1] + U64(b + 16)[1]; \
\
chunk3[0] = chunk2[0] + U64(a)[0]; \
chunk3[1] = chunk2[1] + U64(a)[1]; \
\
chunk2[0] = chunk1_old[0] + U64(b)[0]; \
chunk2[1] = chunk1_old[1] + U64(b)[1]; \
} while (0)
#define VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr) \
((uint64_t*)(b))[0] ^= division_result ^ (sqrt_result << 32); \
{ \
const uint64_t dividend = ((uint64_t*)(ptr))[1]; \
const uint32_t divisor = (((uint32_t*)(ptr))[0] + (uint32_t)(sqrt_result << 1)) | 0x80000001UL; \
division_result = ((uint32_t)(dividend / divisor)) + \
(((uint64_t)(dividend % divisor)) << 32); \
} \
const uint64_t sqrt_input = ((uint64_t*)(ptr))[0] + division_result
#define VARIANT2_INTEGER_MATH(b, ptr) \
do if (variant >= 2) \
{ \
VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr); \
VARIANT2_INTEGER_MATH_SQRT_STEP_FP64(); \
VARIANT2_INTEGER_MATH_SQRT_FIXUP(sqrt_result); \
} while (0)
#define VARIANT2_2() \
do if (variant >= 2) { \
((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x10)))[0] ^= hi; \
((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x10)))[1] ^= lo; \
hi ^= ((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x20)))[0]; \
lo ^= ((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x20)))[1]; \
} while (0)
#pragma pack(push, 1)
union cn_slow_hash_state {
union hash_state hs;
struct {
uint8_t k[64];
uint8_t init[INIT_SIZE_BYTE];
};
};
#pragma pack(pop)
static void do_turtle_blake_hash(const void* input, size_t len, char* output) {
blake256_hash((uint8_t*)output, input, len);
}
void do_turtle_groestl_hash(const void* input, size_t len, char* output) {
groestl(input, len * 8, (uint8_t*)output);
}
static void do_turtle_jh_hash(const void* input, size_t len, char* output) {
int r = jh_hash(HASH_SIZE * 8, input, 8 * len, (uint8_t*)output);
assert(SUCCESS == r);
}
static void do_turtle_skein_hash(const void* input, size_t len, char* output) {
int r = skein_hash(8 * HASH_SIZE, input, 8 * len, (uint8_t*)output);
assert(SKEIN_SUCCESS == r);
}
static void (* const extra_hashes[3])(const void *, size_t, char *) = {
do_turtle_blake_hash, do_turtle_groestl_hash, do_turtle_skein_hash
};
extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
static inline size_t e2i(const uint8_t* a) {
return (*((uint64_t*) a) / AES_BLOCK_SIZE) & (CN_AES_INIT - 1);
}
static void mul(const uint8_t* a, const uint8_t* b, uint8_t* res) {
((uint64_t*) res)[1] = mul128(((uint64_t*) a)[0], ((uint64_t*) b)[0], (uint64_t*) res);
}
static void sum_half_blocks(uint8_t* a, const uint8_t* b) {
uint64_t a0, a1, b0, b1;
a0 = SWAP64LE(((uint64_t*) a)[0]);
a1 = SWAP64LE(((uint64_t*) a)[1]);
b0 = SWAP64LE(((uint64_t*) b)[0]);
b1 = SWAP64LE(((uint64_t*) b)[1]);
a0 += b0;
a1 += b1;
((uint64_t*) a)[0] = SWAP64LE(a0);
((uint64_t*) a)[1] = SWAP64LE(a1);
}
static inline void copy_block(uint8_t* dst, const uint8_t* src) {
((uint64_t*) dst)[0] = ((uint64_t*) src)[0];
((uint64_t*) dst)[1] = ((uint64_t*) src)[1];
}
static void swap_blocks(uint8_t* a, uint8_t* b) {
size_t i;
uint8_t t;
for (i = 0; i < AES_BLOCK_SIZE; i++) {
t = a[i];
a[i] = b[i];
b[i] = t;
}
}
static inline void xor_blocks(uint8_t* a, const uint8_t* b) {
((uint64_t*) a)[0] ^= ((uint64_t*) b)[0];
((uint64_t*) a)[1] ^= ((uint64_t*) b)[1];
}
static inline void xor_blocks_dst(const uint8_t* a, const uint8_t* b, uint8_t* dst) {
((uint64_t*) dst)[0] = ((uint64_t*) a)[0] ^ ((uint64_t*) b)[0];
((uint64_t*) dst)[1] = ((uint64_t*) a)[1] ^ ((uint64_t*) b)[1];
}
struct cryptonightturtle_ctx {
uint8_t long_state[MEMORY];
union cn_slow_hash_state state;
uint8_t text[INIT_SIZE_BYTE];
uint8_t a[AES_BLOCK_SIZE];
uint8_t b[AES_BLOCK_SIZE * 2];
uint8_t c[AES_BLOCK_SIZE];
uint8_t aes_key[AES_KEY_SIZE];
oaes_ctx* aes_ctx;
};
void cryptonightturtle_hash(const char* input, char* output, uint32_t len, int variant) {
#if defined(_MSC_VER)
struct cryptonightturtle_ctx *ctx = _malloca(sizeof(struct cryptonightturtle_ctx));
#else
struct cryptonightturtle_ctx *ctx = alloca(sizeof(struct cryptonightturtle_ctx));
#endif
hash_process(&ctx->state.hs, (const uint8_t*) input, len);
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
memcpy(ctx->aes_key, ctx->state.hs.b, AES_KEY_SIZE);
ctx->aes_ctx = (oaes_ctx*) oaes_alloc();
size_t i, j;
VARIANT1_INIT();
VARIANT2_INIT(ctx->b, ctx->state);
oaes_key_import_data(ctx->aes_ctx, ctx->aes_key, AES_KEY_SIZE);
for (i = 0; i < CN_INIT; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
aesb_pseudo_round(&ctx->text[AES_BLOCK_SIZE * j],
&ctx->text[AES_BLOCK_SIZE * j],
ctx->aes_ctx->key->exp_data);
}
memcpy(&ctx->long_state[i * INIT_SIZE_BYTE], ctx->text, INIT_SIZE_BYTE);
}
for (i = 0; i < 16; i++) {
ctx->a[i] = ctx->state.k[i] ^ ctx->state.k[32 + i];
ctx->b[i] = ctx->state.k[16 + i] ^ ctx->state.k[48 + i];
}
for (i = 0; i < ITER_DIV; i++) {
/* Dependency chain: address -> read value ------+
* written value <-+ hard function (AES or MUL) <+
* next address <-+
*/
/* Iteration 1 */
j = e2i(ctx->a);
aesb_single_round(&ctx->long_state[j * AES_BLOCK_SIZE], ctx->c, ctx->a);
VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b);
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j * AES_BLOCK_SIZE]);
VARIANT1_1((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
/* Iteration 2 */
j = e2i(ctx->c);
uint64_t* dst = (uint64_t*)&ctx->long_state[j * AES_BLOCK_SIZE];
uint64_t t[2];
t[0] = dst[0];
t[1] = dst[1];
VARIANT2_INTEGER_MATH(t, ctx->c);
uint64_t hi;
uint64_t lo = mul128(((uint64_t*)ctx->c)[0], t[0], &hi);
VARIANT2_2();
VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b);
((uint64_t*)ctx->a)[0] += hi;
((uint64_t*)ctx->a)[1] += lo;
dst[0] = ((uint64_t*)ctx->a)[0];
dst[1] = ((uint64_t*)ctx->a)[1];
((uint64_t*)ctx->a)[0] ^= t[0];
((uint64_t*)ctx->a)[1] ^= t[1];
VARIANT1_2((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
copy_block(ctx->b + AES_BLOCK_SIZE, ctx->b);
copy_block(ctx->b, ctx->c);
}
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
oaes_key_import_data(ctx->aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE);
for (i = 0; i < CN_INIT; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
xor_blocks(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
aesb_pseudo_round(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->text[j * AES_BLOCK_SIZE],
ctx->aes_ctx->key->exp_data);
}
}
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
hash_permutation(&ctx->state.hs);
/*memcpy(hash, &state, 32);*/
extra_hashes[ctx->state.hs.b[0] & 2](&ctx->state, 200, output);
oaes_free((OAES_CTX **) &ctx->aes_ctx);
}
void cryptonightturtle_fast_hash(const char* input, char* output, uint32_t len) {
union hash_state state;
hash_process(&state, (const uint8_t*) input, len);
memcpy(output, &state, HASH_SIZE);
}

View file

@ -1,17 +0,0 @@
#ifndef CRYPTONIGHTTURTLE_H
#define CRYPTONIGHTTURTLE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void cryptonightturtle_hash(const char* input, char* output, uint32_t len, int variant);
void cryptonightturtle_fast_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,301 +0,0 @@
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// Portions Copyright (c) 2018 The Monero developers
// Portions Copyright (c) 2018 The TurtleCoin Developers
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "crypto/oaes_lib.h"
#include "crypto/c_keccak.h"
#include "crypto/c_groestl.h"
#include "crypto/c_blake256.h"
#include "crypto/c_jh.h"
#include "../../cn/c_skein.h"
#include "crypto/int-util.h"
#include "crypto/hash-ops.h"
#include "crypto/variant2_int_sqrt.h"
#if defined(_MSC_VER)
#include <malloc.h>
#endif
#define MEMORY 262144 /* 256KB - 2^18 */
#define ITER 131072 /* 2^17 */
#define ITER_DIV 65536 /* 2^16 */
#define AES_BLOCK_SIZE 16
#define AES_KEY_SIZE 32 /*16*/
#define INIT_SIZE_BLK 8
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE)
#define CN_INIT (MEMORY / INIT_SIZE_BYTE)
#define CN_AES_INIT (MEMORY / AES_BLOCK_SIZE) / 2
#define VARIANT1_1(p) \
do if (variant == 1) \
{ \
const uint8_t tmp = ((const uint8_t*)(p))[11]; \
static const uint32_t table = 0x75310; \
const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \
((uint8_t*)(p))[11] = tmp ^ ((table >> index) & 0x30); \
} while(0)
#define VARIANT1_2(p) \
do if (variant == 1) \
{ \
((uint64_t*)p)[1] ^= tweak1_2; \
} while(0)
#define VARIANT1_INIT() \
if (variant == 1 && len < 43) \
{ \
fprintf(stderr, "Cryptonight variant 1 needs at least 43 bytes of data"); \
_exit(1); \
} \
const uint64_t tweak1_2 = (variant == 1) ? *(const uint64_t*)(((const uint8_t*)input)+35) ^ ctx->state.hs.w[24] : 0
#define U64(p) ((uint64_t*)(p))
#define VARIANT2_INIT(b, state) \
uint64_t division_result; \
uint64_t sqrt_result; \
do if (variant >= 2) \
{ \
U64(b)[2] = state.hs.w[8] ^ state.hs.w[10]; \
U64(b)[3] = state.hs.w[9] ^ state.hs.w[11]; \
division_result = state.hs.w[12]; \
sqrt_result = state.hs.w[13]; \
} while (0)
#define VARIANT2_SHUFFLE_ADD(base_ptr, offset, a, b) \
do if (variant >= 2) \
{ \
uint64_t* chunk1 = U64((base_ptr) + ((offset) ^ 0x10)); \
uint64_t* chunk2 = U64((base_ptr) + ((offset) ^ 0x20)); \
uint64_t* chunk3 = U64((base_ptr) + ((offset) ^ 0x30)); \
\
const uint64_t chunk1_old[2] = { chunk1[0], chunk1[1] }; \
\
chunk1[0] = chunk3[0] + U64(b + 16)[0]; \
chunk1[1] = chunk3[1] + U64(b + 16)[1]; \
\
chunk3[0] = chunk2[0] + U64(a)[0]; \
chunk3[1] = chunk2[1] + U64(a)[1]; \
\
chunk2[0] = chunk1_old[0] + U64(b)[0]; \
chunk2[1] = chunk1_old[1] + U64(b)[1]; \
} while (0)
#define VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr) \
((uint64_t*)(b))[0] ^= division_result ^ (sqrt_result << 32); \
{ \
const uint64_t dividend = ((uint64_t*)(ptr))[1]; \
const uint32_t divisor = (((uint32_t*)(ptr))[0] + (uint32_t)(sqrt_result << 1)) | 0x80000001UL; \
division_result = ((uint32_t)(dividend / divisor)) + \
(((uint64_t)(dividend % divisor)) << 32); \
} \
const uint64_t sqrt_input = ((uint64_t*)(ptr))[0] + division_result
#define VARIANT2_INTEGER_MATH(b, ptr) \
do if (variant >= 2) \
{ \
VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr); \
VARIANT2_INTEGER_MATH_SQRT_STEP_FP64(); \
VARIANT2_INTEGER_MATH_SQRT_FIXUP(sqrt_result); \
} while (0)
#define VARIANT2_2() \
do if (variant >= 2) { \
((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x10)))[0] ^= hi; \
((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x10)))[1] ^= lo; \
hi ^= ((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x20)))[0]; \
lo ^= ((uint64_t*)(ctx->long_state + ((j * AES_BLOCK_SIZE) ^ 0x20)))[1]; \
} while (0)
#pragma pack(push, 1)
union cn_slow_hash_state {
union hash_state hs;
struct {
uint8_t k[64];
uint8_t init[INIT_SIZE_BYTE];
};
};
#pragma pack(pop)
static void do_turtle_lite_blake_hash(const void* input, size_t len, char* output) {
blake256_hash((uint8_t*)output, input, len);
}
void do_turtle_lite_groestl_hash(const void* input, size_t len, char* output) {
groestl(input, len * 8, (uint8_t*)output);
}
static void do_turtle_lite_jh_hash(const void* input, size_t len, char* output) {
int r = jh_hash(HASH_SIZE * 8, input, 8 * len, (uint8_t*)output);
assert(SUCCESS == r);
}
static void do_turtle_lite_skein_hash(const void* input, size_t len, char* output) {
int r = skein_hash(8 * HASH_SIZE, input, 8 * len, (uint8_t*)output);
assert(SKEIN_SUCCESS == r);
}
static void (* const extra_hashes[3])(const void *, size_t, char *) = {
do_turtle_lite_blake_hash, do_turtle_lite_groestl_hash, do_turtle_lite_skein_hash
};
extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
static inline size_t e2i(const uint8_t* a) {
return (*((uint64_t*) a) / AES_BLOCK_SIZE) & (CN_AES_INIT - 1);
}
static void mul(const uint8_t* a, const uint8_t* b, uint8_t* res) {
((uint64_t*) res)[1] = mul128(((uint64_t*) a)[0], ((uint64_t*) b)[0], (uint64_t*) res);
}
static void sum_half_blocks(uint8_t* a, const uint8_t* b) {
uint64_t a0, a1, b0, b1;
a0 = SWAP64LE(((uint64_t*) a)[0]);
a1 = SWAP64LE(((uint64_t*) a)[1]);
b0 = SWAP64LE(((uint64_t*) b)[0]);
b1 = SWAP64LE(((uint64_t*) b)[1]);
a0 += b0;
a1 += b1;
((uint64_t*) a)[0] = SWAP64LE(a0);
((uint64_t*) a)[1] = SWAP64LE(a1);
}
static inline void copy_block(uint8_t* dst, const uint8_t* src) {
((uint64_t*) dst)[0] = ((uint64_t*) src)[0];
((uint64_t*) dst)[1] = ((uint64_t*) src)[1];
}
static void swap_blocks(uint8_t* a, uint8_t* b) {
size_t i;
uint8_t t;
for (i = 0; i < AES_BLOCK_SIZE; i++) {
t = a[i];
a[i] = b[i];
b[i] = t;
}
}
static inline void xor_blocks(uint8_t* a, const uint8_t* b) {
((uint64_t*) a)[0] ^= ((uint64_t*) b)[0];
((uint64_t*) a)[1] ^= ((uint64_t*) b)[1];
}
static inline void xor_blocks_dst(const uint8_t* a, const uint8_t* b, uint8_t* dst) {
((uint64_t*) dst)[0] = ((uint64_t*) a)[0] ^ ((uint64_t*) b)[0];
((uint64_t*) dst)[1] = ((uint64_t*) a)[1] ^ ((uint64_t*) b)[1];
}
struct cryptonightturtlelite_ctx {
uint8_t long_state[MEMORY];
union cn_slow_hash_state state;
uint8_t text[INIT_SIZE_BYTE];
uint8_t a[AES_BLOCK_SIZE];
uint8_t b[AES_BLOCK_SIZE * 2];
uint8_t c[AES_BLOCK_SIZE];
uint8_t aes_key[AES_KEY_SIZE];
oaes_ctx* aes_ctx;
};
void cryptonightturtlelite_hash(const char* input, char* output, uint32_t len, int variant) {
#if defined(_MSC_VER)
struct cryptonightturtlelite_ctx *ctx = _malloca(sizeof(struct cryptonightturtlelite_ctx));
#else
struct cryptonightturtlelite_ctx *ctx = alloca(sizeof(struct cryptonightturtlelite_ctx));
#endif
hash_process(&ctx->state.hs, (const uint8_t*) input, len);
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
memcpy(ctx->aes_key, ctx->state.hs.b, AES_KEY_SIZE);
ctx->aes_ctx = (oaes_ctx*) oaes_alloc();
size_t i, j;
VARIANT1_INIT();
VARIANT2_INIT(ctx->b, ctx->state);
oaes_key_import_data(ctx->aes_ctx, ctx->aes_key, AES_KEY_SIZE);
for (i = 0; i < CN_INIT; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
aesb_pseudo_round(&ctx->text[AES_BLOCK_SIZE * j],
&ctx->text[AES_BLOCK_SIZE * j],
ctx->aes_ctx->key->exp_data);
}
memcpy(&ctx->long_state[i * INIT_SIZE_BYTE], ctx->text, INIT_SIZE_BYTE);
}
for (i = 0; i < 16; i++) {
ctx->a[i] = ctx->state.k[i] ^ ctx->state.k[32 + i];
ctx->b[i] = ctx->state.k[16 + i] ^ ctx->state.k[48 + i];
}
for (i = 0; i < ITER_DIV; i++) {
/* Dependency chain: address -> read value ------+
* written value <-+ hard function (AES or MUL) <+
* next address <-+
*/
/* Iteration 1 */
j = e2i(ctx->a);
aesb_single_round(&ctx->long_state[j * AES_BLOCK_SIZE], ctx->c, ctx->a);
VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b);
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j * AES_BLOCK_SIZE]);
VARIANT1_1((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
/* Iteration 2 */
j = e2i(ctx->c);
uint64_t* dst = (uint64_t*)&ctx->long_state[j * AES_BLOCK_SIZE];
uint64_t t[2];
t[0] = dst[0];
t[1] = dst[1];
VARIANT2_INTEGER_MATH(t, ctx->c);
uint64_t hi;
uint64_t lo = mul128(((uint64_t*)ctx->c)[0], t[0], &hi);
VARIANT2_2();
VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b);
((uint64_t*)ctx->a)[0] += hi;
((uint64_t*)ctx->a)[1] += lo;
dst[0] = ((uint64_t*)ctx->a)[0];
dst[1] = ((uint64_t*)ctx->a)[1];
((uint64_t*)ctx->a)[0] ^= t[0];
((uint64_t*)ctx->a)[1] ^= t[1];
VARIANT1_2((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
copy_block(ctx->b + AES_BLOCK_SIZE, ctx->b);
copy_block(ctx->b, ctx->c);
}
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
oaes_key_import_data(ctx->aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE);
for (i = 0; i < CN_INIT; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
xor_blocks(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
aesb_pseudo_round(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->text[j * AES_BLOCK_SIZE],
ctx->aes_ctx->key->exp_data);
}
}
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
hash_permutation(&ctx->state.hs);
/*memcpy(hash, &state, 32);*/
extra_hashes[ctx->state.hs.b[0] & 2](&ctx->state, 200, output);
oaes_free((OAES_CTX **) &ctx->aes_ctx);
}
void cryptonightturtlelite_fast_hash(const char* input, char* output, uint32_t len) {
union hash_state state;
hash_process(&state, (const uint8_t*) input, len);
memcpy(output, &state, HASH_SIZE);
}

View file

@ -1,17 +0,0 @@
#ifndef CRYPTONIGHTTURTLELITE_H
#define CRYPTONIGHTTURTLELITE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void cryptonightturtlelite_hash(const char* input, char* output, uint32_t len, int variant);
void cryptonightturtlelite_fast_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -194,37 +194,37 @@ void flex_hash(const char* input, char* output, cryptonight_ctx** ctx) {
cnAlgo = 14; // skip cn hashing for this loop iteration
}
//selection cnAlgo. if a CN algo is selected then core algo will not be selected
cn_hash_fun f = nullptr;
cn_hash_fun f;
switch(cnAlgo)
{
case CNDark:
cryptonightdark_hash((const char*)in, (char*)hash, size, 1);
//f = CnHash::fn(Algorithm::CN_GR_0, av, Assembly::AUTO);
//cryptonightdark_hash((const char*)in, (char*)hash, size, 1);
f = CnHash::fn(Algorithm::CN_GR_0, av, Assembly::AUTO);
break;
case CNDarklite:
cryptonightdarklite_hash((const char*)in, (char*)hash, size, 1);
//f = CnHash::fn(Algorithm::CN_GR_1, av, Assembly::AUTO);
//cryptonightdarklite_hash((const char*)in, (char*)hash, size, 1);
f = CnHash::fn(Algorithm::CN_GR_1, av, Assembly::AUTO);
break;
case CNFast:
cryptonightfast_hash((const char*)in, (char*)hash, size, 1);
//f = CnHash::fn(Algorithm::CN_GR_2, av, Assembly::AUTO);
//cryptonightfast_hash((const char*)in, (char*)hash, size, 1);
f = CnHash::fn(Algorithm::CN_GR_2, av, Assembly::AUTO);
break;
case CNLite:
cryptonightlite_hash((const char*)in, (char*)hash, size, 1);
//f = CnHash::fn(Algorithm::CN_GR_3, av, Assembly::AUTO);
//cryptonightlite_hash((const char*)in, (char*)hash, size, 1);
f = CnHash::fn(Algorithm::CN_GR_3, av, Assembly::AUTO);
break;
case CNTurtle:
cryptonightturtle_hash((const char*)in, (char*)hash, size, 1);
//f = CnHash::fn(Algorithm::CN_GR_4, av, Assembly::AUTO);
//cryptonightturtle_hash((const char*)in, (char*)hash, size, 1);
f = CnHash::fn(Algorithm::CN_GR_4, av, Assembly::AUTO);
break;
case CNTurtlelite:
cryptonightturtlelite_hash((const char*)in, (char*)hash, size, 1);
//f = CnHash::fn(Algorithm::CN_GR_5, av, Assembly::AUTO);
//cryptonightturtlelite_hash((const char*)in, (char*)hash, size, 1);
f = CnHash::fn(Algorithm::CN_GR_5, av, Assembly::AUTO);
break;
default:
f = nullptr;
}
if (f) f((const uint8_t*)in, size, (uint8_t*)hash, ctx, 0);
if (f) f((const uint8_t*)in, size, (uint8_t*)hash, ctx, 101);
//selection core algo
switch (algo) {

View file

@ -22,7 +22,7 @@
#define APP_ID "xmrig"
#define APP_NAME "XMRig"
#define APP_DESC "XMRig miner"
#define APP_VERSION "6.21.3-mo7"
#define APP_VERSION "6.21.3-mo8"
#define APP_DOMAIN "xmrig.com"
#define APP_SITE "www.xmrig.com"
#define APP_COPYRIGHT "Copyright (C) 2016-2024 xmrig.com"