Cleanup MoneroOcean patchset
This commit is contained in:
parent
aaaaf5c1ed
commit
c4ff8c4064
49 changed files with 2094 additions and 2237 deletions
271
src/crypto/randomx/defyx/KangarooTwelve.c
Normal file
271
src/crypto/randomx/defyx/KangarooTwelve.c
Normal file
|
@ -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 <string.h>
|
||||
#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);
|
||||
}
|
89
src/crypto/randomx/defyx/KangarooTwelve.h
Normal file
89
src/crypto/randomx/defyx/KangarooTwelve.h
Normal file
|
@ -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 <stddef.h>
|
||||
#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
|
41
src/crypto/randomx/defyx/KeccakP-1600-SnP.h
Normal file
41
src/crypto/randomx/defyx/KeccakP-1600-SnP.h
Normal file
|
@ -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
|
402
src/crypto/randomx/defyx/KeccakP-1600-reference.c
Normal file
402
src/crypto/randomx/defyx/KeccakP-1600-reference.c
Normal file
|
@ -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 <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#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<maxNrRounds; i++) {
|
||||
KeccakRoundConstants[i] = 0;
|
||||
for(j=0; j<7; j++) {
|
||||
bitPosition = (1<<j)-1; /* 2^j-1 */
|
||||
if (LFSR86540(&LFSRstate))
|
||||
KeccakRoundConstants[i] ^= (tKeccakLane)1<<bitPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KeccakP1600_InitializeRhoOffsets(void)
|
||||
{
|
||||
unsigned int x, y, t, newX, newY;
|
||||
|
||||
KeccakRhoOffsets[index(0, 0)] = 0;
|
||||
x = 1;
|
||||
y = 0;
|
||||
for(t=0; t<24; t++) {
|
||||
KeccakRhoOffsets[index(x, y)] = ((t+1)*(t+2)/2) % 64;
|
||||
newX = (0*x+1*y) % 5;
|
||||
newY = (2*x+3*y) % 5;
|
||||
x = newX;
|
||||
y = newY;
|
||||
}
|
||||
}
|
||||
|
||||
static int LFSR86540(UINT8 *LFSR)
|
||||
{
|
||||
int result = ((*LFSR) & 0x01) != 0;
|
||||
if (((*LFSR) & 0x80) != 0)
|
||||
/* Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1 */
|
||||
(*LFSR) = ((*LFSR) << 1) ^ 0x71;
|
||||
else
|
||||
(*LFSR) <<= 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static const tKeccakLane KeccakRoundConstants[maxNrRounds] =
|
||||
{
|
||||
0x0000000000000001,
|
||||
0x0000000000008082,
|
||||
0x800000000000808a,
|
||||
0x8000000080008000,
|
||||
0x000000000000808b,
|
||||
0x0000000080000001,
|
||||
0x8000000080008081,
|
||||
0x8000000000008009,
|
||||
0x000000000000008a,
|
||||
0x0000000000000088,
|
||||
0x0000000080008009,
|
||||
0x000000008000000a,
|
||||
0x000000008000808b,
|
||||
0x800000000000008b,
|
||||
0x8000000000008089,
|
||||
0x8000000000008003,
|
||||
0x8000000000008002,
|
||||
0x8000000000000080,
|
||||
0x000000000000800a,
|
||||
0x800000008000000a,
|
||||
0x8000000080008081,
|
||||
0x8000000000008080,
|
||||
0x0000000080000001,
|
||||
0x8000000080008008,
|
||||
};
|
||||
|
||||
static const unsigned int KeccakRhoOffsets[nrLanes] =
|
||||
{
|
||||
0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
void KeccakP1600_Initialize(void *state)
|
||||
{
|
||||
memset(state, 0, 1600/8);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
void KeccakP1600_AddByte(void *state, unsigned char byte, unsigned int offset)
|
||||
{
|
||||
assert(offset < 200);
|
||||
((unsigned char *)state)[offset] ^= byte;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
assert(offset < 200);
|
||||
assert(offset+length <= 200);
|
||||
for(i=0; i<length; i++)
|
||||
((unsigned char *)state)[offset+i] ^= data[i];
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length)
|
||||
{
|
||||
assert(offset < 200);
|
||||
assert(offset+length <= 200);
|
||||
memcpy((unsigned char*)state+offset, data, length);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount)
|
||||
{
|
||||
assert(byteCount <= 200);
|
||||
memset(state, 0, byteCount);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
void KeccakP1600OnWords(tKeccakLane *state, unsigned int nrRounds);
|
||||
void KeccakP1600Round(tKeccakLane *state, unsigned int indexRound);
|
||||
static void theta(tKeccakLane *A);
|
||||
static void rho(tKeccakLane *A);
|
||||
static void pi(tKeccakLane *A);
|
||||
static void chi(tKeccakLane *A);
|
||||
static void iota(tKeccakLane *A, unsigned int indexRound);
|
||||
|
||||
void KeccakP1600_Permute_Nrounds(void *state, unsigned int nrounds)
|
||||
{
|
||||
#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
|
||||
tKeccakLane stateAsWords[1600/64];
|
||||
#endif
|
||||
|
||||
#ifdef KeccakReference
|
||||
displayStateAsBytes(1, "Input of permutation", (const unsigned char *)state, 1600);
|
||||
#endif
|
||||
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
|
||||
KeccakP1600OnWords((tKeccakLane*)state, nrounds);
|
||||
#else
|
||||
fromBytesToWords(stateAsWords, (const unsigned char *)state);
|
||||
KeccakP1600OnWords(stateAsWords, nrounds);
|
||||
fromWordsToBytes((unsigned char *)state, stateAsWords);
|
||||
#endif
|
||||
#ifdef KeccakReference
|
||||
displayStateAsBytes(1, "State after permutation", (const unsigned char *)state, 1600);
|
||||
#endif
|
||||
}
|
||||
|
||||
void KeccakP1600_Permute_12rounds(void *state)
|
||||
{
|
||||
#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
|
||||
tKeccakLane stateAsWords[1600/64];
|
||||
#endif
|
||||
|
||||
#ifdef KeccakReference
|
||||
displayStateAsBytes(1, "Input of permutation", (const unsigned char *)state, 1600);
|
||||
#endif
|
||||
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
|
||||
KeccakP1600OnWords((tKeccakLane*)state, 12);
|
||||
#else
|
||||
fromBytesToWords(stateAsWords, (const unsigned char *)state);
|
||||
KeccakP1600OnWords(stateAsWords, 12);
|
||||
fromWordsToBytes((unsigned char *)state, stateAsWords);
|
||||
#endif
|
||||
#ifdef KeccakReference
|
||||
displayStateAsBytes(1, "State after permutation", (const unsigned char *)state, 1600);
|
||||
#endif
|
||||
}
|
||||
|
||||
void KeccakP1600_Permute_24rounds(void *state)
|
||||
{
|
||||
#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
|
||||
tKeccakLane stateAsWords[1600/64];
|
||||
#endif
|
||||
|
||||
#ifdef KeccakReference
|
||||
displayStateAsBytes(1, "Input of permutation", (const unsigned char *)state, 1600);
|
||||
#endif
|
||||
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
|
||||
KeccakP1600OnWords((tKeccakLane*)state, 24);
|
||||
#else
|
||||
fromBytesToWords(stateAsWords, (const unsigned char *)state);
|
||||
KeccakP1600OnWords(stateAsWords, 24);
|
||||
fromWordsToBytes((unsigned char *)state, stateAsWords);
|
||||
#endif
|
||||
#ifdef KeccakReference
|
||||
displayStateAsBytes(1, "State after permutation", (const unsigned char *)state, 1600);
|
||||
#endif
|
||||
}
|
||||
|
||||
void KeccakP1600OnWords(tKeccakLane *state, unsigned int nrRounds)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
#ifdef KeccakReference
|
||||
displayStateAsLanes(3, "Same, with lanes as 64-bit words", state, 1600);
|
||||
#endif
|
||||
|
||||
for(i=(maxNrRounds-nrRounds); i<maxNrRounds; i++)
|
||||
KeccakP1600Round(state, i);
|
||||
}
|
||||
|
||||
void KeccakP1600Round(tKeccakLane *state, unsigned int indexRound)
|
||||
{
|
||||
#ifdef KeccakReference
|
||||
displayRoundNumber(3, indexRound);
|
||||
#endif
|
||||
|
||||
theta(state);
|
||||
#ifdef KeccakReference
|
||||
displayStateAsLanes(3, "After theta", state, 1600);
|
||||
#endif
|
||||
|
||||
rho(state);
|
||||
#ifdef KeccakReference
|
||||
displayStateAsLanes(3, "After rho", state, 1600);
|
||||
#endif
|
||||
|
||||
pi(state);
|
||||
#ifdef KeccakReference
|
||||
displayStateAsLanes(3, "After pi", state, 1600);
|
||||
#endif
|
||||
|
||||
chi(state);
|
||||
#ifdef KeccakReference
|
||||
displayStateAsLanes(3, "After chi", state, 1600);
|
||||
#endif
|
||||
|
||||
iota(state, indexRound);
|
||||
#ifdef KeccakReference
|
||||
displayStateAsLanes(3, "After iota", state, 1600);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define ROL64(a, offset) ((offset != 0) ? ((((tKeccakLane)a) << offset) ^ (((tKeccakLane)a) >> (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<length; i++)
|
||||
output[i] = input[i] ^ ((unsigned char *)state)[offset+i];
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
void KeccakP1600_DisplayRoundConstants(FILE *f)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for(i=0; i<maxNrRounds; i++) {
|
||||
fprintf(f, "RC[%02i][0][0] = ", i);
|
||||
fprintf(f, "%08X", (unsigned int)(KeccakRoundConstants[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");
|
||||
}
|
35
src/crypto/randomx/defyx/KeccakSponge-common.h
Normal file
35
src/crypto/randomx/defyx/KeccakSponge-common.h
Normal file
|
@ -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 <string.h>
|
||||
#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
|
311
src/crypto/randomx/defyx/KeccakSponge.inc
Normal file
311
src/crypto/randomx/defyx/KeccakSponge.inc
Normal file
|
@ -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
|
54
src/crypto/randomx/defyx/KeccakSpongeWidth1600.c
Normal file
54
src/crypto/randomx/defyx/KeccakSpongeWidth1600.c
Normal file
|
@ -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
|
31
src/crypto/randomx/defyx/KeccakSpongeWidth1600.h
Normal file
31
src/crypto/randomx/defyx/KeccakSpongeWidth1600.h
Normal file
|
@ -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
|
22
src/crypto/randomx/defyx/Phases.h
Normal file
22
src/crypto/randomx/defyx/Phases.h
Normal file
|
@ -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
|
32
src/crypto/randomx/defyx/align.h
Normal file
32
src/crypto/randomx/defyx/align.h
Normal file
|
@ -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
|
143
src/crypto/randomx/defyx/brg_endian.h
Normal file
143
src/crypto/randomx/defyx/brg_endian.h
Normal file
|
@ -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 <sys/isa_defs.h>
|
||||
#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ )
|
||||
# include <sys/endian.h>
|
||||
#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \
|
||||
defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )
|
||||
# include <machine/endian.h>
|
||||
#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
|
||||
# if !defined( __MINGW32__ ) && !defined( _AIX )
|
||||
# include <endian.h>
|
||||
# if !defined( __BEOS__ )
|
||||
# include <byteswap.h>
|
||||
# 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
|
411
src/crypto/randomx/defyx/sha256.c
Normal file
411
src/crypto/randomx/defyx/sha256.c
Normal file
|
@ -0,0 +1,411 @@
|
|||
/*-
|
||||
* Copyright 2005,2007,2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "sha256.h"
|
||||
|
||||
/*
|
||||
* Encode a length len/4 vector of (uint32_t) into a length len vector of
|
||||
* (unsigned char) in big-endian form. Assumes len is a multiple of 4.
|
||||
*/
|
||||
static void
|
||||
be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len / 4; i++)
|
||||
be32enc(dst + i * 4, src[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode a big-endian length len vector of (unsigned char) into a length
|
||||
* len/4 vector of (uint32_t). Assumes len is a multiple of 4.
|
||||
*/
|
||||
static void
|
||||
be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len / 4; i++)
|
||||
dst[i] = be32dec(src + i * 4);
|
||||
}
|
||||
|
||||
/* Elementary functions used by SHA256 */
|
||||
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
|
||||
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
|
||||
#define SHR(x, n) (x >> n)
|
||||
#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
|
||||
#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
|
||||
#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
|
||||
|
||||
/* SHA256 round function */
|
||||
#define RND(a, b, c, d, e, f, g, h, k) \
|
||||
t0 = h + S1(e) + Ch(e, f, g) + k; \
|
||||
t1 = S0(a) + Maj(a, b, c); \
|
||||
d += t0; \
|
||||
h = t0 + t1;
|
||||
|
||||
/* Adjusted round function for rotating state */
|
||||
#define RNDr(S, W, i, k) \
|
||||
RND(S[(64 - i) % 8], S[(65 - i) % 8], \
|
||||
S[(66 - i) % 8], S[(67 - i) % 8], \
|
||||
S[(68 - i) % 8], S[(69 - i) % 8], \
|
||||
S[(70 - i) % 8], S[(71 - i) % 8], \
|
||||
W[i] + k)
|
||||
|
||||
/*
|
||||
* SHA256 block compression function. The 256-bit state is transformed via
|
||||
* the 512-bit input block to produce a new state.
|
||||
*/
|
||||
static void
|
||||
SHA256_Transform(uint32_t * state, const unsigned char block[64])
|
||||
{
|
||||
uint32_t W[64];
|
||||
uint32_t S[8];
|
||||
uint32_t t0, t1;
|
||||
int i;
|
||||
|
||||
/* 1. Prepare message schedule W. */
|
||||
be32dec_vect(W, block, 64);
|
||||
for (i = 16; i < 64; i++)
|
||||
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
|
||||
|
||||
/* 2. Initialize working variables. */
|
||||
memcpy(S, state, 32);
|
||||
|
||||
/* 3. Mix. */
|
||||
RNDr(S, W, 0, 0x428a2f98);
|
||||
RNDr(S, W, 1, 0x71374491);
|
||||
RNDr(S, W, 2, 0xb5c0fbcf);
|
||||
RNDr(S, W, 3, 0xe9b5dba5);
|
||||
RNDr(S, W, 4, 0x3956c25b);
|
||||
RNDr(S, W, 5, 0x59f111f1);
|
||||
RNDr(S, W, 6, 0x923f82a4);
|
||||
RNDr(S, W, 7, 0xab1c5ed5);
|
||||
RNDr(S, W, 8, 0xd807aa98);
|
||||
RNDr(S, W, 9, 0x12835b01);
|
||||
RNDr(S, W, 10, 0x243185be);
|
||||
RNDr(S, W, 11, 0x550c7dc3);
|
||||
RNDr(S, W, 12, 0x72be5d74);
|
||||
RNDr(S, W, 13, 0x80deb1fe);
|
||||
RNDr(S, W, 14, 0x9bdc06a7);
|
||||
RNDr(S, W, 15, 0xc19bf174);
|
||||
RNDr(S, W, 16, 0xe49b69c1);
|
||||
RNDr(S, W, 17, 0xefbe4786);
|
||||
RNDr(S, W, 18, 0x0fc19dc6);
|
||||
RNDr(S, W, 19, 0x240ca1cc);
|
||||
RNDr(S, W, 20, 0x2de92c6f);
|
||||
RNDr(S, W, 21, 0x4a7484aa);
|
||||
RNDr(S, W, 22, 0x5cb0a9dc);
|
||||
RNDr(S, W, 23, 0x76f988da);
|
||||
RNDr(S, W, 24, 0x983e5152);
|
||||
RNDr(S, W, 25, 0xa831c66d);
|
||||
RNDr(S, W, 26, 0xb00327c8);
|
||||
RNDr(S, W, 27, 0xbf597fc7);
|
||||
RNDr(S, W, 28, 0xc6e00bf3);
|
||||
RNDr(S, W, 29, 0xd5a79147);
|
||||
RNDr(S, W, 30, 0x06ca6351);
|
||||
RNDr(S, W, 31, 0x14292967);
|
||||
RNDr(S, W, 32, 0x27b70a85);
|
||||
RNDr(S, W, 33, 0x2e1b2138);
|
||||
RNDr(S, W, 34, 0x4d2c6dfc);
|
||||
RNDr(S, W, 35, 0x53380d13);
|
||||
RNDr(S, W, 36, 0x650a7354);
|
||||
RNDr(S, W, 37, 0x766a0abb);
|
||||
RNDr(S, W, 38, 0x81c2c92e);
|
||||
RNDr(S, W, 39, 0x92722c85);
|
||||
RNDr(S, W, 40, 0xa2bfe8a1);
|
||||
RNDr(S, W, 41, 0xa81a664b);
|
||||
RNDr(S, W, 42, 0xc24b8b70);
|
||||
RNDr(S, W, 43, 0xc76c51a3);
|
||||
RNDr(S, W, 44, 0xd192e819);
|
||||
RNDr(S, W, 45, 0xd6990624);
|
||||
RNDr(S, W, 46, 0xf40e3585);
|
||||
RNDr(S, W, 47, 0x106aa070);
|
||||
RNDr(S, W, 48, 0x19a4c116);
|
||||
RNDr(S, W, 49, 0x1e376c08);
|
||||
RNDr(S, W, 50, 0x2748774c);
|
||||
RNDr(S, W, 51, 0x34b0bcb5);
|
||||
RNDr(S, W, 52, 0x391c0cb3);
|
||||
RNDr(S, W, 53, 0x4ed8aa4a);
|
||||
RNDr(S, W, 54, 0x5b9cca4f);
|
||||
RNDr(S, W, 55, 0x682e6ff3);
|
||||
RNDr(S, W, 56, 0x748f82ee);
|
||||
RNDr(S, W, 57, 0x78a5636f);
|
||||
RNDr(S, W, 58, 0x84c87814);
|
||||
RNDr(S, W, 59, 0x8cc70208);
|
||||
RNDr(S, W, 60, 0x90befffa);
|
||||
RNDr(S, W, 61, 0xa4506ceb);
|
||||
RNDr(S, W, 62, 0xbef9a3f7);
|
||||
RNDr(S, W, 63, 0xc67178f2);
|
||||
|
||||
/* 4. Mix local working variables into global state */
|
||||
for (i = 0; i < 8; i++)
|
||||
state[i] += S[i];
|
||||
|
||||
/* Clean the stack. */
|
||||
memset(W, 0, 256);
|
||||
memset(S, 0, 32);
|
||||
t0 = t1 = 0;
|
||||
}
|
||||
|
||||
static unsigned char PAD[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/* Add padding and terminating bit-count. */
|
||||
static void
|
||||
SHA256_Pad(SHA256_CTX_Y * ctx)
|
||||
{
|
||||
unsigned char len[8];
|
||||
uint32_t r, plen;
|
||||
|
||||
/*
|
||||
* Convert length to a vector of bytes -- we do this now rather
|
||||
* than later because the length will change after we pad.
|
||||
*/
|
||||
be32enc_vect(len, ctx->count, 8);
|
||||
|
||||
/* Add 1--64 bytes so that the resulting length is 56 mod 64 */
|
||||
r = (ctx->count[1] >> 3) & 0x3f;
|
||||
plen = (r < 56) ? (56 - r) : (120 - r);
|
||||
SHA256_Update_Y(ctx, PAD, (size_t)plen);
|
||||
|
||||
/* Add the terminating bit-count */
|
||||
SHA256_Update_Y(ctx, len, 8);
|
||||
}
|
||||
|
||||
/* SHA-256 initialization. Begins a SHA-256 operation. */
|
||||
void
|
||||
SHA256_Init_Y(SHA256_CTX_Y * ctx)
|
||||
{
|
||||
|
||||
/* Zero bits processed so far */
|
||||
ctx->count[0] = ctx->count[1] = 0;
|
||||
|
||||
/* Magic initialization constants */
|
||||
ctx->state[0] = 0x6A09E667;
|
||||
ctx->state[1] = 0xBB67AE85;
|
||||
ctx->state[2] = 0x3C6EF372;
|
||||
ctx->state[3] = 0xA54FF53A;
|
||||
ctx->state[4] = 0x510E527F;
|
||||
ctx->state[5] = 0x9B05688C;
|
||||
ctx->state[6] = 0x1F83D9AB;
|
||||
ctx->state[7] = 0x5BE0CD19;
|
||||
}
|
||||
|
||||
/* Add bytes into the hash */
|
||||
void
|
||||
SHA256_Update_Y(SHA256_CTX_Y * ctx, const void *in, size_t len)
|
||||
{
|
||||
uint32_t bitlen[2];
|
||||
uint32_t r;
|
||||
const unsigned char *src = in;
|
||||
|
||||
/* Number of bytes left in the buffer from previous updates */
|
||||
r = (ctx->count[1] >> 3) & 0x3f;
|
||||
|
||||
/* Convert the length into a number of bits */
|
||||
bitlen[1] = ((uint32_t)len) << 3;
|
||||
bitlen[0] = (uint32_t)(len >> 29);
|
||||
|
||||
/* Update number of bits */
|
||||
if ((ctx->count[1] += bitlen[1]) < bitlen[1])
|
||||
ctx->count[0]++;
|
||||
ctx->count[0] += bitlen[0];
|
||||
|
||||
/* Handle the case where we don't need to perform any transforms */
|
||||
if (len < 64 - r) {
|
||||
memcpy(&ctx->buf[r], src, len);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finish the current block */
|
||||
memcpy(&ctx->buf[r], src, 64 - r);
|
||||
SHA256_Transform(ctx->state, ctx->buf);
|
||||
src += 64 - r;
|
||||
len -= 64 - r;
|
||||
|
||||
/* Perform complete blocks */
|
||||
while (len >= 64) {
|
||||
SHA256_Transform(ctx->state, src);
|
||||
src += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Copy left over data into buffer */
|
||||
memcpy(ctx->buf, src, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 finalization. Pads the input data, exports the hash value,
|
||||
* and clears the context state.
|
||||
*/
|
||||
void
|
||||
SHA256_Final_Y(unsigned char digest[32], SHA256_CTX_Y * ctx)
|
||||
{
|
||||
|
||||
/* Add padding */
|
||||
SHA256_Pad(ctx);
|
||||
|
||||
/* Write the hash */
|
||||
be32enc_vect(digest, ctx->state, 32);
|
||||
|
||||
/* Clear the context state */
|
||||
memset((void *)ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
/* Initialize an HMAC-SHA256 operation with the given key. */
|
||||
void
|
||||
HMAC_SHA256_Init_Y(HMAC_SHA256_CTX_Y * ctx, const void * _K, size_t Klen)
|
||||
{
|
||||
unsigned char pad[64];
|
||||
unsigned char khash[32];
|
||||
const unsigned char * K = _K;
|
||||
size_t i;
|
||||
|
||||
/* If Klen > 64, the key is really SHA256(K). */
|
||||
if (Klen > 64) {
|
||||
SHA256_Init_Y(&ctx->ictx);
|
||||
SHA256_Update_Y(&ctx->ictx, K, Klen);
|
||||
SHA256_Final_Y(khash, &ctx->ictx);
|
||||
K = khash;
|
||||
Klen = 32;
|
||||
}
|
||||
|
||||
/* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
|
||||
SHA256_Init_Y(&ctx->ictx);
|
||||
memset(pad, 0x36, 64);
|
||||
for (i = 0; i < Klen; i++)
|
||||
pad[i] ^= K[i];
|
||||
SHA256_Update_Y(&ctx->ictx, pad, 64);
|
||||
|
||||
/* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
|
||||
SHA256_Init_Y(&ctx->octx);
|
||||
memset(pad, 0x5c, 64);
|
||||
for (i = 0; i < Klen; i++)
|
||||
pad[i] ^= K[i];
|
||||
SHA256_Update_Y(&ctx->octx, pad, 64);
|
||||
|
||||
/* Clean the stack. */
|
||||
memset(khash, 0, 32);
|
||||
}
|
||||
|
||||
/* Add bytes to the HMAC-SHA256 operation. */
|
||||
void
|
||||
HMAC_SHA256_Update_Y(HMAC_SHA256_CTX_Y * ctx, const void *in, size_t len)
|
||||
{
|
||||
|
||||
/* Feed data to the inner SHA256 operation. */
|
||||
SHA256_Update_Y(&ctx->ictx, in, len);
|
||||
}
|
||||
|
||||
/* Finish an HMAC-SHA256 operation. */
|
||||
void
|
||||
HMAC_SHA256_Final_Y(unsigned char digest[32], HMAC_SHA256_CTX_Y * ctx)
|
||||
{
|
||||
unsigned char ihash[32];
|
||||
|
||||
/* Finish the inner SHA256 operation. */
|
||||
SHA256_Final_Y(ihash, &ctx->ictx);
|
||||
|
||||
/* Feed the inner hash to the outer SHA256 operation. */
|
||||
SHA256_Update_Y(&ctx->octx, ihash, 32);
|
||||
|
||||
/* Finish the outer SHA256 operation. */
|
||||
SHA256_Final_Y(digest, &ctx->octx);
|
||||
|
||||
/* Clean the stack. */
|
||||
memset(ihash, 0, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
|
||||
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
|
||||
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
|
||||
*/
|
||||
void
|
||||
PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
|
||||
size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
|
||||
{
|
||||
HMAC_SHA256_CTX_Y PShctx, hctx;
|
||||
size_t i;
|
||||
uint8_t ivec[4];
|
||||
uint8_t U[32];
|
||||
uint8_t T[32];
|
||||
uint64_t j;
|
||||
int k;
|
||||
size_t clen;
|
||||
|
||||
/* Compute HMAC state after processing P and S. */
|
||||
HMAC_SHA256_Init_Y(&PShctx, passwd, passwdlen);
|
||||
HMAC_SHA256_Update_Y(&PShctx, salt, saltlen);
|
||||
|
||||
/* Iterate through the blocks. */
|
||||
for (i = 0; i * 32 < dkLen; i++) {
|
||||
/* Generate INT(i + 1). */
|
||||
be32enc(ivec, (uint32_t)(i + 1));
|
||||
|
||||
/* Compute U_1 = PRF(P, S || INT(i)). */
|
||||
memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX_Y));
|
||||
HMAC_SHA256_Update_Y(&hctx, ivec, 4);
|
||||
HMAC_SHA256_Final_Y(U, &hctx);
|
||||
|
||||
/* T_i = U_1 ... */
|
||||
memcpy(T, U, 32);
|
||||
|
||||
for (j = 2; j <= c; j++) {
|
||||
/* Compute U_j. */
|
||||
HMAC_SHA256_Init_Y(&hctx, passwd, passwdlen);
|
||||
HMAC_SHA256_Update_Y(&hctx, U, 32);
|
||||
HMAC_SHA256_Final_Y(U, &hctx);
|
||||
|
||||
/* ... xor U_j ... */
|
||||
for (k = 0; k < 32; k++)
|
||||
T[k] ^= U[k];
|
||||
}
|
||||
|
||||
/* Copy as many bytes as necessary into buf. */
|
||||
clen = dkLen - i * 32;
|
||||
if (clen > 32)
|
||||
clen = 32;
|
||||
memcpy(&buf[i * 32], T, clen);
|
||||
}
|
||||
|
||||
/* Clean PShctx, since we never called _Final on it. */
|
||||
memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX_Y));
|
||||
}
|
62
src/crypto/randomx/defyx/sha256.h
Normal file
62
src/crypto/randomx/defyx/sha256.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*-
|
||||
* Copyright 2005,2007,2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/lib/libmd/sha256_Y.h,v 1.2 2006/01/17 15:35:56 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SHA256_H_
|
||||
#define _SHA256_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct SHA256Context {
|
||||
uint32_t state[8];
|
||||
uint32_t count[2];
|
||||
unsigned char buf[64];
|
||||
} SHA256_CTX_Y;
|
||||
|
||||
typedef struct HMAC_SHA256Context {
|
||||
SHA256_CTX_Y ictx;
|
||||
SHA256_CTX_Y octx;
|
||||
} HMAC_SHA256_CTX_Y;
|
||||
|
||||
void SHA256_Init_Y(SHA256_CTX_Y *);
|
||||
void SHA256_Update_Y(SHA256_CTX_Y *, const void *, size_t);
|
||||
void SHA256_Final_Y(unsigned char [32], SHA256_CTX_Y *);
|
||||
void HMAC_SHA256_Init_Y(HMAC_SHA256_CTX_Y *, const void *, size_t);
|
||||
void HMAC_SHA256_Update_Y(HMAC_SHA256_CTX_Y *, const void *, size_t);
|
||||
void HMAC_SHA256_Final_Y(unsigned char [32], HMAC_SHA256_CTX_Y *);
|
||||
|
||||
/**
|
||||
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
|
||||
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
|
||||
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
|
||||
*/
|
||||
void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t,
|
||||
uint64_t, uint8_t *, size_t);
|
||||
|
||||
#endif /* !_SHA256_H_ */
|
138
src/crypto/randomx/defyx/sysendian.h
Normal file
138
src/crypto/randomx/defyx/sysendian.h
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*-
|
||||
* Copyright 2007-2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#ifndef _SYSENDIAN_H_
|
||||
#define _SYSENDIAN_H_
|
||||
|
||||
/* If we don't have be64enc, the <sys/endian.h> we have isn't usable. */
|
||||
#if !HAVE_DECL_BE64ENC
|
||||
#undef HAVE_SYS_ENDIAN_H
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_ENDIAN_H
|
||||
|
||||
#include <sys/endian.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint32_t
|
||||
be32dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
|
||||
((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
|
||||
}
|
||||
|
||||
static inline void
|
||||
be32enc(void *pp, uint32_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[3] = x & 0xff;
|
||||
p[2] = (x >> 8) & 0xff;
|
||||
p[1] = (x >> 16) & 0xff;
|
||||
p[0] = (x >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
be64dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) +
|
||||
((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) +
|
||||
((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) +
|
||||
((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56));
|
||||
}
|
||||
|
||||
static inline void
|
||||
be64enc(void *pp, uint64_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[7] = x & 0xff;
|
||||
p[6] = (x >> 8) & 0xff;
|
||||
p[5] = (x >> 16) & 0xff;
|
||||
p[4] = (x >> 24) & 0xff;
|
||||
p[3] = (x >> 32) & 0xff;
|
||||
p[2] = (x >> 40) & 0xff;
|
||||
p[1] = (x >> 48) & 0xff;
|
||||
p[0] = (x >> 56) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
le32dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
|
||||
((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
|
||||
}
|
||||
|
||||
static inline void
|
||||
le32enc(void *pp, uint32_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[0] = x & 0xff;
|
||||
p[1] = (x >> 8) & 0xff;
|
||||
p[2] = (x >> 16) & 0xff;
|
||||
p[3] = (x >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
le64dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) +
|
||||
((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) +
|
||||
((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) +
|
||||
((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56));
|
||||
}
|
||||
|
||||
static inline void
|
||||
le64enc(void *pp, uint64_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[0] = x & 0xff;
|
||||
p[1] = (x >> 8) & 0xff;
|
||||
p[2] = (x >> 16) & 0xff;
|
||||
p[3] = (x >> 24) & 0xff;
|
||||
p[4] = (x >> 32) & 0xff;
|
||||
p[5] = (x >> 40) & 0xff;
|
||||
p[6] = (x >> 48) & 0xff;
|
||||
p[7] = (x >> 56) & 0xff;
|
||||
}
|
||||
#endif /* !HAVE_SYS_ENDIAN_H */
|
||||
|
||||
#endif /* !_SYSENDIAN_H_ */
|
5
src/crypto/randomx/defyx/yescrypt-best.c
Normal file
5
src/crypto/randomx/defyx/yescrypt-best.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#ifdef __SSE2__
|
||||
#include "yescrypt-simd.c"
|
||||
#else
|
||||
#include "yescrypt-opt.c"
|
||||
#endif
|
1102
src/crypto/randomx/defyx/yescrypt-opt.c
Normal file
1102
src/crypto/randomx/defyx/yescrypt-opt.c
Normal file
File diff suppressed because it is too large
Load diff
195
src/crypto/randomx/defyx/yescrypt-platform.c
Normal file
195
src/crypto/randomx/defyx/yescrypt-platform.c
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*-
|
||||
* Copyright 2013-2015 Alexander Peslyak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef __unix
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "yescrypt.h"
|
||||
|
||||
#define HUGEPAGE_THRESHOLD (12 * 1024 * 1024)
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define HUGEPAGE_SIZE (2 * 1024 * 1024)
|
||||
#else
|
||||
#undef HUGEPAGE_SIZE
|
||||
#endif
|
||||
|
||||
static void *
|
||||
alloc_region(yescrypt_region_t * region, size_t size)
|
||||
{
|
||||
size_t base_size = size;
|
||||
uint8_t * base, * aligned;
|
||||
#ifdef MAP_ANON
|
||||
int flags =
|
||||
#ifdef MAP_NOCORE
|
||||
MAP_NOCORE |
|
||||
#endif
|
||||
MAP_ANON | MAP_PRIVATE;
|
||||
#if defined(MAP_HUGETLB) && defined(HUGEPAGE_SIZE)
|
||||
size_t new_size = size;
|
||||
const size_t hugepage_mask = (size_t)HUGEPAGE_SIZE - 1;
|
||||
if (size >= HUGEPAGE_THRESHOLD && size + hugepage_mask >= size) {
|
||||
flags |= MAP_HUGETLB;
|
||||
/*
|
||||
* Linux's munmap() fails on MAP_HUGETLB mappings if size is not a multiple of
|
||||
* huge page size, so let's round up to huge page size here.
|
||||
*/
|
||||
new_size = size + hugepage_mask;
|
||||
new_size &= ~hugepage_mask;
|
||||
}
|
||||
base = mmap(NULL, new_size, PROT_READ | PROT_WRITE, flags, -1, 0);
|
||||
if (base != MAP_FAILED) {
|
||||
base_size = new_size;
|
||||
} else
|
||||
if (flags & MAP_HUGETLB) {
|
||||
flags &= ~MAP_HUGETLB;
|
||||
base = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0);
|
||||
}
|
||||
|
||||
#else
|
||||
base = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0);
|
||||
#endif
|
||||
if (base == MAP_FAILED)
|
||||
base = NULL;
|
||||
aligned = base;
|
||||
#elif defined(HAVE_POSIX_MEMALIGN)
|
||||
if ((errno = posix_memalign((void **)&base, 64, size)) != 0)
|
||||
base = NULL;
|
||||
aligned = base;
|
||||
#else
|
||||
base = aligned = NULL;
|
||||
if (size + 63 < size) {
|
||||
//errno = ENOMEM;
|
||||
} else if ((base = malloc(size + 63)) != NULL) {
|
||||
aligned = base + 63;
|
||||
aligned -= (uintptr_t)aligned & 63;
|
||||
}
|
||||
#endif
|
||||
region->base = base;
|
||||
region->aligned = aligned;
|
||||
region->base_size = base ? base_size : 0;
|
||||
region->aligned_size = base ? size : 0;
|
||||
return aligned;
|
||||
}
|
||||
|
||||
static inline void
|
||||
init_region(yescrypt_region_t * region)
|
||||
{
|
||||
region->base = region->aligned = NULL;
|
||||
region->base_size = region->aligned_size = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
free_region(yescrypt_region_t * region)
|
||||
{
|
||||
if (region->base) {
|
||||
#ifdef MAP_ANON
|
||||
if (munmap(region->base, region->base_size))
|
||||
return -1;
|
||||
#else
|
||||
free(region->base);
|
||||
#endif
|
||||
}
|
||||
init_region(region);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
yescrypt_init_shared(yescrypt_shared_t * shared,
|
||||
const uint8_t * param, size_t paramlen,
|
||||
uint64_t N, uint32_t r, uint32_t p,
|
||||
yescrypt_init_shared_flags_t flags,
|
||||
uint8_t * buf, size_t buflen)
|
||||
{
|
||||
yescrypt_shared_t half1, half2;
|
||||
uint8_t salt[32];
|
||||
|
||||
if (flags & YESCRYPT_SHARED_PREALLOCATED) {
|
||||
if (!shared->aligned || !shared->aligned_size)
|
||||
return -1;
|
||||
} else {
|
||||
init_region(shared);
|
||||
}
|
||||
if (!param && !paramlen && !N && !r && !p && !buf && !buflen)
|
||||
return 0;
|
||||
|
||||
if (yescrypt_kdf(NULL, shared,
|
||||
param, paramlen, NULL, 0, N, r, p, 0, 0,
|
||||
YESCRYPT_RW | __YESCRYPT_INIT_SHARED_1,
|
||||
salt, sizeof(salt)))
|
||||
goto out;
|
||||
|
||||
half1 = half2 = *shared;
|
||||
half1.aligned_size /= 2;
|
||||
#ifdef _MSC_VER
|
||||
(uint8_t*)half2.aligned += half1.aligned_size;
|
||||
#else
|
||||
half2.aligned += half1.aligned_size;
|
||||
#endif
|
||||
half2.aligned_size = half1.aligned_size;
|
||||
N /= 2;
|
||||
|
||||
if (p > 1 && yescrypt_kdf(&half1, &half2,
|
||||
param, paramlen, salt, sizeof(salt), N, r, p, 0, 0,
|
||||
YESCRYPT_RW | __YESCRYPT_INIT_SHARED_2,
|
||||
salt, sizeof(salt)))
|
||||
goto out;
|
||||
|
||||
if (yescrypt_kdf(&half2, &half1,
|
||||
param, paramlen, salt, sizeof(salt), N, r, p, 0, 0,
|
||||
YESCRYPT_RW | __YESCRYPT_INIT_SHARED_1,
|
||||
salt, sizeof(salt)))
|
||||
goto out;
|
||||
|
||||
if (yescrypt_kdf(&half1, &half2,
|
||||
param, paramlen, salt, sizeof(salt), N, r, p, 0, 0,
|
||||
YESCRYPT_RW | __YESCRYPT_INIT_SHARED_1,
|
||||
buf, buflen))
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
if (!(flags & YESCRYPT_SHARED_PREALLOCATED))
|
||||
free_region(shared);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
yescrypt_free_shared(yescrypt_shared_t * shared)
|
||||
{
|
||||
return free_region(shared);
|
||||
}
|
||||
|
||||
int
|
||||
yescrypt_init_local(yescrypt_local_t * local)
|
||||
{
|
||||
init_region(local);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
yescrypt_free_local(yescrypt_local_t * local)
|
||||
{
|
||||
return free_region(local);
|
||||
}
|
880
src/crypto/randomx/defyx/yescrypt-ref.c
Normal file
880
src/crypto/randomx/defyx/yescrypt-ref.c
Normal file
|
@ -0,0 +1,880 @@
|
|||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* Copyright 2013-2015 Alexander Peslyak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*
|
||||
* This is the reference implementation. Its purpose is to provide a simple
|
||||
* human- and machine-readable specification that implementations intended
|
||||
* for actual use should be tested against. It is deliberately mostly not
|
||||
* optimized, and it is not meant to be used in production. Instead, use
|
||||
* yescrypt-best.c or one of the source files included from there.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sha256.h"
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "yescrypt.h"
|
||||
|
||||
static void
|
||||
blkcpy(uint32_t * dest, const uint32_t * src, size_t count)
|
||||
{
|
||||
do {
|
||||
*dest++ = *src++;
|
||||
} while (--count);
|
||||
}
|
||||
|
||||
static void
|
||||
blkxor(uint32_t * dest, const uint32_t * src, size_t count)
|
||||
{
|
||||
do {
|
||||
*dest++ ^= *src++;
|
||||
} while (--count);
|
||||
}
|
||||
|
||||
/**
|
||||
* salsa20(B):
|
||||
* Apply the Salsa20 core to the provided block.
|
||||
*/
|
||||
static void
|
||||
salsa20(uint32_t B[16], uint32_t rounds)
|
||||
{
|
||||
uint32_t x[16];
|
||||
size_t i;
|
||||
|
||||
/* SIMD unshuffle */
|
||||
for (i = 0; i < 16; i++)
|
||||
x[i * 5 % 16] = B[i];
|
||||
|
||||
for (i = 0; i < rounds; i += 2) {
|
||||
#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
|
||||
/* Operate on columns */
|
||||
x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
|
||||
x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
|
||||
|
||||
x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
|
||||
x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
|
||||
|
||||
x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
|
||||
x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
|
||||
|
||||
x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
|
||||
x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
|
||||
|
||||
/* Operate on rows */
|
||||
x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
|
||||
x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
|
||||
|
||||
x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
|
||||
x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
|
||||
|
||||
x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
|
||||
x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
|
||||
|
||||
x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
|
||||
x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
|
||||
#undef R
|
||||
}
|
||||
|
||||
/* SIMD shuffle */
|
||||
for (i = 0; i < 16; i++)
|
||||
B[i] += x[i * 5 % 16];
|
||||
}
|
||||
|
||||
/**
|
||||
* blockmix_salsa8(B, Y, r):
|
||||
* Compute B = BlockMix_{salsa20/8, r}(B). The input B must be 128r bytes in
|
||||
* length; the temporary space Y must also be the same size.
|
||||
*/
|
||||
static void
|
||||
blockmix_salsa8(uint32_t * B, uint32_t * Y, size_t r)
|
||||
{
|
||||
uint32_t X[16];
|
||||
size_t i;
|
||||
|
||||
/* 1: X <-- B_{2r - 1} */
|
||||
blkcpy(X, &B[(2 * r - 1) * 16], 16);
|
||||
|
||||
/* 2: for i = 0 to 2r - 1 do */
|
||||
for (i = 0; i < 2 * r; i++) {
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
blkxor(X, &B[i * 16], 16);
|
||||
salsa20(X, 8);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
blkcpy(&Y[i * 16], X, 16);
|
||||
}
|
||||
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
for (i = 0; i < r; i++)
|
||||
blkcpy(&B[i * 16], &Y[(i * 2) * 16], 16);
|
||||
for (i = 0; i < r; i++)
|
||||
blkcpy(&B[(i + r) * 16], &Y[(i * 2 + 1) * 16], 16);
|
||||
}
|
||||
|
||||
/* These are tunable */
|
||||
#define PWXsimple 2
|
||||
#define PWXgather 4
|
||||
#define PWXrounds 6
|
||||
#define Swidth 8
|
||||
|
||||
/* Derived values. Not tunable on their own. */
|
||||
#define PWXbytes (PWXgather * PWXsimple * 8)
|
||||
#define PWXwords (PWXbytes / sizeof(uint32_t))
|
||||
#define Sbytes (3 * (1 << Swidth) * PWXsimple * 8)
|
||||
#define Swords (Sbytes / sizeof(uint32_t))
|
||||
#define Smask (((1 << Swidth) - 1) * PWXsimple * 8)
|
||||
#define rmin ((PWXbytes + 127) / 128)
|
||||
|
||||
typedef struct {
|
||||
uint32_t *S;
|
||||
uint32_t (*S0)[2], (*S1)[2], (*S2)[2];
|
||||
size_t w;
|
||||
} pwxform_ctx_t;
|
||||
|
||||
/**
|
||||
* pwxform(B):
|
||||
* Transform the provided block using the provided S-boxes.
|
||||
*/
|
||||
static void
|
||||
pwxform(uint32_t * B, pwxform_ctx_t * ctx)
|
||||
{
|
||||
uint32_t (*X)[PWXsimple][2] = (uint32_t (*)[PWXsimple][2])B;
|
||||
uint32_t (*S0)[2] = ctx->S0, (*S1)[2] = ctx->S1, (*S2)[2] = ctx->S2;
|
||||
size_t w = ctx->w;
|
||||
size_t i, j, k;
|
||||
|
||||
/* 1: for i = 0 to PWXrounds - 1 do */
|
||||
for (i = 0; i < PWXrounds; i++) {
|
||||
/* 2: for j = 0 to PWXgather - 1 do */
|
||||
for (j = 0; j < PWXgather; j++) {
|
||||
uint32_t xl = X[j][0][0];
|
||||
uint32_t xh = X[j][0][1];
|
||||
uint32_t (*p0)[2], (*p1)[2];
|
||||
|
||||
/* 3: p0 <-- (lo(B_{j,0}) & Smask) / (PWXsimple * 8) */
|
||||
p0 = S0 + (xl & Smask) / sizeof(*S0);
|
||||
/* 4: p1 <-- (hi(B_{j,0}) & Smask) / (PWXsimple * 8) */
|
||||
p1 = S1 + (xh & Smask) / sizeof(*S1);
|
||||
|
||||
/* 5: for k = 0 to PWXsimple - 1 do */
|
||||
for (k = 0; k < PWXsimple; k++) {
|
||||
uint64_t x, s0, s1;
|
||||
|
||||
/* 6: B_{j,k} <-- (hi(B_{j,k}) * lo(B_{j,k}) + S0_{p0,k}) \xor S1_{p1,k} */
|
||||
s0 = ((uint64_t)p0[k][1] << 32) + p0[k][0];
|
||||
s1 = ((uint64_t)p1[k][1] << 32) + p1[k][0];
|
||||
|
||||
xl = X[j][k][0];
|
||||
xh = X[j][k][1];
|
||||
|
||||
x = (uint64_t)xh * xl;
|
||||
x += s0;
|
||||
x ^= s1;
|
||||
|
||||
X[j][k][0] = x;
|
||||
X[j][k][1] = x >> 32;
|
||||
|
||||
/* 8: if (i != 0) and (i != PWXrounds - 1) */
|
||||
if (i != 0 && i != PWXrounds - 1) {
|
||||
/* 9: S2_w <-- B_j */
|
||||
S2[w][0] = x;
|
||||
S2[w][1] = x >> 32;
|
||||
/* 10: w <-- w + 1 */
|
||||
w++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 14: (S0, S1, S2) <-- (S2, S0, S1) */
|
||||
ctx->S0 = S2;
|
||||
ctx->S1 = S0;
|
||||
ctx->S2 = S1;
|
||||
/* 15: w <-- w mod 2^Swidth */
|
||||
ctx->w = w & ((1 << Swidth) * PWXsimple - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* blockmix_pwxform(B, Y, ctx, r):
|
||||
* Compute B = BlockMix_pwxform{salsa20/2, ctx, r}(B). The input B must be 128r
|
||||
* bytes in length; the temporary space Y must be at least PWXbytes.
|
||||
*/
|
||||
static void
|
||||
blockmix_pwxform(uint32_t * B, uint32_t * Y, pwxform_ctx_t * ctx, size_t r)
|
||||
{
|
||||
size_t r1, i;
|
||||
|
||||
/* Convert 128-byte blocks to PWXbytes blocks */
|
||||
/* 1: r_1 <-- 128r / PWXbytes */
|
||||
r1 = 128 * r / PWXbytes;
|
||||
|
||||
/* 2: X <-- B'_{r_1 - 1} */
|
||||
blkcpy(Y, &B[(r1 - 1) * PWXwords], PWXwords);
|
||||
|
||||
/* 3: for i = 0 to r_1 - 1 do */
|
||||
for (i = 0; i < r1; i++) {
|
||||
/* 4: if r_1 > 1 */
|
||||
if (r1 > 1) {
|
||||
/* 5: X <-- X \xor B'_i */
|
||||
blkxor(Y, &B[i * PWXwords], PWXwords);
|
||||
}
|
||||
|
||||
/* 7: X <-- pwxform(X) */
|
||||
pwxform(Y, ctx);
|
||||
|
||||
/* 8: B'_i <-- X */
|
||||
blkcpy(&B[i * PWXwords], Y, PWXwords);
|
||||
}
|
||||
|
||||
/* 10: i <-- floor((r_1 - 1) * PWXbytes / 64) */
|
||||
i = (r1 - 1) * PWXbytes / 64;
|
||||
|
||||
/* 11: B_i <-- H(B_i) */
|
||||
salsa20(&B[i * 16], 2);
|
||||
|
||||
/* 12: for i = i + 1 to 2r - 1 do */
|
||||
for (i++; i < 2 * r; i++) {
|
||||
/* 13: B_i <-- H(B_i \xor B_{i-1}) */
|
||||
blkxor(&B[i * 16], &B[(i - 1) * 16], 16);
|
||||
salsa20(&B[i * 16], 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* integerify(B, r):
|
||||
* Return the result of parsing B_{2r-1} as a little-endian integer.
|
||||
*/
|
||||
static uint64_t
|
||||
integerify(const uint32_t * B, size_t r)
|
||||
{
|
||||
/*
|
||||
* Our 32-bit words are in host byte order, and word 13 is the second word of
|
||||
* B_{2r-1} due to SIMD shuffling. The 64-bit value we return is also in host
|
||||
* byte order, as it should be.
|
||||
*/
|
||||
const uint32_t * X = &B[(2 * r - 1) * 16];
|
||||
return ((uint64_t)X[13] << 32) + X[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* p2floor(x):
|
||||
* Largest power of 2 not greater than argument.
|
||||
*/
|
||||
static uint64_t
|
||||
p2floor(uint64_t x)
|
||||
{
|
||||
uint64_t y;
|
||||
while ((y = x & (x - 1)))
|
||||
x = y;
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* wrap(x, i):
|
||||
* Wrap x to the range 0 to i-1.
|
||||
*/
|
||||
static uint64_t
|
||||
wrap(uint64_t x, uint64_t i)
|
||||
{
|
||||
uint64_t n = p2floor(i);
|
||||
return (x & (n - 1)) + (i - n);
|
||||
}
|
||||
|
||||
/**
|
||||
* smix1(B, r, N, flags, V, NROM, VROM, XY, ctx):
|
||||
* Compute first loop of B = SMix_r(B, N). The input B must be 128r bytes in
|
||||
* length; the temporary storage V must be 128rN bytes in length; the temporary
|
||||
* storage XY must be 256r bytes in length.
|
||||
*/
|
||||
static void
|
||||
smix1(uint32_t * B, size_t r, uint64_t N, yescrypt_flags_t flags,
|
||||
uint32_t * V, uint64_t NROM, const uint32_t * VROM,
|
||||
uint32_t * XY, pwxform_ctx_t * ctx)
|
||||
{
|
||||
size_t s = 32 * r;
|
||||
uint32_t * X = XY;
|
||||
uint32_t * Y = &XY[s];
|
||||
uint64_t i, j;
|
||||
size_t k;
|
||||
|
||||
/* 1: X <-- B */
|
||||
for (k = 0; k < 2 * r; k++)
|
||||
for (i = 0; i < 16; i++)
|
||||
X[k * 16 + i] = le32dec(&B[k * 16 + (i * 5 % 16)]);
|
||||
|
||||
/* 2: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i++) {
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy(&V[i * s], X, s);
|
||||
|
||||
if (VROM && (i & 1)) {
|
||||
/* j <-- Integerify(X) mod NROM */
|
||||
j = integerify(X, r) & (NROM - 1);
|
||||
|
||||
/* X <-- H(X \xor VROM_j) */
|
||||
blkxor(X, &VROM[j * s], s);
|
||||
} else if ((flags & YESCRYPT_RW) && i > 1) {
|
||||
/* j <-- Wrap(Integerify(X), i) */
|
||||
j = wrap(integerify(X, r), i);
|
||||
|
||||
/* X <-- X \xor V_j */
|
||||
blkxor(X, &V[j * s], s);
|
||||
}
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
if (ctx)
|
||||
blockmix_pwxform(X, Y, ctx, r);
|
||||
else
|
||||
blockmix_salsa8(X, Y, r);
|
||||
}
|
||||
|
||||
/* B' <-- X */
|
||||
for (k = 0; k < 2 * r; k++)
|
||||
for (i = 0; i < 16; i++)
|
||||
le32enc(&B[k * 16 + (i * 5 % 16)], X[k * 16 + i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* smix2(B, r, N, Nloop, flags, V, NROM, VROM, XY, ctx):
|
||||
* Compute second loop of B = SMix_r(B, N). The input B must be 128r bytes in
|
||||
* length; the temporary storage V must be 128rN bytes in length; the temporary
|
||||
* storage XY must be 256r bytes in length. The value N must be a power of 2
|
||||
* greater than 1.
|
||||
*/
|
||||
static void
|
||||
smix2(uint32_t * B, size_t r, uint64_t N, uint64_t Nloop,
|
||||
yescrypt_flags_t flags, uint32_t * V, uint64_t NROM,
|
||||
const uint32_t * VROM, uint32_t * XY, pwxform_ctx_t * ctx)
|
||||
{
|
||||
size_t s = 32 * r;
|
||||
uint32_t * X = XY;
|
||||
uint32_t * Y = &XY[s];
|
||||
uint64_t i, j;
|
||||
size_t k;
|
||||
|
||||
/* X <-- B */
|
||||
for (k = 0; k < 2 * r; k++)
|
||||
for (i = 0; i < 16; i++)
|
||||
X[k * 16 + i] = le32dec(&B[k * 16 + (i * 5 % 16)]);
|
||||
|
||||
/* 6: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < Nloop; i++) {
|
||||
if (VROM && (i & 1)) {
|
||||
/* j <-- Integerify(X) mod NROM */
|
||||
j = integerify(X, r) & (NROM - 1);
|
||||
|
||||
/* X <-- H(X \xor VROM_j) */
|
||||
blkxor(X, &VROM[j * s], s);
|
||||
} else {
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(X, r) & (N - 1);
|
||||
|
||||
/* 8.1: X <-- X \xor V_j */
|
||||
blkxor(X, &V[j * s], s);
|
||||
/* V_j <-- X */
|
||||
if (flags & YESCRYPT_RW)
|
||||
blkcpy(&V[j * s], X, s);
|
||||
}
|
||||
|
||||
/* 8.2: X <-- H(X) */
|
||||
if (ctx)
|
||||
blockmix_pwxform(X, Y, ctx, r);
|
||||
else
|
||||
blockmix_salsa8(X, Y, r);
|
||||
}
|
||||
|
||||
/* 10: B' <-- X */
|
||||
for (k = 0; k < 2 * r; k++)
|
||||
for (i = 0; i < 16; i++)
|
||||
le32enc(&B[k * 16 + (i * 5 % 16)], X[k * 16 + i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* smix(B, r, N, p, t, flags, V, NROM, VROM, XY, ctx, passwd):
|
||||
* Compute B = SMix_r(B, N). The input B must be 128rp bytes in length; the
|
||||
* temporary storage V must be 128rN bytes in length; the temporary storage
|
||||
* XY must be 256r bytes in length. The value N must be a power of 2 greater
|
||||
* than 1.
|
||||
*/
|
||||
static void
|
||||
smix(uint32_t * B, size_t r, uint64_t N, uint32_t p, uint32_t t,
|
||||
yescrypt_flags_t flags,
|
||||
uint32_t * V, uint64_t NROM, const uint32_t * VROM,
|
||||
uint32_t * XY, pwxform_ctx_t * ctx, uint8_t * passwd)
|
||||
{
|
||||
size_t s = 32 * r;
|
||||
uint64_t Nchunk, Nloop_all, Nloop_rw, Vchunk;
|
||||
uint32_t i;
|
||||
|
||||
/* 1: n <-- N / p */
|
||||
Nchunk = N / p;
|
||||
|
||||
/* 2: Nloop_all <-- fNloop(n, t, flags) */
|
||||
Nloop_all = Nchunk;
|
||||
if (flags & YESCRYPT_RW) {
|
||||
if (t <= 1) {
|
||||
if (t)
|
||||
Nloop_all *= 2; /* 2/3 */
|
||||
Nloop_all = (Nloop_all + 2) / 3; /* 1/3, round up */
|
||||
} else {
|
||||
Nloop_all *= t - 1;
|
||||
}
|
||||
} else if (t) {
|
||||
if (t == 1)
|
||||
Nloop_all += (Nloop_all + 1) / 2; /* 1.5, round up */
|
||||
Nloop_all *= t;
|
||||
}
|
||||
|
||||
/* 6: Nloop_rw <-- 0 */
|
||||
Nloop_rw = 0;
|
||||
if (flags & __YESCRYPT_INIT_SHARED) {
|
||||
Nloop_rw = Nloop_all;
|
||||
} else {
|
||||
/* 3: if YESCRYPT_RW flag is set */
|
||||
if (flags & YESCRYPT_RW) {
|
||||
/* 4: Nloop_rw <-- Nloop_all / p */
|
||||
Nloop_rw = Nloop_all / p;
|
||||
}
|
||||
}
|
||||
|
||||
/* 8: n <-- n - (n mod 2) */
|
||||
Nchunk &= ~(uint64_t)1; /* round down to even */
|
||||
/* 9: Nloop_all <-- Nloop_all + (Nloop_all mod 2) */
|
||||
Nloop_all++; Nloop_all &= ~(uint64_t)1; /* round up to even */
|
||||
/* 10: Nloop_rw <-- Nloop_rw + (Nloop_rw mod 2) */
|
||||
Nloop_rw++; Nloop_rw &= ~(uint64_t)1; /* round up to even */
|
||||
|
||||
/* 11: for i = 0 to p - 1 do */
|
||||
/* 12: u <-- in */
|
||||
for (i = 0, Vchunk = 0; i < p; i++, Vchunk += Nchunk) {
|
||||
/* 13: if i = p - 1 */
|
||||
/* 14: n <-- N - u */
|
||||
/* 15: end if */
|
||||
/* 16: v <-- u + n - 1 */
|
||||
uint64_t Np = (i < p - 1) ? Nchunk : (N - Vchunk);
|
||||
uint32_t * Bp = &B[i * s];
|
||||
uint32_t * Vp = &V[Vchunk * s];
|
||||
pwxform_ctx_t * ctx_i = NULL;
|
||||
/* 17: if YESCRYPT_RW flag is set */
|
||||
if (flags & YESCRYPT_RW) {
|
||||
ctx_i = &ctx[i];
|
||||
/* 18: SMix1_1(B_i, Sbytes / 128, S_i, no flags) */
|
||||
smix1(Bp, 1, Sbytes / 128, 0 /* no flags */,
|
||||
ctx_i->S, 0, NULL, XY, NULL);
|
||||
/* 19: S2_i <-- S_{i,0...2^Swidth-1} */
|
||||
ctx_i->S2 = (uint32_t (*)[2])ctx_i->S;
|
||||
/* 20: S1_i <-- S_{i,2^Swidth...2*2^Swidth-1} */
|
||||
ctx_i->S1 = ctx_i->S2 + (1 << Swidth) * PWXsimple;
|
||||
/* 21: S0_i <-- S_{i,2*2^Swidth...3*2^Swidth-1} */
|
||||
ctx_i->S0 = ctx_i->S1 + (1 << Swidth) * PWXsimple;
|
||||
/* 22: w_i <-- 0 */
|
||||
ctx_i->w = 0;
|
||||
/* 23: if i = 0 */
|
||||
if (i == 0) {
|
||||
/* 24: passwd <-- HMAC-SHA256(B_{0,2r-1}, passwd) */
|
||||
HMAC_SHA256_CTX_Y ctx;
|
||||
HMAC_SHA256_Init_Y(&ctx, Bp + (s - 16), 64);
|
||||
HMAC_SHA256_Update_Y(&ctx, passwd, 32);
|
||||
HMAC_SHA256_Final_Y(passwd, &ctx);
|
||||
}
|
||||
}
|
||||
if (!(flags & __YESCRYPT_INIT_SHARED_2)) {
|
||||
/* 27: SMix1_r(B_i, n, V_{u..v}, flags) */
|
||||
smix1(Bp, r, Np, flags, Vp, NROM, VROM, XY, ctx_i);
|
||||
}
|
||||
/* 28: SMix2_r(B_i, p2floor(n), Nloop_rw, V_{u..v}, flags) */
|
||||
smix2(Bp, r, p2floor(Np), Nloop_rw, flags, Vp,
|
||||
NROM, VROM, XY, ctx_i);
|
||||
}
|
||||
|
||||
/* 30: for i = 0 to p - 1 do */
|
||||
for (i = 0; i < p; i++) {
|
||||
uint32_t * Bp = &B[i * s];
|
||||
/* 31: SMix2_r(B_i, N, Nloop_all - Nloop_rw, V, flags excluding YESCRYPT_RW) */
|
||||
smix2(Bp, r, N, Nloop_all - Nloop_rw, flags & ~YESCRYPT_RW,
|
||||
V, NROM, VROM, XY, (flags & YESCRYPT_RW) ? &ctx[i] : NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* yescrypt_kdf_body(shared, local, passwd, passwdlen, salt, saltlen,
|
||||
* N, r, p, t, flags, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen), or a revision of scrypt as requested by flags and shared, and
|
||||
* write the result into buf. The parameters r, p, and buflen must satisfy
|
||||
* r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N must be a power
|
||||
* of 2 greater than 1.
|
||||
*
|
||||
* t controls computation time while not affecting peak memory usage. shared
|
||||
* and flags may request special modes as described in yescrypt.h. local is
|
||||
* the thread-local data structure, allowing optimized implementations to
|
||||
* preserve and reuse a memory allocation across calls, thereby reducing its
|
||||
* overhead (this reference implementation does not make that optimization).
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*/
|
||||
static int
|
||||
yescrypt_kdf_body(const yescrypt_shared_t * shared, yescrypt_local_t * local,
|
||||
const uint8_t * passwd, size_t passwdlen,
|
||||
const uint8_t * salt, size_t saltlen,
|
||||
uint64_t N, uint32_t r, uint32_t p, uint32_t t, yescrypt_flags_t flags,
|
||||
uint8_t * buf, size_t buflen)
|
||||
{
|
||||
int retval = -1;
|
||||
uint64_t NROM;
|
||||
const uint32_t * VROM;
|
||||
size_t B_size, V_size;
|
||||
uint32_t * B, * V, * XY, * S;
|
||||
pwxform_ctx_t * pwxform_ctx;
|
||||
uint32_t sha256[8];
|
||||
uint8_t dk[sizeof(sha256)], * dkp = buf;
|
||||
uint32_t i;
|
||||
|
||||
/* Sanity-check parameters */
|
||||
if ((flags & ~YESCRYPT_KNOWN_FLAGS) || (!flags && t)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
|
||||
errno = EFBIG;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
|
||||
errno = EFBIG;
|
||||
return -1;
|
||||
}
|
||||
if (((N & (N - 1)) != 0) || (N <= 1) || (r < 1) || (p < 1)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if ((r > SIZE_MAX / 128 / p) ||
|
||||
#if SIZE_MAX / 256 <= UINT32_MAX
|
||||
(r > SIZE_MAX / 256) ||
|
||||
#endif
|
||||
(N > SIZE_MAX / 128 / r)) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
if (N > UINT64_MAX / ((uint64_t)t + 1)) {
|
||||
errno = EFBIG;
|
||||
return -1;
|
||||
}
|
||||
if (flags & YESCRYPT_RW) {
|
||||
if ((flags & YESCRYPT_WORM) || (N / p <= 1) || (r < rmin)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (p > SIZE_MAX / Sbytes) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
if (p > SIZE_MAX / sizeof(*pwxform_ctx)) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
NROM = 0;
|
||||
VROM = NULL;
|
||||
if (shared) {
|
||||
NROM = shared->aligned_size / ((size_t)128 * r);
|
||||
/*
|
||||
* This implementation could support ROM without YESCRYPT_RW as well, but we
|
||||
* currently don't want to make such support available so that it can be safely
|
||||
* excluded from optimized implementations (where it'd require extra code).
|
||||
*/
|
||||
if (((NROM & (NROM - 1)) != 0) || (NROM <= 1) ||
|
||||
!(flags & YESCRYPT_RW)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
VROM = shared->aligned;
|
||||
}
|
||||
|
||||
/* Allocate memory */
|
||||
V_size = (size_t)128 * r * N;
|
||||
if (flags & __YESCRYPT_INIT_SHARED) {
|
||||
V = (uint32_t *)local->aligned;
|
||||
if (local->aligned_size < V_size) {
|
||||
if (local->base || local->aligned ||
|
||||
local->base_size || local->aligned_size) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if ((V = malloc(V_size)) == NULL)
|
||||
return -1;
|
||||
local->base = local->aligned = V;
|
||||
local->base_size = local->aligned_size = V_size;
|
||||
}
|
||||
} else {
|
||||
if ((V = malloc(V_size)) == NULL)
|
||||
return -1;
|
||||
}
|
||||
B_size = (size_t)128 * r * p;
|
||||
if ((B = malloc(B_size)) == NULL)
|
||||
goto free_V;
|
||||
if ((XY = malloc((size_t)256 * r)) == NULL)
|
||||
goto free_B;
|
||||
S = NULL;
|
||||
pwxform_ctx = NULL;
|
||||
if (flags & YESCRYPT_RW) {
|
||||
if ((S = malloc((size_t)Sbytes * p)) == NULL)
|
||||
goto free_XY;
|
||||
if ((pwxform_ctx = malloc(sizeof(*pwxform_ctx) * p)) == NULL)
|
||||
goto free_S;
|
||||
}
|
||||
|
||||
if (flags) {
|
||||
HMAC_SHA256_CTX_Y ctx;
|
||||
HMAC_SHA256_Init_Y(&ctx, "yescrypt-prehash",
|
||||
(flags & __YESCRYPT_PREHASH) ? 16 : 8);
|
||||
HMAC_SHA256_Update_Y(&ctx, passwd, passwdlen);
|
||||
HMAC_SHA256_Final_Y((uint8_t *)sha256, &ctx);
|
||||
passwd = (uint8_t *)sha256;
|
||||
passwdlen = sizeof(sha256);
|
||||
}
|
||||
|
||||
/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
|
||||
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1,
|
||||
(uint8_t *)B, B_size);
|
||||
|
||||
if (flags)
|
||||
blkcpy(sha256, B, sizeof(sha256) / sizeof(sha256[0]));
|
||||
|
||||
if (flags & YESCRYPT_RW) {
|
||||
for (i = 0; i < p; i++)
|
||||
pwxform_ctx[i].S = &S[i * Swords];
|
||||
smix(B, r, N, p, t, flags, V, NROM, VROM, XY, pwxform_ctx,
|
||||
(uint8_t *)sha256);
|
||||
} else {
|
||||
/* 2: for i = 0 to p - 1 do */
|
||||
for (i = 0; i < p; i++) {
|
||||
/* 3: B_i <-- MF(B_i, N) */
|
||||
smix(&B[(size_t)32 * r * i], r, N, 1, t, flags, V,
|
||||
NROM, VROM, XY, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
dkp = buf;
|
||||
if (flags && buflen < sizeof(dk)) {
|
||||
PBKDF2_SHA256(passwd, passwdlen, (uint8_t *)B, B_size, 1,
|
||||
dk, sizeof(dk));
|
||||
dkp = dk;
|
||||
}
|
||||
|
||||
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
|
||||
PBKDF2_SHA256(passwd, passwdlen, (uint8_t *)B, B_size, 1, buf, buflen);
|
||||
|
||||
/*
|
||||
* Except when computing classic scrypt, allow all computation so far
|
||||
* to be performed on the client. The final steps below match those of
|
||||
* SCRAM (RFC 5802), so that an extension of SCRAM (with the steps so
|
||||
* far in place of SCRAM's use of PBKDF2 and with SHA-256 in place of
|
||||
* SCRAM's use of SHA-1) would be usable with yescrypt hashes.
|
||||
*/
|
||||
if (flags && !(flags & __YESCRYPT_PREHASH)) {
|
||||
/* Compute ClientKey */
|
||||
{
|
||||
HMAC_SHA256_CTX_Y ctx;
|
||||
HMAC_SHA256_Init_Y(&ctx, dkp, sizeof(dk));
|
||||
HMAC_SHA256_Update_Y(&ctx, "Client Key", 10);
|
||||
HMAC_SHA256_Final_Y((uint8_t *)sha256, &ctx);
|
||||
}
|
||||
/* Compute StoredKey */
|
||||
{
|
||||
SHA256_CTX_Y ctx;
|
||||
size_t clen = buflen;
|
||||
if (clen > sizeof(dk))
|
||||
clen = sizeof(dk);
|
||||
SHA256_Init_Y(&ctx);
|
||||
SHA256_Update_Y(&ctx, (uint8_t *)sha256, sizeof(sha256));
|
||||
SHA256_Final_Y(dk, &ctx);
|
||||
memcpy(buf, dk, clen);
|
||||
}
|
||||
}
|
||||
|
||||
/* Success! */
|
||||
retval = 0;
|
||||
|
||||
/* Free memory */
|
||||
free(pwxform_ctx);
|
||||
free_S:
|
||||
free(S);
|
||||
free_XY:
|
||||
free(XY);
|
||||
free_B:
|
||||
free(B);
|
||||
free_V:
|
||||
if (!(flags & __YESCRYPT_INIT_SHARED))
|
||||
free(V);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* yescrypt_kdf(shared, local, passwd, passwdlen, salt, saltlen,
|
||||
* N, r, p, t, g, flags, buf, buflen):
|
||||
* Compute scrypt or its revision as requested by the parameters. The inputs
|
||||
* to this function are the same as those for yescrypt_kdf_body() above, with
|
||||
* the addition of g, which controls hash upgrades (0 for no upgrades so far).
|
||||
*/
|
||||
int
|
||||
yescrypt_kdf(const yescrypt_shared_t * shared, yescrypt_local_t * local,
|
||||
const uint8_t * passwd, size_t passwdlen,
|
||||
const uint8_t * salt, size_t saltlen,
|
||||
uint64_t N, uint32_t r, uint32_t p, uint32_t t, uint32_t g,
|
||||
yescrypt_flags_t flags,
|
||||
uint8_t * buf, size_t buflen)
|
||||
{
|
||||
uint8_t dk[32];
|
||||
|
||||
if ((flags & YESCRYPT_RW) &&
|
||||
p >= 1 && N / p >= 0x100 && N / p * r >= 0x20000) {
|
||||
int retval = yescrypt_kdf_body(shared, local,
|
||||
passwd, passwdlen, salt, saltlen,
|
||||
N >> 6, r, p, 0, flags | __YESCRYPT_PREHASH,
|
||||
dk, sizeof(dk));
|
||||
if (retval)
|
||||
return retval;
|
||||
passwd = dk;
|
||||
passwdlen = sizeof(dk);
|
||||
}
|
||||
|
||||
do {
|
||||
uint8_t * dkp = g ? dk : buf;
|
||||
size_t dklen = g ? sizeof(dk) : buflen;
|
||||
int retval = yescrypt_kdf_body(shared, local,
|
||||
passwd, passwdlen, salt, saltlen,
|
||||
N, r, p, t, flags, dkp, dklen);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
passwd = dkp;
|
||||
passwdlen = dklen;
|
||||
|
||||
N <<= 2;
|
||||
if (!N)
|
||||
return -1;
|
||||
t >>= 1;
|
||||
} while (g--);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
yescrypt_init_shared(yescrypt_shared_t * shared,
|
||||
const uint8_t * param, size_t paramlen,
|
||||
uint64_t N, uint32_t r, uint32_t p,
|
||||
yescrypt_init_shared_flags_t flags,
|
||||
uint8_t * buf, size_t buflen)
|
||||
{
|
||||
yescrypt_shared_t half1, half2;
|
||||
uint8_t salt[32];
|
||||
|
||||
if (flags & YESCRYPT_SHARED_PREALLOCATED) {
|
||||
if (!shared->aligned || !shared->aligned_size)
|
||||
return -1;
|
||||
} else {
|
||||
shared->base = shared->aligned = NULL;
|
||||
shared->base_size = shared->aligned_size = 0;
|
||||
}
|
||||
if (!param && !paramlen && !N && !r && !p && !buf && !buflen)
|
||||
return 0;
|
||||
|
||||
if (yescrypt_kdf_body(NULL, shared,
|
||||
param, paramlen, NULL, 0, N, r, p, 0,
|
||||
YESCRYPT_RW | __YESCRYPT_INIT_SHARED_1,
|
||||
salt, sizeof(salt)))
|
||||
goto out;
|
||||
|
||||
half1 = half2 = *shared;
|
||||
half1.aligned_size /= 2;
|
||||
#ifdef _MSC_VER
|
||||
(uint8_t*)half2.aligned += half1.aligned_size;
|
||||
#else
|
||||
half2.aligned += half1.aligned_size;
|
||||
#endif
|
||||
half2.aligned_size = half1.aligned_size;
|
||||
N /= 2;
|
||||
|
||||
if (p > 1 && yescrypt_kdf_body(&half1, &half2,
|
||||
param, paramlen, salt, sizeof(salt), N, r, p, 0,
|
||||
YESCRYPT_RW | __YESCRYPT_INIT_SHARED_2,
|
||||
salt, sizeof(salt)))
|
||||
goto out;
|
||||
|
||||
if (yescrypt_kdf_body(&half2, &half1,
|
||||
param, paramlen, salt, sizeof(salt), N, r, p, 0,
|
||||
YESCRYPT_RW | __YESCRYPT_INIT_SHARED_1,
|
||||
salt, sizeof(salt)))
|
||||
goto out;
|
||||
|
||||
if (yescrypt_kdf_body(&half1, &half2,
|
||||
param, paramlen, salt, sizeof(salt), N, r, p, 0,
|
||||
YESCRYPT_RW | __YESCRYPT_INIT_SHARED_1,
|
||||
buf, buflen))
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
if (!(flags & YESCRYPT_SHARED_PREALLOCATED))
|
||||
free(shared->base);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
yescrypt_free_shared(yescrypt_shared_t * shared)
|
||||
{
|
||||
free(shared->base);
|
||||
shared->base = shared->aligned = NULL;
|
||||
shared->base_size = shared->aligned_size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
yescrypt_init_local(yescrypt_local_t * local)
|
||||
{
|
||||
/* The reference implementation doesn't use the local structure */
|
||||
local->base = local->aligned = NULL;
|
||||
local->base_size = local->aligned_size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
yescrypt_free_local(yescrypt_local_t * local)
|
||||
{
|
||||
/* The reference implementation frees its memory in yescrypt_kdf() */
|
||||
return 0;
|
||||
}
|
1367
src/crypto/randomx/defyx/yescrypt-simd.c
Normal file
1367
src/crypto/randomx/defyx/yescrypt-simd.c
Normal file
File diff suppressed because it is too large
Load diff
326
src/crypto/randomx/defyx/yescrypt.h
Normal file
326
src/crypto/randomx/defyx/yescrypt.h
Normal file
|
@ -0,0 +1,326 @@
|
|||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* Copyright 2013-2015 Alexander Peslyak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#ifndef _YESCRYPT_H_
|
||||
#define _YESCRYPT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h> /* for size_t */
|
||||
|
||||
/**
|
||||
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen) and write the result into buf. The parameters r, p, and buflen
|
||||
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
|
||||
* must be a power of 2 greater than 1.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*
|
||||
* MT-safe as long as buf is local to the thread.
|
||||
*/
|
||||
extern int crypto_scrypt(const uint8_t * __passwd, size_t __passwdlen,
|
||||
const uint8_t * __salt, size_t __saltlen,
|
||||
uint64_t __N, uint32_t __r, uint32_t __p,
|
||||
uint8_t * __buf, size_t __buflen);
|
||||
|
||||
/**
|
||||
* Internal type used by the memory allocator. Please do not use it directly.
|
||||
* Use yescrypt_shared_t and yescrypt_local_t as appropriate instead, since
|
||||
* they might differ from each other in a future version.
|
||||
*/
|
||||
typedef struct {
|
||||
void * base, * aligned;
|
||||
size_t base_size, aligned_size;
|
||||
} yescrypt_region_t;
|
||||
|
||||
/**
|
||||
* Types for shared (ROM) and thread-local (RAM) data structures.
|
||||
*/
|
||||
typedef yescrypt_region_t yescrypt_shared_t;
|
||||
typedef yescrypt_region_t yescrypt_local_t;
|
||||
|
||||
/**
|
||||
* Possible values for yescrypt_init_shared()'s flags argument.
|
||||
*/
|
||||
typedef enum {
|
||||
YESCRYPT_SHARED_DEFAULTS = 0,
|
||||
YESCRYPT_SHARED_PREALLOCATED = 0x100
|
||||
} yescrypt_init_shared_flags_t;
|
||||
|
||||
/**
|
||||
* Possible values for the flags argument of yescrypt_kdf(),
|
||||
* yescrypt_gensalt_r(), yescrypt_gensalt(). These may be OR'ed together,
|
||||
* except that YESCRYPT_WORM and YESCRYPT_RW are mutually exclusive.
|
||||
* Please refer to the description of yescrypt_kdf() below for the meaning of
|
||||
* these flags.
|
||||
*/
|
||||
typedef enum {
|
||||
/* public */
|
||||
YESCRYPT_WORM = 2,
|
||||
YESCRYPT_RW = 1,
|
||||
/* private */
|
||||
__YESCRYPT_INIT_SHARED_1 = 0x10000,
|
||||
__YESCRYPT_INIT_SHARED_2 = 0x20000,
|
||||
__YESCRYPT_INIT_SHARED = 0x30000,
|
||||
__YESCRYPT_PREHASH = 0x100000
|
||||
} yescrypt_flags_t;
|
||||
|
||||
#define YESCRYPT_KNOWN_FLAGS \
|
||||
(YESCRYPT_WORM | YESCRYPT_RW | \
|
||||
__YESCRYPT_INIT_SHARED | __YESCRYPT_PREHASH)
|
||||
|
||||
/**
|
||||
* yescrypt_init_shared(shared, param, paramlen, N, r, p, flags, buf, buflen):
|
||||
* Optionally allocate memory for and initialize the shared (ROM) data
|
||||
* structure. The parameters N, r, and p must satisfy the same conditions as
|
||||
* with crypto_scrypt(). param and paramlen specify a local parameter with
|
||||
* which the ROM is seeded. If buf is not NULL, then it is used to return
|
||||
* buflen bytes of message digest for the initialized ROM (the caller may use
|
||||
* this to verify that the ROM has been computed in the same way that it was on
|
||||
* a previous run).
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*
|
||||
* If bit YESCRYPT_SHARED_PREALLOCATED in flags is set, then memory for the
|
||||
* ROM is assumed to have been preallocated by the caller, with shared->aligned
|
||||
* being the start address of the ROM and shared->aligned_size being its size
|
||||
* (which must be consistent with N, r, and p). This may be used e.g. when the
|
||||
* ROM is to be placed in a SysV shared memory segment allocated by the caller.
|
||||
*
|
||||
* MT-safe as long as shared is local to the thread.
|
||||
*/
|
||||
extern int yescrypt_init_shared(yescrypt_shared_t * __shared,
|
||||
const uint8_t * __param, size_t __paramlen,
|
||||
uint64_t __N, uint32_t __r, uint32_t __p,
|
||||
yescrypt_init_shared_flags_t __flags,
|
||||
uint8_t * __buf, size_t __buflen);
|
||||
|
||||
/**
|
||||
* yescrypt_free_shared(shared):
|
||||
* Free memory that had been allocated with yescrypt_init_shared().
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*
|
||||
* MT-safe as long as shared is local to the thread.
|
||||
*/
|
||||
extern int yescrypt_free_shared(yescrypt_shared_t * __shared);
|
||||
|
||||
/**
|
||||
* yescrypt_init_local(local):
|
||||
* Initialize the thread-local (RAM) data structure. Actual memory allocation
|
||||
* is currently fully postponed until a call to yescrypt_kdf() or yescrypt_r().
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*
|
||||
* MT-safe as long as local is local to the thread.
|
||||
*/
|
||||
extern int yescrypt_init_local(yescrypt_local_t * __local);
|
||||
|
||||
/**
|
||||
* yescrypt_free_local(local):
|
||||
* Free memory that may have been allocated for an initialized thread-local
|
||||
* (RAM) data structure.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*
|
||||
* MT-safe as long as local is local to the thread.
|
||||
*/
|
||||
extern int yescrypt_free_local(yescrypt_local_t * __local);
|
||||
|
||||
/**
|
||||
* yescrypt_kdf(shared, local, passwd, passwdlen, salt, saltlen,
|
||||
* N, r, p, t, g, flags, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen), or a revision of scrypt as requested by flags and shared, and
|
||||
* write the result into buf. The parameters N, r, p, and buflen must satisfy
|
||||
* the same conditions as with crypto_scrypt(). t controls computation time
|
||||
* while not affecting peak memory usage. g controls hash upgrades (0 for no
|
||||
* upgrades so far). shared and flags may request special modes as described
|
||||
* below. local is the thread-local data structure, allowing to preserve and
|
||||
* reuse a memory allocation across calls, thereby reducing its overhead.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*
|
||||
* t controls computation time. t = 0 is optimal in terms of achieving the
|
||||
* highest area-time for ASIC attackers. Thus, higher computation time, if
|
||||
* affordable, is best achieved by increasing N rather than by increasing t.
|
||||
* However, if the higher memory usage (which goes along with higher N) is not
|
||||
* affordable, or if fine-tuning of the time is needed (recall that N must be a
|
||||
* power of 2), then t = 1 or above may be used to increase time while staying
|
||||
* at the same peak memory usage. t = 1 increases the time by 25% and
|
||||
* decreases the normalized area-time to 96% of optimal. (Of course, in
|
||||
* absolute terms the area-time increases with higher t. It's just that it
|
||||
* would increase slightly more with higher N*r rather than with higher t.)
|
||||
* t = 2 increases the time by another 20% and decreases the normalized
|
||||
* area-time to 89% of optimal. Thus, these two values are reasonable to use
|
||||
* for fine-tuning. Values of t higher than 2 result in further increase in
|
||||
* time while reducing the efficiency much further (e.g., down to around 50% of
|
||||
* optimal for t = 5, which runs 3 to 4 times slower than t = 0, with exact
|
||||
* numbers varying by the flags settings).
|
||||
*
|
||||
* Classic scrypt is available by setting t = 0, flags = 0, and shared = NULL.
|
||||
* In this mode, the thread-local memory region (RAM) is first sequentially
|
||||
* written to and then randomly read from. This algorithm is friendly towards
|
||||
* time-memory tradeoffs (TMTO), available both to defenders (albeit not in
|
||||
* this implementation) and to attackers.
|
||||
*
|
||||
* Setting YESCRYPT_WORM enables only minimal enhancements relative to classic
|
||||
* scrypt: support for the t parameter, and pre- and post-hashing.
|
||||
*
|
||||
* Setting YESCRYPT_RW adds extra random reads and writes to the thread-local
|
||||
* memory region (RAM), which makes TMTO a lot less efficient. This may be
|
||||
* used to slow down the kinds of attackers who would otherwise benefit from
|
||||
* classic scrypt's efficient TMTO. Since classic scrypt's TMTO allows not
|
||||
* only for the tradeoff, but also for a decrease of attacker's area-time (by
|
||||
* up to a constant factor), setting YESCRYPT_RW substantially increases the
|
||||
* cost of attacks in area-time terms as well. Yet another benefit of it is
|
||||
* that optimal area-time is reached at an earlier time than with classic
|
||||
* scrypt, and t = 0 actually corresponds to this earlier completion time,
|
||||
* resulting in quicker hash computations (and thus in higher request rate
|
||||
* capacity). Due to these properties, YESCRYPT_RW should almost always be
|
||||
* set, except when compatibility with classic scrypt or TMTO-friendliness are
|
||||
* desired.
|
||||
*
|
||||
* YESCRYPT_RW also moves parallelism that is present with p > 1 to a
|
||||
* lower level as compared to where it is in classic scrypt. This reduces
|
||||
* flexibility for efficient computation (for both attackers and defenders) by
|
||||
* requiring that, short of resorting to TMTO, the full amount of memory be
|
||||
* allocated as needed for the specified p, regardless of whether that
|
||||
* parallelism is actually being fully made use of or not. (For comparison, a
|
||||
* single instance of classic scrypt may be computed in less memory without any
|
||||
* CPU time overhead, but in more real time, by not making full use of the
|
||||
* parallelism.) This may be desirable when the defender has enough memory
|
||||
* with sufficiently low latency and high bandwidth for efficient full parallel
|
||||
* execution, yet the required memory size is high enough that some likely
|
||||
* attackers might end up being forced to choose between using higher latency
|
||||
* memory than they could use otherwise (waiting for data longer) or using TMTO
|
||||
* (waiting for data more times per one hash computation). The area-time cost
|
||||
* for other kinds of attackers (who would use the same memory type and TMTO
|
||||
* factor or no TMTO either way) remains roughly the same, given the same
|
||||
* running time for the defender.
|
||||
*
|
||||
* As a side effect of differences between the algorithms, setting YESCRYPT_RW
|
||||
* also changes the way the total processing time (combined for all threads)
|
||||
* and memory allocation (if the parallelism is being made use of) is to be
|
||||
* controlled from N*r*p (for classic scrypt) to N*r (in this modification).
|
||||
* Obviously, these only differ for p > 1.
|
||||
*
|
||||
* Passing a shared structure, with ROM contents previously computed by
|
||||
* yescrypt_init_shared(), enables the use of ROM and requires YESCRYPT_RW for
|
||||
* the thread-local RAM region. In order to allow for initialization of the
|
||||
* ROM to be split into a separate program, the shared->aligned and
|
||||
* shared->aligned_size fields may be set by the caller of yescrypt_kdf()
|
||||
* manually rather than with yescrypt_init_shared().
|
||||
*
|
||||
* local must be initialized with yescrypt_init_local().
|
||||
*
|
||||
* MT-safe as long as local and buf are local to the thread.
|
||||
*/
|
||||
extern int yescrypt_kdf(const yescrypt_shared_t * __shared,
|
||||
yescrypt_local_t * __local,
|
||||
const uint8_t * __passwd, size_t __passwdlen,
|
||||
const uint8_t * __salt, size_t __saltlen,
|
||||
uint64_t __N, uint32_t __r, uint32_t __p, uint32_t __t, uint32_t __g,
|
||||
yescrypt_flags_t __flags,
|
||||
uint8_t * __buf, size_t __buflen);
|
||||
|
||||
/**
|
||||
* yescrypt_r(shared, local, passwd, passwdlen, setting, buf, buflen):
|
||||
* Compute and encode an scrypt or enhanced scrypt hash of passwd given the
|
||||
* parameters and salt value encoded in setting. If shared is not NULL, a ROM
|
||||
* is used and YESCRYPT_RW is required. Otherwise, whether to compute classic
|
||||
* scrypt, YESCRYPT_WORM (a slight deviation from classic scrypt), or
|
||||
* YESCRYPT_RW (time-memory tradeoff discouraging modification) is determined
|
||||
* by the setting string. shared (if not NULL) and local must be initialized
|
||||
* as described above for yescrypt_kdf(). buf must be large enough (as
|
||||
* indicated by buflen) to hold the encoded hash string.
|
||||
*
|
||||
* Return the encoded hash string on success; or NULL on error.
|
||||
*
|
||||
* MT-safe as long as local and buf are local to the thread.
|
||||
*/
|
||||
extern uint8_t * yescrypt_r(const yescrypt_shared_t * __shared,
|
||||
yescrypt_local_t * __local,
|
||||
const uint8_t * __passwd, size_t __passwdlen,
|
||||
const uint8_t * __setting,
|
||||
uint8_t * __buf, size_t __buflen);
|
||||
|
||||
/**
|
||||
* yescrypt(passwd, setting):
|
||||
* Compute and encode an scrypt or enhanced scrypt hash of passwd given the
|
||||
* parameters and salt value encoded in setting. Whether to compute classic
|
||||
* scrypt, YESCRYPT_WORM (a slight deviation from classic scrypt), or
|
||||
* YESCRYPT_RW (time-memory tradeoff discouraging modification) is determined
|
||||
* by the setting string.
|
||||
*
|
||||
* Return the encoded hash string on success; or NULL on error.
|
||||
*
|
||||
* This is a crypt(3)-like interface, which is simpler to use than
|
||||
* yescrypt_r(), but it is not MT-safe, it does not allow for the use of a ROM,
|
||||
* and it is slower than yescrypt_r() for repeated calls because it allocates
|
||||
* and frees memory on each call.
|
||||
*
|
||||
* MT-unsafe.
|
||||
*/
|
||||
extern uint8_t * yescrypt(const uint8_t * __passwd, const uint8_t * __setting);
|
||||
|
||||
/**
|
||||
* yescrypt_gensalt_r(N_log2, r, p, flags, src, srclen, buf, buflen):
|
||||
* Generate a setting string for use with yescrypt_r() and yescrypt() by
|
||||
* encoding into it the parameters N_log2 (which is to be set to base 2
|
||||
* logarithm of the desired value for N), r, p, flags, and a salt given by src
|
||||
* (of srclen bytes). buf must be large enough (as indicated by buflen) to
|
||||
* hold the setting string.
|
||||
*
|
||||
* Return the setting string on success; or NULL on error.
|
||||
*
|
||||
* MT-safe as long as buf is local to the thread.
|
||||
*/
|
||||
extern uint8_t * yescrypt_gensalt_r(
|
||||
uint32_t __N_log2, uint32_t __r, uint32_t __p,
|
||||
yescrypt_flags_t __flags,
|
||||
const uint8_t * __src, size_t __srclen,
|
||||
uint8_t * __buf, size_t __buflen);
|
||||
|
||||
/**
|
||||
* yescrypt_gensalt(N_log2, r, p, flags, src, srclen):
|
||||
* Generate a setting string for use with yescrypt_r() and yescrypt(). This
|
||||
* function is the same as yescrypt_gensalt_r() except that it uses a static
|
||||
* buffer and thus is not MT-safe.
|
||||
*
|
||||
* Return the setting string on success; or NULL on error.
|
||||
*
|
||||
* MT-unsafe.
|
||||
*/
|
||||
extern uint8_t * yescrypt_gensalt(
|
||||
uint32_t __N_log2, uint32_t __r, uint32_t __p,
|
||||
yescrypt_flags_t __flags,
|
||||
const uint8_t * __src, size_t __srclen);
|
||||
|
||||
#endif /* !_YESCRYPT_H_ */
|
|
@ -48,13 +48,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <cassert>
|
||||
|
||||
extern "C" {
|
||||
#include "crypto/defyx/yescrypt.h"
|
||||
#include "crypto/defyx/KangarooTwelve.h"
|
||||
#include "crypto/randomx/defyx/yescrypt.h"
|
||||
#include "crypto/randomx/defyx/KangarooTwelve.h"
|
||||
}
|
||||
#define YESCRYPT_FLAGS YESCRYPT_RW
|
||||
#define YESCRYPT_BASE_N 2048
|
||||
#define YESCRYPT_R 8
|
||||
#define YESCRYPT_P 1
|
||||
|
||||
RandomX_ConfigurationWownero::RandomX_ConfigurationWownero()
|
||||
{
|
||||
|
@ -127,8 +123,8 @@ RandomX_ConfigurationScala::RandomX_ConfigurationScala()
|
|||
ScratchpadL1_Size = 65536;
|
||||
ScratchpadL2_Size = 131072;
|
||||
ScratchpadL3_Size = 262144;
|
||||
ProgramSize = 64;
|
||||
ProgramIterations = 1024;
|
||||
ProgramSize = 64;
|
||||
ProgramIterations = 1024;
|
||||
ProgramCount = 4;
|
||||
|
||||
RANDOMX_FREQ_IADD_RS = 25;
|
||||
|
@ -344,31 +340,25 @@ alignas(64) RandomX_ConfigurationBase RandomX_CurrentConfig;
|
|||
|
||||
static std::mutex vm_pool_mutex;
|
||||
|
||||
int sipesh(void *out, size_t outlen, const void *in, size_t inlen)
|
||||
int rx_sipesh_k12(void *out, size_t outlen, const void *in, size_t inlen)
|
||||
{
|
||||
const void *salt = in;
|
||||
size_t saltlen = inlen;
|
||||
unsigned int t_cost = 0;
|
||||
unsigned int m_cost = 0;
|
||||
const void *salt = in;
|
||||
size_t saltlen = inlen;
|
||||
yescrypt_local_t local;
|
||||
int retval;
|
||||
|
||||
if (yescrypt_init_local(&local))
|
||||
return -1;
|
||||
retval = yescrypt_kdf(NULL, &local, (const uint8_t*)in, inlen, (const uint8_t*)salt, saltlen,
|
||||
(uint64_t)YESCRYPT_BASE_N << m_cost, YESCRYPT_R, YESCRYPT_P,
|
||||
t_cost, 0, YESCRYPT_FLAGS, (uint8_t*)out, outlen);
|
||||
if (yescrypt_free_local(&local))
|
||||
return -1;
|
||||
if (yescrypt_init_local(&local)) return -1;
|
||||
retval = yescrypt_kdf(NULL, &local,
|
||||
(const uint8_t*)in, inlen,
|
||||
(const uint8_t*)salt, saltlen,
|
||||
(uint64_t)2048, 8, 1, 0, 0, (yescrypt_flags_t)1,
|
||||
(uint8_t*)out, outlen
|
||||
);
|
||||
if (yescrypt_free_local(&local) || retval) return -1;
|
||||
retval = KangarooTwelve((const unsigned char *)in, inlen, (unsigned char *)out, 32, 0, 0);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int k12(void *hash, const void *data, size_t length)
|
||||
{
|
||||
int kDo = KangarooTwelve((const unsigned char *)data, length, (unsigned char *)hash, 32, 0, 0);
|
||||
return kDo;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
randomx_cache *randomx_create_cache(randomx_flags flags, uint8_t *memory) {
|
||||
|
@ -569,12 +559,16 @@ extern "C" {
|
|||
vm->~randomx_vm();
|
||||
}
|
||||
|
||||
void randomx_calculate_hash(randomx_vm *machine, const void *input, size_t inputSize, void *output) {
|
||||
void randomx_calculate_hash(randomx_vm *machine, const void *input, size_t inputSize, void *output, const xmrig::Algorithm algo) {
|
||||
assert(machine != nullptr);
|
||||
assert(inputSize == 0 || input != nullptr);
|
||||
assert(output != nullptr);
|
||||
alignas(16) uint64_t tempHash[8];
|
||||
rx_blake2b(tempHash, sizeof(tempHash), input, inputSize, nullptr, 0);
|
||||
if (algo == xmrig::Algorithm::RX_DEFYX) {
|
||||
rx_sipesh_k12(tempHash, sizeof(tempHash), input, inputSize);
|
||||
} else {
|
||||
rx_blake2b(tempHash, sizeof(tempHash), input, inputSize, nullptr, 0);
|
||||
}
|
||||
machine->initScratchpad(&tempHash);
|
||||
machine->resetRoundingMode();
|
||||
for (uint32_t chain = 0; chain < RandomX_CurrentConfig.ProgramCount - 1; ++chain) {
|
||||
|
@ -585,12 +579,16 @@ extern "C" {
|
|||
machine->getFinalResult(output, RANDOMX_HASH_SIZE);
|
||||
}
|
||||
|
||||
void randomx_calculate_hash_first(randomx_vm* machine, uint64_t (&tempHash)[8], const void* input, size_t inputSize) {
|
||||
rx_blake2b(tempHash, sizeof(tempHash), input, inputSize, nullptr, 0);
|
||||
void randomx_calculate_hash_first(randomx_vm* machine, uint64_t (&tempHash)[8], const void* input, size_t inputSize, const xmrig::Algorithm algo) {
|
||||
if (algo == xmrig::Algorithm::RX_DEFYX) {
|
||||
rx_sipesh_k12(tempHash, sizeof(tempHash), input, inputSize);
|
||||
} else {
|
||||
rx_blake2b(tempHash, sizeof(tempHash), input, inputSize, nullptr, 0);
|
||||
}
|
||||
machine->initScratchpad(tempHash);
|
||||
}
|
||||
|
||||
void randomx_calculate_hash_next(randomx_vm* machine, uint64_t (&tempHash)[8], const void* nextInput, size_t nextInputSize, void* output) {
|
||||
void randomx_calculate_hash_next(randomx_vm* machine, uint64_t (&tempHash)[8], const void* nextInput, size_t nextInputSize, void* output, const xmrig::Algorithm algo) {
|
||||
machine->resetRoundingMode();
|
||||
for (uint32_t chain = 0; chain < RandomX_CurrentConfig.ProgramCount - 1; ++chain) {
|
||||
machine->run(&tempHash);
|
||||
|
@ -599,44 +597,12 @@ extern "C" {
|
|||
machine->run(&tempHash);
|
||||
|
||||
// Finish current hash and fill the scratchpad for the next hash at the same time
|
||||
rx_blake2b(tempHash, sizeof(tempHash), nextInput, nextInputSize, nullptr, 0);
|
||||
if (algo == xmrig::Algorithm::RX_DEFYX) {
|
||||
rx_sipesh_k12(tempHash, sizeof(tempHash), nextInput, nextInputSize);
|
||||
} else {
|
||||
rx_blake2b(tempHash, sizeof(tempHash), nextInput, nextInputSize, nullptr, 0);
|
||||
}
|
||||
machine->hashAndFill(output, RANDOMX_HASH_SIZE, tempHash);
|
||||
}
|
||||
|
||||
void defyx_calculate_hash(randomx_vm *machine, const void *input, size_t inputSize, void *output) {
|
||||
assert(machine != nullptr);
|
||||
assert(inputSize == 0 || input != nullptr);
|
||||
assert(output != nullptr);
|
||||
alignas(16) uint64_t tempHash[8];
|
||||
sipesh(tempHash, sizeof(tempHash), input, inputSize);
|
||||
k12(tempHash, input, inputSize);
|
||||
machine->initScratchpad(&tempHash);
|
||||
machine->resetRoundingMode();
|
||||
for (uint32_t chain = 0; chain < RandomX_CurrentConfig.ProgramCount - 1; ++chain) {
|
||||
machine->run(&tempHash);
|
||||
rx_blake2b(tempHash, sizeof(tempHash), machine->getRegisterFile(), sizeof(randomx::RegisterFile), nullptr, 0);
|
||||
}
|
||||
machine->run(&tempHash);
|
||||
machine->getFinalResult(output, RANDOMX_HASH_SIZE);
|
||||
}
|
||||
|
||||
void defyx_calculate_hash_first(randomx_vm* machine, uint64_t (&tempHash)[8], const void* input, size_t inputSize) {
|
||||
sipesh(tempHash, sizeof(tempHash), input, inputSize);
|
||||
k12(tempHash, input, inputSize);
|
||||
machine->initScratchpad(tempHash);
|
||||
}
|
||||
|
||||
void defyx_calculate_hash_next(randomx_vm* machine, uint64_t (&tempHash)[8], const void* nextInput, size_t nextInputSize, void* output) {
|
||||
machine->resetRoundingMode();
|
||||
for (uint32_t chain = 0; chain < RandomX_CurrentConfig.ProgramCount - 1; ++chain) {
|
||||
machine->run(&tempHash);
|
||||
rx_blake2b(tempHash, sizeof(tempHash), machine->getRegisterFile(), sizeof(randomx::RegisterFile), nullptr, 0);
|
||||
}
|
||||
machine->run(&tempHash);
|
||||
|
||||
// Finish current hash and fill the scratchpad for the next hash at the same time
|
||||
sipesh(tempHash, sizeof(tempHash), nextInput, nextInputSize);
|
||||
k12(tempHash, nextInput, nextInputSize);
|
||||
machine->hashAndFill(output, RANDOMX_HASH_SIZE, tempHash);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include "base/crypto/Algorithm.h"
|
||||
#include "crypto/randomx/intrin_portable.h"
|
||||
|
||||
#define RANDOMX_HASH_SIZE 32
|
||||
|
@ -347,24 +348,10 @@ RANDOMX_EXPORT void randomx_destroy_vm(randomx_vm *machine);
|
|||
* @param output is a pointer to memory where the hash will be stored. Must not
|
||||
* be NULL and at least RANDOMX_HASH_SIZE bytes must be available for writing.
|
||||
*/
|
||||
RANDOMX_EXPORT void randomx_calculate_hash(randomx_vm *machine, const void *input, size_t inputSize, void *output);
|
||||
RANDOMX_EXPORT void randomx_calculate_hash(randomx_vm *machine, const void *input, size_t inputSize, void *output, const xmrig::Algorithm algo);
|
||||
|
||||
RANDOMX_EXPORT void randomx_calculate_hash_first(randomx_vm* machine, uint64_t (&tempHash)[8], const void* input, size_t inputSize);
|
||||
RANDOMX_EXPORT void randomx_calculate_hash_next(randomx_vm* machine, uint64_t (&tempHash)[8], const void* nextInput, size_t nextInputSize, void* output);
|
||||
|
||||
/**
|
||||
* Calculates a RandomX hash value (Scala variant).
|
||||
*
|
||||
* @param machine is a pointer to a randomx_vm structure. Must not be NULL.
|
||||
* @param input is a pointer to memory to be hashed. Must not be NULL.
|
||||
* @param inputSize is the number of bytes to be hashed.
|
||||
* @param output is a pointer to memory where the hash will be stored. Must not
|
||||
* be NULL and at least RANDOMX_HASH_SIZE bytes must be available for writing.
|
||||
*/
|
||||
RANDOMX_EXPORT void defyx_calculate_hash(randomx_vm *machine, const void *input, size_t inputSize, void *output);
|
||||
|
||||
RANDOMX_EXPORT void defyx_calculate_hash_first(randomx_vm* machine, uint64_t (&tempHash)[8], const void* input, size_t inputSize);
|
||||
RANDOMX_EXPORT void defyx_calculate_hash_next(randomx_vm* machine, uint64_t (&tempHash)[8], const void* nextInput, size_t nextInputSize, void* output);
|
||||
RANDOMX_EXPORT void randomx_calculate_hash_first(randomx_vm* machine, uint64_t (&tempHash)[8], const void* input, size_t inputSize, const xmrig::Algorithm algo);
|
||||
RANDOMX_EXPORT void randomx_calculate_hash_next(randomx_vm* machine, uint64_t (&tempHash)[8], const void* nextInput, size_t nextInputSize, void* output, const xmrig::Algorithm algo);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue