-
Notifications
You must be signed in to change notification settings - Fork 552
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
325 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,257 @@ | ||
// Minotaur hash | ||
|
||
#include "algo-gate-api.h" | ||
#include <stdlib.h> | ||
#include <stdint.h> | ||
#include <string.h> | ||
#include <stdio.h> | ||
#include "algo/blake/sph_blake.h" | ||
#include "algo/bmw/sph_bmw.h" | ||
#include "algo/groestl/sph_groestl.h" | ||
#include "algo/jh/sph_jh.h" | ||
#include "algo/keccak/sph_keccak.h" | ||
#include "algo/skein/sph_skein.h" | ||
#include "algo/shavite/sph_shavite.h" | ||
#include "algo/luffa/luffa_for_sse2.h" | ||
#include "algo/cubehash/cubehash_sse2.h" | ||
#include "algo/simd/nist.h" | ||
#include "algo/echo/sph_echo.h" | ||
#include "algo/hamsi/sph_hamsi.h" | ||
#include "algo/fugue/sph_fugue.h" | ||
#include "algo/shabal/sph_shabal.h" | ||
#include "algo/whirlpool/sph_whirlpool.h" | ||
#include <openssl/sha.h> | ||
#if defined(__AES__) | ||
#include "algo/echo/aes_ni/hash_api.h" | ||
#include "algo/groestl/aes_ni/hash-groestl.h" | ||
#endif | ||
|
||
|
||
// Config | ||
#define MINOTAUR_ALGO_COUNT 16 | ||
|
||
typedef struct TortureNode TortureNode; | ||
typedef struct TortureGarden TortureGarden; | ||
|
||
// Graph of hash algos plus SPH contexts | ||
struct TortureGarden { | ||
#if defined(__AES__) | ||
hashState_echo echo; | ||
hashState_groestl groestl; | ||
#else | ||
sph_groestl512_context groestl; | ||
sph_echo512_context echo; | ||
#endif | ||
sph_blake512_context blake; | ||
sph_bmw512_context bmw; | ||
sph_skein512_context skein; | ||
sph_jh512_context jh; | ||
sph_keccak512_context keccak; | ||
hashState_luffa luffa; | ||
cubehashParam cube; | ||
shavite512_context shavite; | ||
hashState_sd simd; | ||
sph_hamsi512_context hamsi; | ||
sph_fugue512_context fugue; | ||
sph_shabal512_context shabal; | ||
sph_whirlpool_context whirlpool; | ||
SHA512_CTX sha512; | ||
|
||
struct TortureNode { | ||
unsigned int algo; | ||
TortureNode *childLeft; | ||
TortureNode *childRight; | ||
} nodes[22]; | ||
}; | ||
|
||
// Get a 64-byte hash for given 64-byte input, using given TortureGarden contexts and given algo index | ||
static void get_hash( void *output, const void *input, TortureGarden *garden, | ||
unsigned int algo ) | ||
{ | ||
unsigned char _ALIGN(64) hash[64]; | ||
|
||
switch (algo) { | ||
case 0: | ||
sph_blake512_init(&garden->blake); | ||
sph_blake512(&garden->blake, input, 64); | ||
sph_blake512_close(&garden->blake, hash); | ||
break; | ||
case 1: | ||
sph_bmw512_init(&garden->bmw); | ||
sph_bmw512(&garden->bmw, input, 64); | ||
sph_bmw512_close(&garden->bmw, hash); | ||
break; | ||
case 2: | ||
cubehashInit( &garden->cube, 512, 16, 32 ); | ||
cubehashUpdateDigest( &garden->cube, (byte*)hash, | ||
(const byte*)input, 64 ); | ||
break; | ||
case 3: | ||
#if defined(__AES__) | ||
echo_full( &garden->echo, (BitSequence *)hash, 512, | ||
(const BitSequence *)input, 64 ); | ||
#else | ||
sph_echo512_init(&garden->echo); | ||
sph_echo512(&garden->echo, input, 64); | ||
sph_echo512_close(&garden->echo, hash); | ||
#endif | ||
break; | ||
case 4: | ||
sph_fugue512_init(&garden->fugue); | ||
sph_fugue512(&garden->fugue, input, 64); | ||
sph_fugue512_close(&garden->fugue, hash); | ||
break; | ||
case 5: | ||
#if defined(__AES__) | ||
groestl512_full( &garden->groestl, (char*)hash, (char*)input, 512 ); | ||
#else | ||
sph_groestl512_init(&garden->groestl); | ||
sph_groestl512(&garden->groestl, input, 64); | ||
sph_groestl512_close(&garden->groestl, hash); | ||
#endif | ||
break; | ||
case 6: | ||
sph_hamsi512_init(&garden->hamsi); | ||
sph_hamsi512(&garden->hamsi, input, 64); | ||
sph_hamsi512_close(&garden->hamsi, hash); | ||
break; | ||
case 7: | ||
SHA512_Init( &garden->sha512 ); | ||
SHA512_Update( &garden->sha512, input, 64 ); | ||
SHA512_Final( (unsigned char*)hash, &garden->sha512 ); | ||
break; | ||
case 8: | ||
sph_jh512_init(&garden->jh); | ||
sph_jh512(&garden->jh, input, 64); | ||
sph_jh512_close(&garden->jh, hash); | ||
break; | ||
case 9: | ||
sph_keccak512_init(&garden->keccak); | ||
sph_keccak512(&garden->keccak, input, 64); | ||
sph_keccak512_close(&garden->keccak, hash); | ||
break; | ||
case 10: | ||
init_luffa( &garden->luffa, 512 ); | ||
update_and_final_luffa( &garden->luffa, (BitSequence*)hash, | ||
(const BitSequence*)input, 64 ); | ||
break; | ||
case 11: | ||
sph_shabal512_init(&garden->shabal); | ||
sph_shabal512(&garden->shabal, input, 64); | ||
sph_shabal512_close(&garden->shabal, hash); | ||
break; | ||
case 12: | ||
sph_shavite512_init(&garden->shavite); | ||
sph_shavite512(&garden->shavite, input, 64); | ||
sph_shavite512_close(&garden->shavite, hash); | ||
break; | ||
case 13: | ||
init_sd( &garden->simd, 512 ); | ||
update_final_sd( &garden->simd, (BitSequence *)hash, | ||
(const BitSequence*)input, 512 ); | ||
break; | ||
case 14: | ||
sph_skein512_init(&garden->skein); | ||
sph_skein512(&garden->skein, input, 64); | ||
sph_skein512_close(&garden->skein, hash); | ||
break; | ||
case 15: | ||
sph_whirlpool_init(&garden->whirlpool); | ||
sph_whirlpool(&garden->whirlpool, input, 64); | ||
sph_whirlpool_close(&garden->whirlpool, hash); | ||
break; | ||
} | ||
|
||
// Output the hash | ||
memcpy(output, hash, 64); | ||
} | ||
|
||
// Recursively traverse a given torture garden starting with a given hash and given node within the garden. The hash is overwritten with the final hash. | ||
static void traverse_garden( TortureGarden *garden, void *hash, | ||
TortureNode *node ) | ||
{ | ||
unsigned char _ALIGN(64) partialHash[64]; | ||
get_hash(partialHash, hash, garden, node->algo); | ||
|
||
if ( partialHash[63] % 2 == 0 ) | ||
{ // Last byte of output hash is even | ||
if ( node->childLeft != NULL ) | ||
traverse_garden( garden, partialHash, node->childLeft ); | ||
} | ||
else | ||
{ // Last byte of output hash is odd | ||
if ( node->childRight != NULL ) | ||
traverse_garden( garden, partialHash, node->childRight ); | ||
} | ||
|
||
memcpy( hash, partialHash, 64 ); | ||
} | ||
|
||
// Associate child nodes with a parent node | ||
static inline void link_nodes( TortureNode *parent, TortureNode *childLeft, | ||
TortureNode *childRight ) | ||
{ | ||
parent->childLeft = childLeft; | ||
parent->childRight = childRight; | ||
} | ||
|
||
static TortureGarden garden; | ||
|
||
void initialize_torture_garden() | ||
{ | ||
// Create torture garden nodes. Note that both sides of 19 and 20 lead to 21, and 21 has no children (to make traversal complete). | ||
link_nodes(&garden.nodes[0], &garden.nodes[1], &garden.nodes[2]); | ||
link_nodes(&garden.nodes[1], &garden.nodes[3], &garden.nodes[4]); | ||
link_nodes(&garden.nodes[2], &garden.nodes[5], &garden.nodes[6]); | ||
link_nodes(&garden.nodes[3], &garden.nodes[7], &garden.nodes[8]); | ||
link_nodes(&garden.nodes[4], &garden.nodes[9], &garden.nodes[10]); | ||
link_nodes(&garden.nodes[5], &garden.nodes[11], &garden.nodes[12]); | ||
link_nodes(&garden.nodes[6], &garden.nodes[13], &garden.nodes[14]); | ||
link_nodes(&garden.nodes[7], &garden.nodes[15], &garden.nodes[16]); | ||
link_nodes(&garden.nodes[8], &garden.nodes[15], &garden.nodes[16]); | ||
link_nodes(&garden.nodes[9], &garden.nodes[15], &garden.nodes[16]); | ||
link_nodes(&garden.nodes[10], &garden.nodes[15], &garden.nodes[16]); | ||
link_nodes(&garden.nodes[11], &garden.nodes[17], &garden.nodes[18]); | ||
link_nodes(&garden.nodes[12], &garden.nodes[17], &garden.nodes[18]); | ||
link_nodes(&garden.nodes[13], &garden.nodes[17], &garden.nodes[18]); | ||
link_nodes(&garden.nodes[14], &garden.nodes[17], &garden.nodes[18]); | ||
link_nodes(&garden.nodes[15], &garden.nodes[19], &garden.nodes[20]); | ||
link_nodes(&garden.nodes[16], &garden.nodes[19], &garden.nodes[20]); | ||
link_nodes(&garden.nodes[17], &garden.nodes[19], &garden.nodes[20]); | ||
link_nodes(&garden.nodes[18], &garden.nodes[19], &garden.nodes[20]); | ||
link_nodes(&garden.nodes[19], &garden.nodes[21], &garden.nodes[21]); | ||
link_nodes(&garden.nodes[20], &garden.nodes[21], &garden.nodes[21]); | ||
garden.nodes[21].childLeft = NULL; | ||
garden.nodes[21].childRight = NULL; | ||
} | ||
|
||
// Produce a 32-byte hash from 80-byte input data | ||
int minotaur_hash( void *output, const void *input ) | ||
{ | ||
unsigned char _ALIGN(64) hash[64]; | ||
|
||
// Find initial sha512 hash | ||
SHA512_Init( &garden.sha512 ); | ||
SHA512_Update( &garden.sha512, input, 80 ); | ||
SHA512_Final( (unsigned char*) hash, &garden.sha512 ); | ||
|
||
// Assign algos to torture garden nodes based on initial hash | ||
for ( int i = 0; i < 22; i++ ) | ||
garden.nodes[i].algo = hash[i] % MINOTAUR_ALGO_COUNT; | ||
|
||
// Send the initial hash through the torture garden | ||
traverse_garden( &garden, hash, &garden.nodes[0] ); | ||
|
||
memcpy( output, hash, 32 ); | ||
|
||
return 1; | ||
} | ||
|
||
bool register_minotaur_algo( algo_gate_t* gate ) | ||
{ | ||
gate->hash = (void*)&minotaur_hash; | ||
gate->optimizations = SSE2_OPT | AES_OPT | AVX2_OPT | AVX512_OPT; | ||
initialize_torture_garden(); | ||
return true; | ||
}; | ||
|
Oops, something went wrong.