New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RELEASE] Monero Cryptonight variants, and add one for v7 #3253

Merged
merged 3 commits into from Mar 6, 2018
Jump to file or symbol
Failed to load files and symbols.
+107 −17
Diff settings

Always

Just for now

Copy path View file
@@ -69,10 +69,10 @@ namespace crypto {
chacha20(data, length, key.data(), reinterpret_cast<const uint8_t*>(&iv), cipher);
}
inline void generate_chacha_key(const void *data, size_t size, chacha_key& key, bool prehashed=false) {
inline void generate_chacha_key(const void *data, size_t size, chacha_key& key, int cn_variant = 0, bool prehashed=false) {
static_assert(sizeof(chacha_key) <= sizeof(hash), "Size of hash must be at least that of chacha_key");
tools::scrubbed_arr<char, HASH_SIZE> pwd_hash;
crypto::cn_slow_hash_pre(data, size, pwd_hash.data(), prehashed);
crypto::cn_slow_hash_pre(data, size, pwd_hash.data(), cn_variant, prehashed);
memcpy(&key, pwd_hash.data(), sizeof(key));
}
Copy path View file
@@ -79,8 +79,8 @@ enum {
};
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 cn_slow_hash_pre(const void *data, size_t length, char *hash, bool pre);
void cn_slow_hash(const void *data, size_t length, char *hash, int variant);
void cn_slow_hash_pre(const void *data, size_t length, char *hash, int variant, bool pre);
void hash_extra_blake(const void *data, size_t length, char *hash);
void hash_extra_groestl(const void *data, size_t length, char *hash);
Copy path View file
@@ -71,8 +71,8 @@ namespace crypto {
return h;
}
inline void cn_slow_hash(const void *data, std::size_t length, hash &hash) {
cn_slow_hash(data, length, reinterpret_cast<char *>(&hash));
inline void cn_slow_hash(const void *data, std::size_t length, hash &hash, int variant = 0) {
cn_slow_hash(data, length, reinterpret_cast<char *>(&hash), variant);
}
inline void tree_hash(const hash *hashes, std::size_t count, hash &root_hash) {
Copy path View file
@@ -32,6 +32,8 @@
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "common/int-util.h"
#include "hash-ops.h"
@@ -47,6 +49,46 @@
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);
#define VARIANT1_1(p) \
do if (variant > 0) \
{ \
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 > 0) \
{ \
xor64(p, tweak1_2); \
} while(0)
#define VARIANT1_CHECK() \
do if (length < 43) \
{ \
fprintf(stderr, "Cryptonight variants need at least 43 bytes of data"); \
_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 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)))
// Optimised code below, uses x86-specific intrinsics, SSE2, AES-NI
// Fall back to more portable code is down at the bottom
@@ -125,6 +167,7 @@ extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *exp
_mm_store_si128(R128(c), _c); \
_b = _mm_xor_si128(_b, _c); \
_mm_store_si128(R128(&hp_state[j]), _b); \
VARIANT1_1(&hp_state[j]); \
j = state_index(c); \
p = U64(&hp_state[j]); \
b[0] = p[0]; b[1] = p[1]; \
@@ -133,6 +176,7 @@ extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *exp
p = U64(&hp_state[j]); \
p[0] = a[0]; p[1] = a[1]; \
a[0] ^= b[0]; a[1] ^= b[1]; \
VARIANT1_2(p + 1); \
_b = _c; \
#if defined(_MSC_VER)
@@ -183,6 +227,11 @@ STATIC INLINE void xor_blocks(uint8_t *a, const uint8_t *b)
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
* @return true if the CPU supports AES, false otherwise
@@ -515,11 +564,11 @@ void slow_hash_free_state(void)
* @param length the length in bytes of the data
* @param hash a pointer to a buffer in which the final 256 bit hash will be stored
*/
void cn_slow_hash(const void *data, size_t length, char *hash) {
cn_slow_hash_pre(data,length,hash,false);
void cn_slow_hash(const void *data, size_t length, char *hash, int variant) {
cn_slow_hash_pre(data,length,hash,variant,false);
}
void cn_slow_hash_pre(const void *data, size_t length, char *hash, bool prehashed)
void cn_slow_hash_pre(const void *data, size_t length, char *hash, int variant, bool prehashed)
{
RDATA_ALIGN16 uint8_t expandedKey[240]; /* These buffers are aligned to use later with SSE functions */
@@ -553,6 +602,8 @@ void cn_slow_hash_pre(const void *data, size_t length, char *hash, bool prehashe
}
memcpy(text, state.init, INIT_SIZE_BYTE);
VARIANT1_INIT64();
/* CryptoNight Step 2: Iteratively encrypt the results from Keccak to fill
* the 2MB large random access buffer.
*/
@@ -676,6 +727,11 @@ void slow_hash_free_state(void)
#define U64(x) ((uint64_t *) (x))
STATIC INLINE void xor64(uint64 *a, const uint64 b)
{
*a ^= b;
}
#pragma pack(push, 1)
union cn_slow_hash_state
{
@@ -712,6 +768,7 @@ union cn_slow_hash_state
vst1q_u8((uint8_t *)c, _c); \
_b = veorq_u8(_b, _c); \
vst1q_u8(&hp_state[j], _b); \
VARIANT1_1(&hp_state[j]); \
j = state_index(c); \
p = U64(&hp_state[j]); \
b[0] = p[0]; b[1] = p[1]; \
@@ -720,6 +777,7 @@ union cn_slow_hash_state
p = U64(&hp_state[j]); \
p[0] = a[0]; p[1] = a[1]; \
a[0] ^= b[0]; a[1] ^= b[1]; \
VARIANT1_2(p + 1); \
_b = _c; \
@@ -851,7 +909,7 @@ STATIC INLINE void aes_pseudo_round_xor(const uint8_t *in, uint8_t *out, const u
}
}
void cn_slow_hash(const void *data, size_t length, char *hash)
void cn_slow_hash(const void *data, size_t length, char *hash, int variant)
{
RDATA_ALIGN16 uint8_t expandedKey[240];
RDATA_ALIGN16 uint8_t hp_state[MEMORY];
@@ -877,6 +935,8 @@ void cn_slow_hash(const void *data, size_t length, char *hash)
hash_process(&state.hs, data, length);
memcpy(text, state.init, INIT_SIZE_BYTE);
VARIANT1_INIT64();
/* CryptoNight Step 2: Iteratively encrypt the results from Keccak to fill
* the 2MB large random access buffer.
*/
@@ -1045,7 +1105,7 @@ STATIC INLINE void xor_blocks(uint8_t* a, const uint8_t* b)
U64(a)[1] ^= U64(b)[1];
}
void cn_slow_hash(const void *data, size_t length, char *hash)
void cn_slow_hash(const void *data, size_t length, char *hash, int variant)
{
uint8_t text[INIT_SIZE_BYTE];
uint8_t a[AES_BLOCK_SIZE];
@@ -1074,6 +1134,8 @@ void cn_slow_hash(const void *data, size_t length, char *hash)
hash_process(&state.hs, data, length);
memcpy(text, state.init, INIT_SIZE_BYTE);
VARIANT1_INIT64();
aes_ctx = (oaes_ctx *) oaes_alloc();
oaes_key_import_data(aes_ctx, state.hs.b, AES_KEY_SIZE);
@@ -1103,6 +1165,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash)
xor_blocks(b, p);
swap_blocks(b, p);
swap_blocks(a, b);
VARIANT1_1(p);
// Iteration 2
p = &long_state[state_index(a)];
@@ -1112,6 +1175,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash)
swap_blocks(b, p);
xor_blocks(b, p);
swap_blocks(a, b);
VARIANT1_2(U64(p) + 1);
}
memcpy(text, state.init, INIT_SIZE_BYTE);
@@ -1206,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)
union cn_slow_hash_state {
union hash_state hs;
@@ -1216,7 +1289,7 @@ union cn_slow_hash_state {
};
#pragma pack(pop)
void cn_slow_hash(const void *data, size_t length, char *hash) {
void cn_slow_hash(const void *data, size_t length, char *hash, int variant) {
uint8_t long_state[MEMORY];
union cn_slow_hash_state state;
uint8_t text[INIT_SIZE_BYTE];
@@ -1233,6 +1306,8 @@ void cn_slow_hash(const void *data, size_t length, char *hash) {
memcpy(aes_key, state.hs.b, AES_KEY_SIZE);
aes_ctx = (oaes_ctx *) oaes_alloc();
VARIANT1_PORTABLE_INIT();
oaes_key_import_data(aes_ctx, aes_key, AES_KEY_SIZE);
for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
@@ -1260,13 +1335,15 @@ void cn_slow_hash(const void *data, size_t length, char *hash) {
copy_block(&long_state[j * AES_BLOCK_SIZE], c);
assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE));
swap_blocks(a, b);
VARIANT1_1(&long_state[j * AES_BLOCK_SIZE]);
/* Iteration 2 */
j = e2i(a, MEMORY / AES_BLOCK_SIZE);
copy_block(c, &long_state[j * AES_BLOCK_SIZE]);
mul(a, c, d);
sum_half_blocks(b, d);
swap_blocks(b, c);
xor_blocks(b, c);
VARIANT1_2(c + 8);
copy_block(&long_state[j * AES_BLOCK_SIZE], c);
assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE));
swap_blocks(a, b);
@@ -1022,7 +1022,8 @@ namespace cryptonote
return true;
}
blobdata bd = get_block_hashing_blob(b);
crypto::cn_slow_hash(bd.data(), bd.size(), res);
const int cn_variant = b.major_version >= 7 ? b.major_version - 6 : 0;
crypto::cn_slow_hash(bd.data(), bd.size(), res, cn_variant);
return true;
}
//---------------------------------------------------------------
Copy path View file
@@ -511,7 +511,7 @@ namespace hw {
char prekey[200];
memmove(prekey, &this->buffer_recv[0], 200);
crypto::generate_chacha_key(&prekey[0], sizeof(prekey), key, true);
crypto::generate_chacha_key(&prekey[0], sizeof(prekey), key, 0, true);
#ifdef DEBUG_HWDEVICE
hw::ledger::check32("generate_chacha_key", "key", (char*)key_x.data(), (char*)key.data());
Copy path View file
@@ -43,7 +43,7 @@ set_property(TARGET hash-tests
PROPERTY
FOLDER "tests")
foreach (hash IN ITEMS fast slow tree extra-blake extra-groestl extra-jh extra-skein)
foreach (hash IN ITEMS fast slow slow-1 tree extra-blake extra-groestl extra-jh extra-skein)
add_test(
NAME "hash-${hash}"
COMMAND hash-tests "${hash}" "${CMAKE_CURRENT_SOURCE_DIR}/tests-${hash}.txt")
Copy path View file
@@ -51,16 +51,23 @@ extern "C" {
}
tree_hash((const char (*)[32]) data, length >> 5, hash);
}
static void cn_slow_hash_0(const void *data, size_t length, char *hash) {
return cn_slow_hash(data, length, hash, 0);
}
static void cn_slow_hash_1(const void *data, size_t length, char *hash) {
return cn_slow_hash(data, length, hash, 1);
}
}
POP_WARNINGS
extern "C" typedef void hash_f(const void *, size_t, char *);
struct hash_func {
const string name;
hash_f &f;
} hashes[] = {{"fast", cn_fast_hash}, {"slow", cn_slow_hash}, {"tree", hash_tree},
} hashes[] = {{"fast", cn_fast_hash}, {"slow", cn_slow_hash_0}, {"tree", hash_tree},
{"extra-blake", hash_extra_blake}, {"extra-groestl", hash_extra_groestl},
{"extra-jh", hash_extra_jh}, {"extra-skein", hash_extra_skein}};
{"extra-jh", hash_extra_jh}, {"extra-skein", hash_extra_skein},
{"slow-1", cn_slow_hash_1}};
int main(int argc, char *argv[]) {
hash_f *f;
Copy path View file
@@ -0,0 +1,5 @@
b5a7f63abb94d07d1a6445c36c07c7e8327fe61b1647e391b4c7edae5de57a3d 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000
80563c40ed46575a9e44820d93ee095e2851aa22483fd67837118c6cd951ba61 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
5bb40c5880cef2f739bdb6aaaf16161eaae55530e7b10d7ea996b751a299e949 8519e039172b0d70e5ca7b3383d6b3167315a422747b73f019cf9528f0fde341fd0f2a63030ba6450525cf6de31837669af6f1df8131faf50aaab8d3a7405589
613e638505ba1fd05f428d5c9f8e08f8165614342dac419adc6a47dce257eb3e 37a636d7dafdf259b7287eddca2f58099e98619d2f99bdb8969d7b14498102cc065201c8be90bd777323f449848b215d2977c92c4c1c2da36ab46b2e389689ed97c18fec08cd3b03235c5e4c62a37ad88c7b67932495a71090e85dd4020a9300
ed082e49dbd5bbe34a3726a0d1dad981146062b39d36d62c71eb1ed8ab49459b 38274c97c45a172cfc97679870422e3a1ab0784960c60514d816271415c306ee3a3ed1a77e31f6a885c3cb
ProTip! Use n and p to navigate between commits in a pull request.