tweaks to the monerov1 cryptonight algorithm

This commit is contained in:
Lee Clagett 2018-02-27 18:45:32 -05:00 committed by moneromooo-monero
parent d58c9ec99c
commit e136bc6b8a
No known key found for this signature in database
GPG Key ID: 686F07454D6CEFC3
2 changed files with 57 additions and 21 deletions

View File

@ -61,16 +61,33 @@ extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *exp
#define VARIANT1_2(p) \ #define VARIANT1_2(p) \
do if (variant > 0) \ do if (variant > 0) \
{ \ { \
((uint32_t*)p)[2] ^= nonce; \ xor64(p, tweak1_2); \
} while(0) } while(0)
#define VARIANT1_INIT() \ #define VARIANT1_CHECK() \
if (variant > 0 && length < 43) \ do if (length < 43) \
{ \ { \
fprintf(stderr, "Cryptonight variants need at least 43 bytes of data"); \ fprintf(stderr, "Cryptonight variants need at least 43 bytes of data"); \
_exit(1); \ _exit(1); \
} while(0)
#define NONCE_POINTER (((const uint8_t*)data)+35)
#define VARIANT1_PORTABLE_INIT() \
uint8_t tweak1_2[8]; \
do if (variant > 0) \
{ \
VARIANT1_CHECK(); \
memcpy(&tweak1_2, &state.hs.b[192], sizeof(tweak1_2)); \
xor64(tweak1_2, NONCE_POINTER); \
} while(0)
#define VARIANT1_INIT64() \
if (variant > 0) \
{ \
VARIANT1_CHECK(); \
} \ } \
const uint32_t nonce = variant > 0 ? *(const uint32_t*)(((const uint8_t*)data)+39) : 0 const uint64_t tweak1_2 = variant > 0 ? (state.hs.w[24] ^ (*((const uint64_t*)NONCE_POINTER))) : 0
#if !defined NO_AES && (defined(__x86_64__) || (defined(_MSC_VER) && defined(_WIN64))) #if !defined NO_AES && (defined(__x86_64__) || (defined(_MSC_VER) && defined(_WIN64)))
// Optimised code below, uses x86-specific intrinsics, SSE2, AES-NI // Optimised code below, uses x86-specific intrinsics, SSE2, AES-NI
@ -159,8 +176,8 @@ extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *exp
p = U64(&hp_state[j]); \ p = U64(&hp_state[j]); \
p[0] = a[0]; p[1] = a[1]; \ p[0] = a[0]; p[1] = a[1]; \
a[0] ^= b[0]; a[1] ^= b[1]; \ a[0] ^= b[0]; a[1] ^= b[1]; \
VARIANT1_2(p + 1); \
_b = _c; \ _b = _c; \
VARIANT1_2(&hp_state[j]); \
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define THREADV __declspec(thread) #define THREADV __declspec(thread)
@ -210,6 +227,11 @@ STATIC INLINE void xor_blocks(uint8_t *a, const uint8_t *b)
U64(a)[1] ^= U64(b)[1]; U64(a)[1] ^= U64(b)[1];
} }
STATIC INLINE void xor64(uint64_t *a, const uint64_t b)
{
*a ^= b;
}
/** /**
* @brief uses cpuid to determine if the CPU supports the AES instructions * @brief uses cpuid to determine if the CPU supports the AES instructions
* @return true if the CPU supports AES, false otherwise * @return true if the CPU supports AES, false otherwise
@ -568,8 +590,6 @@ void cn_slow_hash_pre(const void *data, size_t length, char *hash, int variant,
hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein
}; };
VARIANT1_INIT();
// this isn't supposed to happen, but guard against it for now. // this isn't supposed to happen, but guard against it for now.
if(hp_state == NULL) if(hp_state == NULL)
slow_hash_allocate_state(); slow_hash_allocate_state();
@ -582,6 +602,8 @@ void cn_slow_hash_pre(const void *data, size_t length, char *hash, int variant,
} }
memcpy(text, state.init, INIT_SIZE_BYTE); memcpy(text, state.init, INIT_SIZE_BYTE);
VARIANT1_INIT64();
/* CryptoNight Step 2: Iteratively encrypt the results from Keccak to fill /* CryptoNight Step 2: Iteratively encrypt the results from Keccak to fill
* the 2MB large random access buffer. * the 2MB large random access buffer.
*/ */
@ -705,6 +727,11 @@ void slow_hash_free_state(void)
#define U64(x) ((uint64_t *) (x)) #define U64(x) ((uint64_t *) (x))
STATIC INLINE void xor64(uint64 *a, const uint64 b)
{
*a ^= b;
}
#pragma pack(push, 1) #pragma pack(push, 1)
union cn_slow_hash_state union cn_slow_hash_state
{ {
@ -750,7 +777,7 @@ union cn_slow_hash_state
p = U64(&hp_state[j]); \ p = U64(&hp_state[j]); \
p[0] = a[0]; p[1] = a[1]; \ p[0] = a[0]; p[1] = a[1]; \
a[0] ^= b[0]; a[1] ^= b[1]; \ a[0] ^= b[0]; a[1] ^= b[1]; \
VARIANT1_2(p); \ VARIANT1_2(p + 1); \
_b = _c; \ _b = _c; \
@ -903,13 +930,13 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant)
hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein
}; };
VARIANT1_INIT();
/* CryptoNight Step 1: Use Keccak1600 to initialize the 'state' (and 'text') buffers from the data. */ /* CryptoNight Step 1: Use Keccak1600 to initialize the 'state' (and 'text') buffers from the data. */
hash_process(&state.hs, data, length); hash_process(&state.hs, data, length);
memcpy(text, state.init, INIT_SIZE_BYTE); memcpy(text, state.init, INIT_SIZE_BYTE);
VARIANT1_INIT64();
/* CryptoNight Step 2: Iteratively encrypt the results from Keccak to fill /* CryptoNight Step 2: Iteratively encrypt the results from Keccak to fill
* the 2MB large random access buffer. * the 2MB large random access buffer.
*/ */
@ -1097,8 +1124,6 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant)
hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein
}; };
VARIANT1_INIT();
#ifndef FORCE_USE_HEAP #ifndef FORCE_USE_HEAP
uint8_t long_state[MEMORY]; uint8_t long_state[MEMORY];
#else #else
@ -1109,6 +1134,8 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant)
hash_process(&state.hs, data, length); hash_process(&state.hs, data, length);
memcpy(text, state.init, INIT_SIZE_BYTE); memcpy(text, state.init, INIT_SIZE_BYTE);
VARIANT1_INIT64();
aes_ctx = (oaes_ctx *) oaes_alloc(); aes_ctx = (oaes_ctx *) oaes_alloc();
oaes_key_import_data(aes_ctx, state.hs.b, AES_KEY_SIZE); oaes_key_import_data(aes_ctx, state.hs.b, AES_KEY_SIZE);
@ -1148,7 +1175,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant)
swap_blocks(b, p); swap_blocks(b, p);
xor_blocks(b, p); xor_blocks(b, p);
swap_blocks(a, b); swap_blocks(a, b);
VARIANT1_2(p); VARIANT1_2(U64(p) + 1);
} }
memcpy(text, state.init, INIT_SIZE_BYTE); memcpy(text, state.init, INIT_SIZE_BYTE);
@ -1243,6 +1270,15 @@ static void xor_blocks(uint8_t* a, const uint8_t* b) {
} }
} }
static void xor64(uint8_t* left, const uint8_t* right)
{
size_t i;
for (i = 0; i < 8; ++i)
{
left[i] ^= right[i];
}
}
#pragma pack(push, 1) #pragma pack(push, 1)
union cn_slow_hash_state { union cn_slow_hash_state {
union hash_state hs; union hash_state hs;
@ -1265,13 +1301,13 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant) {
uint8_t aes_key[AES_KEY_SIZE]; uint8_t aes_key[AES_KEY_SIZE];
oaes_ctx *aes_ctx; oaes_ctx *aes_ctx;
VARIANT1_INIT();
hash_process(&state.hs, data, length); hash_process(&state.hs, data, length);
memcpy(text, state.init, INIT_SIZE_BYTE); memcpy(text, state.init, INIT_SIZE_BYTE);
memcpy(aes_key, state.hs.b, AES_KEY_SIZE); memcpy(aes_key, state.hs.b, AES_KEY_SIZE);
aes_ctx = (oaes_ctx *) oaes_alloc(); aes_ctx = (oaes_ctx *) oaes_alloc();
VARIANT1_PORTABLE_INIT();
oaes_key_import_data(aes_ctx, aes_key, AES_KEY_SIZE); oaes_key_import_data(aes_ctx, aes_key, AES_KEY_SIZE);
for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) { for (j = 0; j < INIT_SIZE_BLK; j++) {
@ -1307,10 +1343,10 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant) {
sum_half_blocks(b, d); sum_half_blocks(b, d);
swap_blocks(b, c); swap_blocks(b, c);
xor_blocks(b, c); xor_blocks(b, c);
VARIANT1_2(c + 8);
copy_block(&long_state[j * AES_BLOCK_SIZE], c); copy_block(&long_state[j * AES_BLOCK_SIZE], c);
assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE)); assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE));
swap_blocks(a, b); swap_blocks(a, b);
VARIANT1_2(&long_state[j * AES_BLOCK_SIZE]);
} }
memcpy(text, state.init, INIT_SIZE_BYTE); memcpy(text, state.init, INIT_SIZE_BYTE);

