diff --git a/algo/cryptonight/cryptonight.h b/algo/cryptonight/cryptonight.h index a3c929805..6f1352787 100644 --- a/algo/cryptonight/cryptonight.h +++ b/algo/cryptonight/cryptonight.h @@ -26,6 +26,7 @@ #include #include +#include #define MEMORY 2097152 /* 2 MiB */ @@ -38,7 +39,7 @@ struct cryptonight_ctx { extern void (* const extra_hashes[4])(const void *, size_t, char *); -void cryptonight_init(int variant); +bool cryptonight_init(int variant); void cryptonight_hash(void* output, const void* input, size_t input_len); int scanhash_cryptonight(int thr_id, uint32_t *hash, uint32_t *restrict pdata, const uint32_t *restrict ptarget, uint32_t max_nonce, unsigned long *restrict hashes_done, struct cryptonight_ctx *restrict ctx); diff --git a/algo/cryptonight/cryptonight_common.c b/algo/cryptonight/cryptonight_common.c index 67876e8c9..b703b48ba 100644 --- a/algo/cryptonight/cryptonight_common.c +++ b/algo/cryptonight/cryptonight_common.c @@ -25,7 +25,7 @@ #include #ifndef BUILD_TEST -# include "xmrig.h" +# include "xmrig.h" #endif #include "crypto/c_groestl.h" @@ -34,6 +34,22 @@ #include "crypto/c_skein.h" #include "cryptonight.h" #include "options.h" +#include "utils/applog.h" + + +const static char test_input[76] = { + 0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00, + 0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B, + 0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62, + 0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92, + 0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01 +}; + + +const static char test_output[32] = { + 0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7, + 0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00 +}; void cryptonight_av1_aesni(void* output, const void* input, struct cryptonight_ctx* ctx); @@ -48,7 +64,22 @@ void cryptonight_av4_softaes(void* output, const void* input, struct cryptonight void (*cryptonight_hash_ctx)(void* output, const void* input, struct cryptonight_ctx* ctx) = NULL; -void cryptonight_init(int variant) +static bool self_test() { + char output[32]; + + struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) malloc(sizeof(struct cryptonight_ctx)); + ctx->memory = (uint8_t *) malloc(MEMORY); + + cryptonight_hash_ctx(output, test_input, ctx); + + free(ctx->memory); + free(ctx); + + return memcmp(output, test_output, 32) == 0; +} + + +bool cryptonight_init(int variant) { switch (variant) { case XMR_AV1_AESNI: @@ -77,6 +108,7 @@ void cryptonight_init(int variant) break; } + return self_test(); } diff --git a/options.c b/options.c index ed5aa857b..3e2c08bf4 100644 --- a/options.c +++ b/options.c @@ -393,7 +393,10 @@ void parse_cmdline(int argc, char *argv[]) { opt_donate_level = 1; } - cryptonight_init(opt_algo_variant); + if (!cryptonight_init(opt_algo_variant)) { + applog(LOG_ERR, "Cryptonight hash self-test failed. This might be caused by bad compiler optimizations."); + proper_exit(1); + } } diff --git a/test/cryptonight/cryptonight.c b/test/cryptonight/cryptonight.c index 49c99db62..2ebb7eadc 100644 --- a/test/cryptonight/cryptonight.c +++ b/test/cryptonight/cryptonight.c @@ -3,6 +3,13 @@ #include #include +const static char input[76] = { + 0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00, 0x7C, 0xBF, 0x34, + 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B, 0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, + 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62, 0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, + 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92, 0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01 +}; + void cryptonight_av1_aesni(void* output, const void* input, struct cryptonight_ctx* ctx); void cryptonight_av2_aesni_stak(void* output, const void* input, struct cryptonight_ctx* ctx); @@ -11,9 +18,7 @@ void cryptonight_av4_softaes(void* output, const void* input, struct cryptonight void cryptonight_av5_aesni_experimental(void* output, const void* input, struct cryptonight_ctx* ctx); -char hash[32]; -char data[76]; - +static char hash[32]; #define RESULT "1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100" @@ -31,31 +36,6 @@ static char *bin2hex(const unsigned char *p, size_t len) return s; } -static bool hex2bin(unsigned char *p, const char *hexstr, size_t len) -{ - char hex_byte[3]; - char *ep; - - hex_byte[2] = '\0'; - - while (*hexstr && len) { - if (!hexstr[1]) { - return false; - } - hex_byte[0] = hexstr[0]; - hex_byte[1] = hexstr[1]; - *p = (unsigned char) strtol(hex_byte, &ep, 16); - if (*ep) { - return false; - } - p++; - hexstr += 2; - len--; - } - - return (len == 0 && *hexstr == 0) ? true : false; -} - static void * create_ctx() { struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) malloc(sizeof(struct cryptonight_ctx)); @@ -74,7 +54,7 @@ static void free_ctx(struct cryptonight_ctx *ctx) { void test_cryptonight_av1_should_CalcHash(void) { struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) create_ctx(); - cryptonight_av1_aesni(&hash, data, ctx); + cryptonight_av1_aesni(&hash, input, ctx); free_ctx(ctx); @@ -86,7 +66,7 @@ void test_cryptonight_av2_should_CalcHash(void) { struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) create_ctx(); - cryptonight_av2_aesni_stak(&hash, data, ctx); + cryptonight_av2_aesni_stak(&hash, input, ctx); free_ctx(ctx); @@ -98,7 +78,7 @@ void test_cryptonight_av3_should_CalcHash(void) { struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) create_ctx(); - cryptonight_av3_aesni_bmi2(&hash, data, ctx); + cryptonight_av3_aesni_bmi2(&hash, input, ctx); free_ctx(ctx); @@ -110,7 +90,7 @@ void test_cryptonight_av4_should_CalcHash(void) { struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) create_ctx(); - cryptonight_av4_softaes(&hash, data, ctx); + cryptonight_av4_softaes(&hash, input, ctx); free_ctx(ctx); @@ -122,7 +102,7 @@ void test_cryptonight_av5_should_CalcHash(void) { struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) create_ctx(); - cryptonight_av5_aesni_experimental(&hash, data, ctx); + cryptonight_av5_aesni_experimental(&hash, input, ctx); free_ctx(ctx); @@ -132,8 +112,6 @@ void test_cryptonight_av5_should_CalcHash(void) int main(void) { - hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); - UNITY_BEGIN(); RUN_TEST(test_cryptonight_av1_should_CalcHash); diff --git a/xmrig.c b/xmrig.c index 17255ceb8..22334bde8 100644 --- a/xmrig.c +++ b/xmrig.c @@ -289,7 +289,7 @@ static void *miner_thread(void *userdata) { } uint32_t *nonceptr = (uint32_t*) (((char*)work.data) + 39); - uint32_t hash[32 / 4] __attribute__((aligned(32))); + uint32_t hash[8] __attribute__((aligned(32))); while (1) { unsigned long hashes_done;