diff --git a/CMakeLists.txt b/CMakeLists.txt index 14dcc931..e813b2fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,7 @@ set(HEADERS_CRYPTO src/crypto/skein_port.h src/crypto/soft_aes.h src/crypto/asm/CryptonightR_template.h + src/crypto/k12.h ) if (XMRIG_ARM) @@ -156,6 +157,9 @@ set(SOURCES_CRYPTO src/crypto/c_blake256.c src/crypto/c_jh.c src/crypto/c_skein.c + src/crypto/k12/KangarooTwelve.c + src/crypto/k12/KeccakP-1600-reference.c + src/crypto/k12/KeccakSpongeWidth1600.c ) if (WIN32) diff --git a/src/common/crypto/Algorithm.cpp b/src/common/crypto/Algorithm.cpp index f14d034d..77668655 100644 --- a/src/common/crypto/Algorithm.cpp +++ b/src/common/crypto/Algorithm.cpp @@ -75,6 +75,7 @@ static AlgoData const algorithms[] = { { "cryptonight-light", "cn-light", xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_AUTO }, { "cryptonight-lite/0", "cn-lite/0", xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_0 }, { "cryptonight-lite/1", "cn-lite/1", xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_1 }, + { "kangarootwelve", "k12", xmrig::KANGAROOTWELVE, xmrig::VARIANT_0 }, # endif # ifndef XMRIG_NO_SUMO @@ -117,6 +118,7 @@ static AlgoData const xmrStakAlgorithms[] = { { "cryptonight_turtle", nullptr, xmrig::CRYPTONIGHT_PICO, xmrig::VARIANT_TRTL }, { "cryptonight_gpu", nullptr, xmrig::CRYPTONIGHT, xmrig::VARIANT_GPU }, { "cryptonight_r", nullptr, xmrig::CRYPTONIGHT, xmrig::VARIANT_4 }, + { "kangarootwelve", nullptr, xmrig::KANGAROOTWELVE, xmrig::VARIANT_0 }, }; #endif diff --git a/src/common/net/Job.cpp b/src/common/net/Job.cpp index 851507ad..55bdcd53 100644 --- a/src/common/net/Job.cpp +++ b/src/common/net/Job.cpp @@ -256,6 +256,7 @@ xmrig::Variant xmrig::Job::variant() const return VARIANT_1; case CRYPTONIGHT_HEAVY: + case KANGAROOTWELVE: return VARIANT_0; default: diff --git a/src/common/xmrig.h b/src/common/xmrig.h index e8ca8857..e4aa97df 100644 --- a/src/common/xmrig.h +++ b/src/common/xmrig.h @@ -36,6 +36,7 @@ enum Algo { CRYPTONIGHT_LITE, /* CryptoNight (1 MB) */ CRYPTONIGHT_HEAVY, /* CryptoNight (4 MB) */ CRYPTONIGHT_PICO, /* CryptoNight (256 KB) */ + KANGAROOTWELVE, /* KangarooTwelve */ ALGO_MAX }; diff --git a/src/core/Config.cpp b/src/core/Config.cpp index 82a96117..f93ace22 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -162,7 +162,7 @@ bool xmrig::Config::finalize() const AlgoVariant av = getAlgoVariant(); m_threads.mode = m_threads.count ? Simple : Automatic; - const size_t size = CpuThread::multiway(av) * cn_select_memory(m_algorithm.algo()) / 1024; + const size_t size = std::max(1, CpuThread::multiway(av) * cn_select_memory(m_algorithm.algo()) / 1024); if (!m_threads.count) { m_threads.count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage); diff --git a/src/core/usage.h b/src/core/usage.h index 0d5c4781..3c4295c9 100644 --- a/src/core/usage.h +++ b/src/core/usage.h @@ -39,7 +39,8 @@ Options:\n\ cryptonight\n" #ifndef XMRIG_NO_AEON "\ - cryptonight-lite\n" + cryptonight-lite\n\ + kangarootwelve\n" #endif #ifndef XMRIG_NO_SUMO "\ diff --git a/src/crypto/CryptoNight_test.h b/src/crypto/CryptoNight_test.h index 6fa9dd28..66c60d8d 100644 --- a/src/crypto/CryptoNight_test.h +++ b/src/crypto/CryptoNight_test.h @@ -301,6 +301,13 @@ const static uint8_t test_output_v1_lite[160] = { 0x8C, 0x2B, 0xA4, 0x1F, 0x60, 0x76, 0x39, 0xD7, 0xF6, 0x46, 0x77, 0x18, 0x20, 0xAD, 0xD4, 0xC9, 0x87, 0xF7, 0x37, 0xDA, 0xFD, 0xBA, 0xBA, 0xD2, 0xF2, 0x68, 0xDC, 0x26, 0x8D, 0x1B, 0x08, 0xC6 }; + + +// "k12" AEON v8 +const static uint8_t test_output_k12[32] = { + 0xaf, 0x1b, 0x9d, 0xf7, 0x2e, 0xa0, 0xc4, 0xb5, 0xfd, 0xbf, 0x22, 0xad, 0x61, 0x82, 0x5a, 0xd8, + 0xc9, 0x84, 0x6d, 0x9d, 0x98, 0xef, 0xc3, 0x19, 0xfa, 0x71, 0x52, 0xcd, 0x30, 0xed, 0x98, 0x32, +}; #endif diff --git a/src/crypto/k12.h b/src/crypto/k12.h new file mode 100644 index 00000000..bec4cb91 --- /dev/null +++ b/src/crypto/k12.h @@ -0,0 +1,9 @@ +extern "C" +{ +#include "k12/KangarooTwelve.h" +} + +inline void k12(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx **ctx, uint64_t height) +{ + KangarooTwelve((const unsigned char *)input, size, (unsigned char *)output, 32, 0, 0); +} diff --git a/src/crypto/k12/KangarooTwelve.c b/src/crypto/k12/KangarooTwelve.c new file mode 100644 index 00000000..5f8b879f --- /dev/null +++ b/src/crypto/k12/KangarooTwelve.c @@ -0,0 +1,271 @@ +/* +Implementation by Ronny Van Keer, hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#include +#include "KangarooTwelve.h" +#ifndef KeccakP1600timesN_excluded + // #include "KeccakP-1600-times2-SnP.h" + // #include "KeccakP-1600-times4-SnP.h" + // #include "KeccakP-1600-times8-SnP.h" +#endif + +#define chunkSize 8192 +#define laneSize 8 +#define suffixLeaf 0x0B /* '110': message hop, simple padding, inner node */ + +#define security 128 +#define capacity (2*security) +#define capacityInBytes (capacity/8) +#define capacityInLanes (capacityInBytes/laneSize) +#define rate (1600-capacity) +#define rateInBytes (rate/8) +#define rateInLanes (rateInBytes/laneSize) + +#define ParallelSpongeFastLoop( Parallellism ) \ + while ( inLen >= Parallellism * chunkSize ) { \ + ALIGN(KeccakP1600times##Parallellism##_statesAlignment) unsigned char states[KeccakP1600times##Parallellism##_statesSizeInBytes]; \ + unsigned char intermediate[Parallellism*capacityInBytes]; \ + unsigned int localBlockLen = chunkSize; \ + const unsigned char * localInput = input; \ + unsigned int i; \ + unsigned int fastLoopOffset; \ + \ + KeccakP1600times##Parallellism##_StaticInitialize(); \ + KeccakP1600times##Parallellism##_InitializeAll(states); \ + fastLoopOffset = KeccakP1600times##Parallellism##_12rounds_FastLoop_Absorb(states, rateInLanes, chunkSize / laneSize, rateInLanes, localInput, Parallellism * chunkSize); \ + localBlockLen -= fastLoopOffset; \ + localInput += fastLoopOffset; \ + for ( i = 0; i < Parallellism; ++i, localInput += chunkSize ) { \ + KeccakP1600times##Parallellism##_AddBytes(states, i, localInput, 0, localBlockLen); \ + KeccakP1600times##Parallellism##_AddByte(states, i, suffixLeaf, localBlockLen); \ + KeccakP1600times##Parallellism##_AddByte(states, i, 0x80, rateInBytes-1); \ + } \ + KeccakP1600times##Parallellism##_PermuteAll_12rounds(states); \ + input += Parallellism * chunkSize; \ + inLen -= Parallellism * chunkSize; \ + ktInstance->blockNumber += Parallellism; \ + KeccakP1600times##Parallellism##_ExtractLanesAll(states, intermediate, capacityInLanes, capacityInLanes ); \ + if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, Parallellism * capacityInBytes) != 0) return 1; \ + } + +#define ParallelSpongeLoop( Parallellism ) \ + while ( inLen >= Parallellism * chunkSize ) { \ + ALIGN(KeccakP1600times##Parallellism##_statesAlignment) unsigned char states[KeccakP1600times##Parallellism##_statesSizeInBytes]; \ + unsigned char intermediate[Parallellism*capacityInBytes]; \ + unsigned int localBlockLen = chunkSize; \ + const unsigned char * localInput = input; \ + unsigned int i; \ + \ + KeccakP1600times##Parallellism##_StaticInitialize(); \ + KeccakP1600times##Parallellism##_InitializeAll(states); \ + while(localBlockLen >= rateInBytes) { \ + KeccakP1600times##Parallellism##_AddLanesAll(states, localInput, rateInLanes, chunkSize / laneSize); \ + KeccakP1600times##Parallellism##_PermuteAll_12rounds(states); \ + localBlockLen -= rateInBytes; \ + localInput += rateInBytes; \ + } \ + for ( i = 0; i < Parallellism; ++i, localInput += chunkSize ) { \ + KeccakP1600times##Parallellism##_AddBytes(states, i, localInput, 0, localBlockLen); \ + KeccakP1600times##Parallellism##_AddByte(states, i, suffixLeaf, localBlockLen); \ + KeccakP1600times##Parallellism##_AddByte(states, i, 0x80, rateInBytes-1); \ + } \ + KeccakP1600times##Parallellism##_PermuteAll_12rounds(states); \ + input += Parallellism * chunkSize; \ + inLen -= Parallellism * chunkSize; \ + ktInstance->blockNumber += Parallellism; \ + KeccakP1600times##Parallellism##_ExtractLanesAll(states, intermediate, capacityInLanes, capacityInLanes ); \ + if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, Parallellism * capacityInBytes) != 0) return 1; \ + } + +static unsigned int right_encode( unsigned char * encbuf, size_t value ) +{ + unsigned int n, i; + size_t v; + + for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 ) + ; /* empty */ + for ( i = 1; i <= n; ++i ) + encbuf[i-1] = (unsigned char)(value >> (8 * (n-i))); + encbuf[n] = (unsigned char)n; + return n + 1; +} + +int KangarooTwelve_Initialize(KangarooTwelve_Instance *ktInstance, size_t outputLen) +{ + ktInstance->fixedOutputLength = outputLen; + ktInstance->queueAbsorbedLen = 0; + ktInstance->blockNumber = 0; + ktInstance->phase = ABSORBING; + return KeccakWidth1600_12rounds_SpongeInitialize(&ktInstance->finalNode, rate, capacity); +} + +int KangarooTwelve_Update(KangarooTwelve_Instance *ktInstance, const unsigned char *input, size_t inLen) +{ + if (ktInstance->phase != ABSORBING) + return 1; + + if ( ktInstance->blockNumber == 0 ) { + /* First block, absorb in final node */ + unsigned int len = (inLen < (chunkSize - ktInstance->queueAbsorbedLen)) ? inLen : (chunkSize - ktInstance->queueAbsorbedLen); + if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, input, len) != 0) + return 1; + input += len; + inLen -= len; + ktInstance->queueAbsorbedLen += len; + if ( (ktInstance->queueAbsorbedLen == chunkSize) && (inLen != 0) ) { + /* First block complete and more input data available, finalize it */ + const unsigned char padding = 0x03; /* '110^6': message hop, simple padding */ + ktInstance->queueAbsorbedLen = 0; + ktInstance->blockNumber = 1; + if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, &padding, 1) != 0) + return 1; + ktInstance->finalNode.byteIOIndex = (ktInstance->finalNode.byteIOIndex + 7) & ~7; /* Zero padding up to 64 bits */ + } + } + else if ( ktInstance->queueAbsorbedLen != 0 ) { + /* There is data in the queue, absorb further in queue until block complete */ + unsigned int len = (inLen < (chunkSize - ktInstance->queueAbsorbedLen)) ? inLen : (chunkSize - ktInstance->queueAbsorbedLen); + if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->queueNode, input, len) != 0) + return 1; + input += len; + inLen -= len; + ktInstance->queueAbsorbedLen += len; + if ( ktInstance->queueAbsorbedLen == chunkSize ) { + unsigned char intermediate[capacityInBytes]; + ktInstance->queueAbsorbedLen = 0; + ++ktInstance->blockNumber; + if (KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits(&ktInstance->queueNode, suffixLeaf) != 0) + return 1; + if (KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->queueNode, intermediate, capacityInBytes) != 0) + return 1; + if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, capacityInBytes) != 0) + return 1; + } + } + + #if defined(KeccakP1600times8_implementation) && !defined(KeccakP1600times8_isFallback) + #if defined(KeccakP1600times8_12rounds_FastLoop_supported) + ParallelSpongeFastLoop( 8 ) + #else + ParallelSpongeLoop( 8 ) + #endif + #endif + + #if defined(KeccakP1600times4_implementation) && !defined(KeccakP1600times4_isFallback) + #if defined(KeccakP1600times4_12rounds_FastLoop_supported) + ParallelSpongeFastLoop( 4 ) + #else + ParallelSpongeLoop( 4 ) + #endif + #endif + + #if defined(KeccakP1600times2_implementation) && !defined(KeccakP1600times2_isFallback) + #if defined(KeccakP1600times2_12rounds_FastLoop_supported) + ParallelSpongeFastLoop( 2 ) + #else + ParallelSpongeLoop( 2 ) + #endif + #endif + + while ( inLen > 0 ) { + unsigned int len = (inLen < chunkSize) ? inLen : chunkSize; + if (KeccakWidth1600_12rounds_SpongeInitialize(&ktInstance->queueNode, rate, capacity) != 0) + return 1; + if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->queueNode, input, len) != 0) + return 1; + input += len; + inLen -= len; + if ( len == chunkSize ) { + unsigned char intermediate[capacityInBytes]; + ++ktInstance->blockNumber; + if (KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits(&ktInstance->queueNode, suffixLeaf) != 0) + return 1; + if (KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->queueNode, intermediate, capacityInBytes) != 0) + return 1; + if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, capacityInBytes) != 0) + return 1; + } + else + ktInstance->queueAbsorbedLen = len; + } + + return 0; +} + +int KangarooTwelve_Final(KangarooTwelve_Instance *ktInstance, unsigned char * output, const unsigned char * customization, size_t customLen) +{ + unsigned char encbuf[sizeof(size_t)+1+2]; + unsigned char padding; + + if (ktInstance->phase != ABSORBING) + return 1; + + /* Absorb customization | right_encode(customLen) */ + if ((customLen != 0) && (KangarooTwelve_Update(ktInstance, customization, customLen) != 0)) + return 1; + if (KangarooTwelve_Update(ktInstance, encbuf, right_encode(encbuf, customLen)) != 0) + return 1; + + if ( ktInstance->blockNumber == 0 ) { + /* Non complete first block in final node, pad it */ + padding = 0x07; /* '11': message hop, final node */ + } + else { + unsigned int n; + + if ( ktInstance->queueAbsorbedLen != 0 ) { + /* There is data in the queue node */ + unsigned char intermediate[capacityInBytes]; + ++ktInstance->blockNumber; + if (KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits(&ktInstance->queueNode, suffixLeaf) != 0) + return 1; + if (KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->queueNode, intermediate, capacityInBytes) != 0) + return 1; + if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, capacityInBytes) != 0) + return 1; + } + --ktInstance->blockNumber; /* Absorb right_encode(number of Chaining Values) || 0xFF || 0xFF */ + n = right_encode(encbuf, ktInstance->blockNumber); + encbuf[n++] = 0xFF; + encbuf[n++] = 0xFF; + if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, encbuf, n) != 0) + return 1; + padding = 0x06; /* '01': chaining hop, final node */ + } + if (KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits(&ktInstance->finalNode, padding) != 0) + return 1; + if ( ktInstance->fixedOutputLength != 0 ) { + ktInstance->phase = FINAL; + return KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->finalNode, output, ktInstance->fixedOutputLength); + } + ktInstance->phase = SQUEEZING; + return 0; +} + +int KangarooTwelve_Squeeze(KangarooTwelve_Instance *ktInstance, unsigned char * output, size_t outputLen) +{ + if (ktInstance->phase != SQUEEZING) + return 1; + return KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->finalNode, output, outputLen); +} + +int KangarooTwelve( const unsigned char * input, size_t inLen, unsigned char * output, size_t outLen, const unsigned char * customization, size_t customLen ) +{ + KangarooTwelve_Instance ktInstance; + + if (outLen == 0) + return 1; + if (KangarooTwelve_Initialize(&ktInstance, outLen) != 0) + return 1; + if (KangarooTwelve_Update(&ktInstance, input, inLen) != 0) + return 1; + return KangarooTwelve_Final(&ktInstance, output, customization, customLen); +} diff --git a/src/crypto/k12/KangarooTwelve.h b/src/crypto/k12/KangarooTwelve.h new file mode 100644 index 00000000..0e9ed41e --- /dev/null +++ b/src/crypto/k12/KangarooTwelve.h @@ -0,0 +1,89 @@ +/* +Implementation by Ronny Van Keer, hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _KangarooTwelve_h_ +#define _KangarooTwelve_h_ + +#ifndef KeccakP1600_excluded + +#include +#include "align.h" +#include "KeccakSpongeWidth1600.h" +#include "Phases.h" + +typedef KCP_Phases KangarooTwelve_Phases; + +typedef struct { + KeccakWidth1600_12rounds_SpongeInstance queueNode; + KeccakWidth1600_12rounds_SpongeInstance finalNode; + size_t fixedOutputLength; + size_t blockNumber; + unsigned int queueAbsorbedLen; + KangarooTwelve_Phases phase; +} KangarooTwelve_Instance; + +/** Extendable ouput function KangarooTwelve. + * @param input Pointer to the input message (M). + * @param inputByteLen The length of the input message in bytes. + * @param output Pointer to the output buffer. + * @param outputByteLen The desired number of output bytes. + * @param customization Pointer to the customization string (C). + * @param customByteLen The length of the customization string in bytes. + * @return 0 if successful, 1 otherwise. + */ +int KangarooTwelve(const unsigned char *input, size_t inputByteLen, unsigned char *output, size_t outputByteLen, const unsigned char *customization, size_t customByteLen ); + +/** + * Function to initialize a KangarooTwelve instance. + * @param ktInstance Pointer to the instance to be initialized. + * @param outputByteLen The desired number of output bytes, + * or 0 for an arbitrarily-long output. + * @return 0 if successful, 1 otherwise. + */ +int KangarooTwelve_Initialize(KangarooTwelve_Instance *ktInstance, size_t outputByteLen); + +/** + * Function to give input data to be absorbed. + * @param ktInstance Pointer to the instance initialized by KangarooTwelve_Initialize(). + * @param input Pointer to the input message data (M). + * @param inputByteLen The number of bytes provided in the input message data. + * @return 0 if successful, 1 otherwise. + */ +int KangarooTwelve_Update(KangarooTwelve_Instance *ktInstance, const unsigned char *input, size_t inputByteLen); + +/** + * Function to call after all the input message has been input, and to get + * output bytes if the length was specified when calling KangarooTwelve_Initialize(). + * @param ktInstance Pointer to the hash instance initialized by KangarooTwelve_Initialize(). + * If @a outputByteLen was not 0 in the call to KangarooTwelve_Initialize(), the number of + * output bytes is equal to @a outputByteLen. + * If @a outputByteLen was 0 in the call to KangarooTwelve_Initialize(), the output bytes + * must be extracted using the KangarooTwelve_Squeeze() function. + * @param output Pointer to the buffer where to store the output data. + * @param customization Pointer to the customization string (C). + * @param customByteLen The length of the customization string in bytes. + * @return 0 if successful, 1 otherwise. + */ +int KangarooTwelve_Final(KangarooTwelve_Instance *ktInstance, unsigned char *output, const unsigned char *customization, size_t customByteLen); + +/** + * Function to squeeze output data. + * @param ktInstance Pointer to the hash instance initialized by KangarooTwelve_Initialize(). + * @param data Pointer to the buffer where to store the output data. + * @param outputByteLen The number of output bytes desired. + * @pre KangarooTwelve_Final() must have been already called. + * @return 0 if successful, 1 otherwise. + */ +int KangarooTwelve_Squeeze(KangarooTwelve_Instance *ktInstance, unsigned char *output, size_t outputByteLen); + +#endif + +#endif diff --git a/src/crypto/k12/KeccakP-1600-SnP.h b/src/crypto/k12/KeccakP-1600-SnP.h new file mode 100644 index 00000000..907e3581 --- /dev/null +++ b/src/crypto/k12/KeccakP-1600-SnP.h @@ -0,0 +1,41 @@ +/* +Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, +Michaël Peeters, Gilles Van Assche and Ronny Van Keer, +hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ + +--- + +Please refer to SnP-documentation.h for more details. +*/ + +#ifndef _KeccakP_1600_SnP_h_ +#define _KeccakP_1600_SnP_h_ + +#define KeccakP1600_implementation "64-bit reference implementation" +#define KeccakP1600_stateSizeInBytes 200 +#define KeccakP1600_stateAlignment 8 + +#ifdef KeccakReference +void KeccakP1600_StaticInitialize( void ); +#else +#define KeccakP1600_StaticInitialize() +#endif +void KeccakP1600_Initialize(void *state); +void KeccakP1600_AddByte(void *state, unsigned char data, unsigned int offset); +void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length); +void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length); +void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount); +void KeccakP1600_Permute_Nrounds(void *state, unsigned int nrounds); +void KeccakP1600_Permute_12rounds(void *state); +void KeccakP1600_Permute_24rounds(void *state); +void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length); +void KeccakP1600_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length); + +#endif diff --git a/src/crypto/k12/KeccakP-1600-reference.c b/src/crypto/k12/KeccakP-1600-reference.c new file mode 100644 index 00000000..0c126030 --- /dev/null +++ b/src/crypto/k12/KeccakP-1600-reference.c @@ -0,0 +1,402 @@ +/* +Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, +Michaël Peeters, Gilles Van Assche and Ronny Van Keer, +hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ + +--- + +This file implements Keccak-p[1600] in a SnP-compatible way. +Please refer to SnP-documentation.h for more details. + +This implementation comes with KeccakP-1600-SnP.h in the same folder. +Please refer to LowLevel.build for the exact list of other files it must be combined with. +*/ + +#include +#include +#include +#include +#include "brg_endian.h" +#ifdef KeccakReference +#include "displayIntermediateValues.h" +#endif + +typedef unsigned char UINT8; +typedef unsigned long long UINT64; +typedef UINT64 tKeccakLane; + +#define maxNrRounds 24 +#define nrLanes 25 +#define index(x, y) (((x)%5)+5*((y)%5)) + +#ifdef KeccakReference + +static tKeccakLane KeccakRoundConstants[maxNrRounds]; +static unsigned int KeccakRhoOffsets[nrLanes]; + +/* ---------------------------------------------------------------- */ + +void KeccakP1600_InitializeRoundConstants(void); +void KeccakP1600_InitializeRhoOffsets(void); +static int LFSR86540(UINT8 *LFSR); + +void KeccakP1600_StaticInitialize(void) +{ + if (sizeof(tKeccakLane) != 8) { + printf("tKeccakLane should be 64-bit wide\n"); + abort(); + } + KeccakP1600_InitializeRoundConstants(); + KeccakP1600_InitializeRhoOffsets(); +} + +void KeccakP1600_InitializeRoundConstants(void) +{ + UINT8 LFSRstate = 0x01; + unsigned int i, j, bitPosition; + + for(i=0; i> (64-offset))) : a) + +static void theta(tKeccakLane *A) +{ + unsigned int x, y; + tKeccakLane C[5], D[5]; + + for(x=0; x<5; x++) { + C[x] = 0; + for(y=0; y<5; y++) + C[x] ^= A[index(x, y)]; + } + for(x=0; x<5; x++) + D[x] = ROL64(C[(x+1)%5], 1) ^ C[(x+4)%5]; + for(x=0; x<5; x++) + for(y=0; y<5; y++) + A[index(x, y)] ^= D[x]; +} + +static void rho(tKeccakLane *A) +{ + unsigned int x, y; + + for(x=0; x<5; x++) for(y=0; y<5; y++) + A[index(x, y)] = ROL64(A[index(x, y)], KeccakRhoOffsets[index(x, y)]); +} + +static void pi(tKeccakLane *A) +{ + unsigned int x, y; + tKeccakLane tempA[25]; + + for(x=0; x<5; x++) for(y=0; y<5; y++) + tempA[index(x, y)] = A[index(x, y)]; + for(x=0; x<5; x++) for(y=0; y<5; y++) + A[index(0*x+1*y, 2*x+3*y)] = tempA[index(x, y)]; +} + +static void chi(tKeccakLane *A) +{ + unsigned int x, y; + tKeccakLane C[5]; + + for(y=0; y<5; y++) { + for(x=0; x<5; x++) + C[x] = A[index(x, y)] ^ ((~A[index(x+1, y)]) & A[index(x+2, y)]); + for(x=0; x<5; x++) + A[index(x, y)] = C[x]; + } +} + +static void iota(tKeccakLane *A, unsigned int indexRound) +{ + A[index(0, 0)] ^= KeccakRoundConstants[indexRound]; +} + +/* ---------------------------------------------------------------- */ + +void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length) +{ + assert(offset < 200); + assert(offset+length <= 200); + memcpy(data, (unsigned char*)state+offset, length); +} + +/* ---------------------------------------------------------------- */ + +void KeccakP1600_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length) +{ + unsigned int i; + + assert(offset < 200); + assert(offset+length <= 200); + for(i=0; i> 32)); + fprintf(f, "%08X", (unsigned int)(KeccakRoundConstants[i] & 0xFFFFFFFFULL)); + fprintf(f, "\n"); + } + fprintf(f, "\n"); +} + +void KeccakP1600_DisplayRhoOffsets(FILE *f) +{ + unsigned int x, y; + + for(y=0; y<5; y++) for(x=0; x<5; x++) { + fprintf(f, "RhoOffset[%i][%i] = ", x, y); + fprintf(f, "%2i", KeccakRhoOffsets[index(x, y)]); + fprintf(f, "\n"); + } + fprintf(f, "\n"); +} diff --git a/src/crypto/k12/KeccakP-1600-reference.h b/src/crypto/k12/KeccakP-1600-reference.h new file mode 100644 index 00000000..909b282c --- /dev/null +++ b/src/crypto/k12/KeccakP-1600-reference.h @@ -0,0 +1,20 @@ +/* +Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, +Michaël Peeters, Gilles Van Assche and Ronny Van Keer, +hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _KeccakP_1600_reference_h_ +#define _KeccakP_1600_reference_h_ + +void KeccakP1600_DisplayRoundConstants(FILE *f); +void KeccakP1600_DisplayRhoOffsets(FILE *f); + +#endif diff --git a/src/crypto/k12/KeccakSponge-common.h b/src/crypto/k12/KeccakSponge-common.h new file mode 100644 index 00000000..8fb3ba1a --- /dev/null +++ b/src/crypto/k12/KeccakSponge-common.h @@ -0,0 +1,35 @@ +/* +Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, +Michaël Peeters, Gilles Van Assche and Ronny Van Keer, +hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _KeccakSpongeCommon_h_ +#define _KeccakSpongeCommon_h_ + +#include +#include "align.h" + +#define KCP_DeclareSpongeStructure(prefix, size, alignment) \ + ALIGN(alignment) typedef struct prefix##_SpongeInstanceStruct { \ + unsigned char state[size]; \ + unsigned int rate; \ + unsigned int byteIOIndex; \ + int squeezing; \ + } prefix##_SpongeInstance; + +#define KCP_DeclareSpongeFunctions(prefix) \ + int prefix##_Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen); \ + int prefix##_SpongeInitialize(prefix##_SpongeInstance *spongeInstance, unsigned int rate, unsigned int capacity); \ + int prefix##_SpongeAbsorb(prefix##_SpongeInstance *spongeInstance, const unsigned char *data, size_t dataByteLen); \ + int prefix##_SpongeAbsorbLastFewBits(prefix##_SpongeInstance *spongeInstance, unsigned char delimitedData); \ + int prefix##_SpongeSqueeze(prefix##_SpongeInstance *spongeInstance, unsigned char *data, size_t dataByteLen); + +#endif diff --git a/src/crypto/k12/KeccakSponge.inc b/src/crypto/k12/KeccakSponge.inc new file mode 100644 index 00000000..f6c59cee --- /dev/null +++ b/src/crypto/k12/KeccakSponge.inc @@ -0,0 +1,311 @@ +/* +Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, +Michaël Peeters, Gilles Van Assche and Ronny Van Keer, +hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#define JOIN0(a, b) a ## b +#define JOIN(a, b) JOIN0(a, b) + +#define Sponge JOIN(prefix, _Sponge) +#define SpongeInstance JOIN(prefix, _SpongeInstance) +#define SpongeInitialize JOIN(prefix, _SpongeInitialize) +#define SpongeAbsorb JOIN(prefix, _SpongeAbsorb) +#define SpongeAbsorbLastFewBits JOIN(prefix, _SpongeAbsorbLastFewBits) +#define SpongeSqueeze JOIN(prefix, _SpongeSqueeze) + +#define SnP_stateSizeInBytes JOIN(SnP, _stateSizeInBytes) +#define SnP_stateAlignment JOIN(SnP, _stateAlignment) +#define SnP_StaticInitialize JOIN(SnP, _StaticInitialize) +#define SnP_Initialize JOIN(SnP, _Initialize) +#define SnP_AddByte JOIN(SnP, _AddByte) +#define SnP_AddBytes JOIN(SnP, _AddBytes) +#define SnP_ExtractBytes JOIN(SnP, _ExtractBytes) + +int Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen) +{ + ALIGN(SnP_stateAlignment) unsigned char state[SnP_stateSizeInBytes]; + unsigned int partialBlock; + const unsigned char *curInput = input; + unsigned char *curOutput = output; + unsigned int rateInBytes = rate/8; + + if (rate+capacity != SnP_width) + return 1; + if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0)) + return 1; + if (suffix == 0) + return 1; + + /* Initialize the state */ + SnP_StaticInitialize(); + SnP_Initialize(state); + + /* First, absorb whole blocks */ +#ifdef SnP_FastLoop_Absorb + if (((rateInBytes % (SnP_width/200)) == 0) && (inputByteLen >= rateInBytes)) { + /* fast lane: whole lane rate */ + size_t j; + j = SnP_FastLoop_Absorb(state, rateInBytes/(SnP_width/200), curInput, inputByteLen); + curInput += j; + inputByteLen -= j; + } +#endif + while(inputByteLen >= (size_t)rateInBytes) { + #ifdef KeccakReference + displayBytes(1, "Block to be absorbed", curInput, rateInBytes); + #endif + SnP_AddBytes(state, curInput, 0, rateInBytes); + SnP_Permute(state); + curInput += rateInBytes; + inputByteLen -= rateInBytes; + } + + /* Then, absorb what remains */ + partialBlock = (unsigned int)inputByteLen; + #ifdef KeccakReference + displayBytes(1, "Block to be absorbed (part)", curInput, partialBlock); + #endif + SnP_AddBytes(state, curInput, 0, partialBlock); + + /* Finally, absorb the suffix */ + #ifdef KeccakReference + { + unsigned char delimitedData1[1]; + delimitedData1[0] = suffix; + displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1); + } + #endif + /* Last few bits, whose delimiter coincides with first bit of padding */ + SnP_AddByte(state, suffix, partialBlock); + /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */ + if ((suffix >= 0x80) && (partialBlock == (rateInBytes-1))) + SnP_Permute(state); + /* Second bit of padding */ + SnP_AddByte(state, 0x80, rateInBytes-1); + #ifdef KeccakReference + { + unsigned char block[SnP_width/8]; + memset(block, 0, SnP_width/8); + block[rateInBytes-1] = 0x80; + displayBytes(1, "Second bit of padding", block, rateInBytes); + } + #endif + SnP_Permute(state); + #ifdef KeccakReference + displayText(1, "--- Switching to squeezing phase ---"); + #endif + + /* First, output whole blocks */ + while(outputByteLen > (size_t)rateInBytes) { + SnP_ExtractBytes(state, curOutput, 0, rateInBytes); + SnP_Permute(state); + #ifdef KeccakReference + displayBytes(1, "Squeezed block", curOutput, rateInBytes); + #endif + curOutput += rateInBytes; + outputByteLen -= rateInBytes; + } + + /* Finally, output what remains */ + partialBlock = (unsigned int)outputByteLen; + SnP_ExtractBytes(state, curOutput, 0, partialBlock); + #ifdef KeccakReference + displayBytes(1, "Squeezed block (part)", curOutput, partialBlock); + #endif + + return 0; +} + +/* ---------------------------------------------------------------- */ +/* ---------------------------------------------------------------- */ +/* ---------------------------------------------------------------- */ + +int SpongeInitialize(SpongeInstance *instance, unsigned int rate, unsigned int capacity) +{ + if (rate+capacity != SnP_width) + return 1; + if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0)) + return 1; + SnP_StaticInitialize(); + SnP_Initialize(instance->state); + instance->rate = rate; + instance->byteIOIndex = 0; + instance->squeezing = 0; + + return 0; +} + +/* ---------------------------------------------------------------- */ + +int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dataByteLen) +{ + size_t i, j; + unsigned int partialBlock; + const unsigned char *curData; + unsigned int rateInBytes = instance->rate/8; + + if (instance->squeezing) + return 1; /* Too late for additional input */ + + i = 0; + curData = data; + while(i < dataByteLen) { + if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) { +#ifdef SnP_FastLoop_Absorb + /* processing full blocks first */ + if ((rateInBytes % (SnP_width/200)) == 0) { + /* fast lane: whole lane rate */ + j = SnP_FastLoop_Absorb(instance->state, rateInBytes/(SnP_width/200), curData, dataByteLen - i); + i += j; + curData += j; + } + else { +#endif + for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { + #ifdef KeccakReference + displayBytes(1, "Block to be absorbed", curData, rateInBytes); + #endif + SnP_AddBytes(instance->state, curData, 0, rateInBytes); + SnP_Permute(instance->state); + curData+=rateInBytes; + } + i = dataByteLen - j; +#ifdef SnP_FastLoop_Absorb + } +#endif + } + else { + /* normal lane: using the message queue */ + partialBlock = (unsigned int)(dataByteLen - i); + if (partialBlock+instance->byteIOIndex > rateInBytes) + partialBlock = rateInBytes-instance->byteIOIndex; + #ifdef KeccakReference + displayBytes(1, "Block to be absorbed (part)", curData, partialBlock); + #endif + i += partialBlock; + + SnP_AddBytes(instance->state, curData, instance->byteIOIndex, partialBlock); + curData += partialBlock; + instance->byteIOIndex += partialBlock; + if (instance->byteIOIndex == rateInBytes) { + SnP_Permute(instance->state); + instance->byteIOIndex = 0; + } + } + } + return 0; +} + +/* ---------------------------------------------------------------- */ + +int SpongeAbsorbLastFewBits(SpongeInstance *instance, unsigned char delimitedData) +{ + unsigned int rateInBytes = instance->rate/8; + + if (delimitedData == 0) + return 1; + if (instance->squeezing) + return 1; /* Too late for additional input */ + + #ifdef KeccakReference + { + unsigned char delimitedData1[1]; + delimitedData1[0] = delimitedData; + displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1); + } + #endif + /* Last few bits, whose delimiter coincides with first bit of padding */ + SnP_AddByte(instance->state, delimitedData, instance->byteIOIndex); + /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */ + if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes-1))) + SnP_Permute(instance->state); + /* Second bit of padding */ + SnP_AddByte(instance->state, 0x80, rateInBytes-1); + #ifdef KeccakReference + { + unsigned char block[SnP_width/8]; + memset(block, 0, SnP_width/8); + block[rateInBytes-1] = 0x80; + displayBytes(1, "Second bit of padding", block, rateInBytes); + } + #endif + SnP_Permute(instance->state); + instance->byteIOIndex = 0; + instance->squeezing = 1; + #ifdef KeccakReference + displayText(1, "--- Switching to squeezing phase ---"); + #endif + return 0; +} + +/* ---------------------------------------------------------------- */ + +int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByteLen) +{ + size_t i, j; + unsigned int partialBlock; + unsigned int rateInBytes = instance->rate/8; + unsigned char *curData; + + if (!instance->squeezing) + SpongeAbsorbLastFewBits(instance, 0x01); + + i = 0; + curData = data; + while(i < dataByteLen) { + if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) { + for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { + SnP_Permute(instance->state); + SnP_ExtractBytes(instance->state, curData, 0, rateInBytes); + #ifdef KeccakReference + displayBytes(1, "Squeezed block", curData, rateInBytes); + #endif + curData+=rateInBytes; + } + i = dataByteLen - j; + } + else { + /* normal lane: using the message queue */ + if (instance->byteIOIndex == rateInBytes) { + SnP_Permute(instance->state); + instance->byteIOIndex = 0; + } + partialBlock = (unsigned int)(dataByteLen - i); + if (partialBlock+instance->byteIOIndex > rateInBytes) + partialBlock = rateInBytes-instance->byteIOIndex; + i += partialBlock; + + SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock); + #ifdef KeccakReference + displayBytes(1, "Squeezed block (part)", curData, partialBlock); + #endif + curData += partialBlock; + instance->byteIOIndex += partialBlock; + } + } + return 0; +} + +/* ---------------------------------------------------------------- */ + +#undef Sponge +#undef SpongeInstance +#undef SpongeInitialize +#undef SpongeAbsorb +#undef SpongeAbsorbLastFewBits +#undef SpongeSqueeze +#undef SnP_stateSizeInBytes +#undef SnP_stateAlignment +#undef SnP_StaticInitialize +#undef SnP_Initialize +#undef SnP_AddByte +#undef SnP_AddBytes +#undef SnP_ExtractBytes diff --git a/src/crypto/k12/KeccakSpongeWidth1600.c b/src/crypto/k12/KeccakSpongeWidth1600.c new file mode 100644 index 00000000..672ec36d --- /dev/null +++ b/src/crypto/k12/KeccakSpongeWidth1600.c @@ -0,0 +1,54 @@ +/* +Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, +Michaël Peeters, Gilles Van Assche and Ronny Van Keer, +hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#include "KeccakSpongeWidth1600.h" + +#ifdef KeccakReference + #include "displayIntermediateValues.h" +#endif + +#ifndef KeccakP1600_excluded + #include "KeccakP-1600-SnP.h" + + #define prefix KeccakWidth1600 + #define SnP KeccakP1600 + #define SnP_width 1600 + #define SnP_Permute KeccakP1600_Permute_24rounds + #if defined(KeccakF1600_FastLoop_supported) + #define SnP_FastLoop_Absorb KeccakF1600_FastLoop_Absorb + #endif + #include "KeccakSponge.inc" + #undef prefix + #undef SnP + #undef SnP_width + #undef SnP_Permute + #undef SnP_FastLoop_Absorb +#endif + +#ifndef KeccakP1600_excluded + #include "KeccakP-1600-SnP.h" + + #define prefix KeccakWidth1600_12rounds + #define SnP KeccakP1600 + #define SnP_width 1600 + #define SnP_Permute KeccakP1600_Permute_12rounds + #if defined(KeccakP1600_12rounds_FastLoop_supported) + #define SnP_FastLoop_Absorb KeccakP1600_12rounds_FastLoop_Absorb + #endif + #include "KeccakSponge.inc" + #undef prefix + #undef SnP + #undef SnP_width + #undef SnP_Permute + #undef SnP_FastLoop_Absorb +#endif diff --git a/src/crypto/k12/KeccakSpongeWidth1600.h b/src/crypto/k12/KeccakSpongeWidth1600.h new file mode 100644 index 00000000..1558256c --- /dev/null +++ b/src/crypto/k12/KeccakSpongeWidth1600.h @@ -0,0 +1,31 @@ +/* +Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, +Michaël Peeters, Gilles Van Assche and Ronny Van Keer, +hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _KeccakSpongeWidth1600_h_ +#define _KeccakSpongeWidth1600_h_ + +#include "KeccakSponge-common.h" + +#ifndef KeccakP1600_excluded + #include "KeccakP-1600-SnP.h" + KCP_DeclareSpongeStructure(KeccakWidth1600, KeccakP1600_stateSizeInBytes, KeccakP1600_stateAlignment) + KCP_DeclareSpongeFunctions(KeccakWidth1600) +#endif + +#ifndef KeccakP1600_excluded + #include "KeccakP-1600-SnP.h" + KCP_DeclareSpongeStructure(KeccakWidth1600_12rounds, KeccakP1600_stateSizeInBytes, KeccakP1600_stateAlignment) + KCP_DeclareSpongeFunctions(KeccakWidth1600_12rounds) +#endif + +#endif diff --git a/src/crypto/k12/Phases.h b/src/crypto/k12/Phases.h new file mode 100644 index 00000000..769125c3 --- /dev/null +++ b/src/crypto/k12/Phases.h @@ -0,0 +1,22 @@ +/* +Implementation by Ronny Van Keer, hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _Phases_h_ +#define _Phases_h_ + +typedef enum { + NOT_INITIALIZED, + ABSORBING, + FINAL, + SQUEEZING +} KCP_Phases; + +#endif diff --git a/src/crypto/k12/align.h b/src/crypto/k12/align.h new file mode 100644 index 00000000..90c1b37a --- /dev/null +++ b/src/crypto/k12/align.h @@ -0,0 +1,32 @@ +/* +Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, +Michaël Peeters, Gilles Van Assche and Ronny Van Keer, +hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _align_h_ +#define _align_h_ + +/* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror chokes on the redef. */ +#ifdef ALIGN +#undef ALIGN +#endif + +#if defined(__GNUC__) +#define ALIGN(x) __attribute__ ((aligned(x))) +#elif defined(_MSC_VER) +#define ALIGN(x) __declspec(align(x)) +#elif defined(__ARMCC_VERSION) +#define ALIGN(x) __align(x) +#else +#define ALIGN(x) +#endif + +#endif diff --git a/src/crypto/k12/brg_endian.h b/src/crypto/k12/brg_endian.h new file mode 100644 index 00000000..7c640b90 --- /dev/null +++ b/src/crypto/k12/brg_endian.h @@ -0,0 +1,143 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 + Changes for ARM 9/9/2010 +*/ + +#ifndef _BRG_ENDIAN_H +#define _BRG_ENDIAN_H + +#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ +#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ + +#if 0 +/* Include files where endian defines and byteswap functions may reside */ +#if defined( __sun ) +# include +#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) +# include +#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \ + defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ ) +# include +#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ ) +# if !defined( __MINGW32__ ) && !defined( _AIX ) +# include +# if !defined( __BEOS__ ) +# include +# endif +# endif +#endif +#endif + +/* Now attempt to set the define for platform byte order using any */ +/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */ +/* seem to encompass most endian symbol definitions */ + +#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN ) +# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN ) +# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( _BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( _LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN ) +# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( __BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( __LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ ) +# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__ +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__ +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( __BIG_ENDIAN__ ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( __LITTLE_ENDIAN__ ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +/* if the platform byte order could not be determined, then try to */ +/* set this define using common machine defines */ +#if !defined(PLATFORM_BYTE_ORDER) + +#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \ + defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \ + defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \ + defined( vax ) || defined( vms ) || defined( VMS ) || \ + defined( __VMS ) || defined( _M_X64 ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN + +#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \ + defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \ + defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \ + defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \ + defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \ + defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \ + defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX ) || \ + defined( __s390__ ) || defined( __s390x__ ) || defined( __zarch__ ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN + +#elif defined(__arm__) +# ifdef __BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# else +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif 1 /* **** EDIT HERE IF NECESSARY **** */ +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#else +# error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order +#endif + +#endif + +#endif diff --git a/src/workers/CpuThread.cpp b/src/workers/CpuThread.cpp index 6548b461..2ae756df 100644 --- a/src/workers/CpuThread.cpp +++ b/src/workers/CpuThread.cpp @@ -39,6 +39,9 @@ # include "crypto/CryptoNight_x86.h" #endif +#ifndef XMRIG_NO_AEON +# include "crypto/k12.h" +#endif xmrig::CpuThread::CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch, Assembly assembly) : m_algorithm(algorithm), @@ -566,6 +569,44 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE # endif + +# ifndef XMRIG_NO_AEON + k12, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_0 + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1 + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TUBE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XTL + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_MSR + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XHV + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XAO + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RTO + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_2 + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_HALF + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TRTL + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_GPU + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_WOW + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_4 + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE +# else + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_0 + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1 + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TUBE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XTL + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_MSR + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XHV + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XAO + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RTO + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_2 + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_HALF + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TRTL + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_GPU + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_WOW + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_4 + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE +# endif }; static_assert(count == sizeof(func_table) / sizeof(func_table[0]), "func_table size mismatch"); diff --git a/src/workers/MultiWorker.cpp b/src/workers/MultiWorker.cpp index 02eec378..3d7fed6c 100644 --- a/src/workers/MultiWorker.cpp +++ b/src/workers/MultiWorker.cpp @@ -85,6 +85,9 @@ bool MultiWorker::selfTest() return verify(VARIANT_0, test_output_v0_lite) && verify(VARIANT_1, test_output_v1_lite); } + if (m_thread->algorithm() == KANGAROOTWELVE) { + return verify(VARIANT_0, test_output_k12); + } # endif # ifndef XMRIG_NO_SUMO