View File

@ -1,5 +1,5 @@
b46aab7facce3eb4b4679d1d526f2d500d43736988b7881853c4c0c4af04ac0e 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000 b5a7f63abb94d07d1a6445c36c07c7e8327fe61b1647e391b4c7edae5de57a3d 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000
f0f0ab8a50a809ccd82c76996e494b20a1e01e90ed4814a27db2558511559091 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 80563c40ed46575a9e44820d93ee095e2851aa22483fd67837118c6cd951ba61 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
13310922971e1112b382357aeaa8b0bf0cd941dc6f5e398979f3fa77d13749bd 8519e039172b0d70e5ca7b3383d6b3167315a422747b73f019cf9528f0fde341fd0f2a63030ba6450525cf6de31837669af6f1df8131faf50aaab8d3a7405589 5bb40c5880cef2f739bdb6aaaf16161eaae55530e7b10d7ea996b751a299e949 8519e039172b0d70e5ca7b3383d6b3167315a422747b73f019cf9528f0fde341fd0f2a63030ba6450525cf6de31837669af6f1df8131faf50aaab8d3a7405589
0d9f641d14a782748ed5548f72a20c83c4a2cfe606015ad9eda5b36a00947d72 37a636d7dafdf259b7287eddca2f58099e98619d2f99bdb8969d7b14498102cc065201c8be90bd777323f449848b215d2977c92c4c1c2da36ab46b2e389689ed97c18fec08cd3b03235c5e4c62a37ad88c7b67932495a71090e85dd4020a9300 613e638505ba1fd05f428d5c9f8e08f8165614342dac419adc6a47dce257eb3e 37a636d7dafdf259b7287eddca2f58099e98619d2f99bdb8969d7b14498102cc065201c8be90bd777323f449848b215d2977c92c4c1c2da36ab46b2e389689ed97c18fec08cd3b03235c5e4c62a37ad88c7b67932495a71090e85dd4020a9300
d74a0c9b603aa9f9af0bfec0c36d3d383c14930a0ee2f08dab44536fccda5bee 38274c97c45a172cfc97679870422e3a1ab0784960c60514d816271415c306ee3a3ed1a77e31f6a885c3cb ed082e49dbd5bbe34a3726a0d1dad981146062b39d36d62c71eb1ed8ab49459b 38274c97c45a172cfc97679870422e3a1ab0784960c60514d816271415c306ee3a3ed1a77e31f6a885c3cb