Merge branch 'tpruvot-next' into next

This commit is contained in:
Ralph S. (Coolguy3289) 2020-01-01 23:52:49 -05:00
commit a420e14e0f
235 changed files with 11996 additions and 3105 deletions

5
.gitignore vendored
View file

@ -1,5 +1,7 @@
*.o *.o
*.a *.a
.deps
.dirstamp
stratum/stratum stratum/stratum
stratum/blocknotify stratum/blocknotify
blocknotify/blocknotify blocknotify/blocknotify
@ -18,3 +20,6 @@ web/serverconfig.php
web/assets/ web/assets/
*.rej *.rej
*.orig *.orig
.idea/*
web/yaamp/.idea/
*.0

5
.travis.yml Normal file
View file

@ -0,0 +1,5 @@
language: cpp
script:
- (cd blocknotify && make)
- (cd stratum/iniparser && make)
- (cd stratum && make)

View file

@ -4,6 +4,9 @@ To install the pool you will need:
1. Ubuntu 16.04 VPS 1. Ubuntu 16.04 VPS
2. Install Script 2. Install Script
WARNINGS
- Use at your own risks.
The install Script will install the pool and all dependencies needed. The install Script will install the pool and all dependencies needed.
TO INSTALL: TO INSTALL:

View file

@ -25,8 +25,9 @@ screen -dmS deep $STRATUM_DIR/run.sh deep
screen -dmS x11 $STRATUM_DIR/run.sh x11 screen -dmS x11 $STRATUM_DIR/run.sh x11
screen -dmS x11evo $STRATUM_DIR/run.sh x11evo screen -dmS x11evo $STRATUM_DIR/run.sh x11evo
screen -dmS x13 $STRATUM_DIR/run.sh x13 screen -dmS x13 $STRATUM_DIR/run.sh x13
screen -dmS x14 $STRATUM_DIR/run.sh x14 #screen -dmS x14 $STRATUM_DIR/run.sh x14
screen -dmS x15 $STRATUM_DIR/run.sh x15 #screen -dmS x15 $STRATUM_DIR/run.sh x15
#screen -dmS x16r $STRATUM_DIR/run.sh x16r
screen -dmS x17 $STRATUM_DIR/run.sh x17 screen -dmS x17 $STRATUM_DIR/run.sh x17
screen -dmS xevan $STRATUM_DIR/run.sh xevan screen -dmS xevan $STRATUM_DIR/run.sh xevan
screen -dmS timetravel $STRATUM_DIR/run.sh timetravel screen -dmS timetravel $STRATUM_DIR/run.sh timetravel
@ -48,9 +49,12 @@ screen -dmS jha $STRATUM_DIR/run.sh jha
#screen -dmS dmd-gr $STRATUM_DIR/run.sh dmd-gr #screen -dmS dmd-gr $STRATUM_DIR/run.sh dmd-gr
screen -dmS myr-gr $STRATUM_DIR/run.sh myr-gr screen -dmS myr-gr $STRATUM_DIR/run.sh myr-gr
screen -dmS lbry $STRATUM_DIR/run.sh lbry screen -dmS lbry $STRATUM_DIR/run.sh lbry
screen -dmS lyra2 $STRATUM_DIR/run.sh lyra2 screen -dmS allium $STRATUM_DIR/run.sh allium
#screen -dmS lyra2 $STRATUM_DIR/run.sh lyra2
screen -dmS lyra2v2 $STRATUM_DIR/run.sh lyra2v2 screen -dmS lyra2v2 $STRATUM_DIR/run.sh lyra2v2
screen -dmS zero $STRATUM_DIR/run.sh lyra2z screen -dmS lyra2z $STRATUM_DIR/run.sh lyra2z
screen -dmS lyra2zz $STRATUM_DIR/run.sh lyra2zz
screen -dmS rainforest $STRATUM_DIR/run.sh rainforest
screen -dmS blakecoin $STRATUM_DIR/run.sh blakecoin # blake 8 screen -dmS blakecoin $STRATUM_DIR/run.sh blakecoin # blake 8
screen -dmS blake $STRATUM_DIR/run.sh blake screen -dmS blake $STRATUM_DIR/run.sh blake
@ -59,15 +63,22 @@ screen -dmS vanilla $STRATUM_DIR/run.sh vanilla # blake 8
screen -dmS decred $STRATUM_DIR/run.sh decred # blake 14 screen -dmS decred $STRATUM_DIR/run.sh decred # blake 14
#screen -dmS keccak $STRATUM_DIR/run.sh keccak #screen -dmS keccak $STRATUM_DIR/run.sh keccak
#screen -dmS keccakc $STRATUM_DIR/run.sh keccakc
#screen -dmS phi $STRATUM_DIR/run.sh phi
#screen -dmS polytimos $STRATUM_DIR/run.sh polytimos
screen -dmS whirlpool $STRATUM_DIR/run.sh whirlpool screen -dmS whirlpool $STRATUM_DIR/run.sh whirlpool
screen -dmS skein $STRATUM_DIR/run.sh skein screen -dmS skein $STRATUM_DIR/run.sh skein
screen -dmS skein2 $STRATUM_DIR/run.sh skein2 screen -dmS skein2 $STRATUM_DIR/run.sh skein2
screen -dmS yescrypt $STRATUM_DIR/run.sh yescrypt screen -dmS yescrypt $STRATUM_DIR/run.sh yescrypt
#screen -dmS yescryptR16 $STRATUM_DIR/run.sh yescryptR16
screen -dmS zr5 $STRATUM_DIR/run.sh zr5 screen -dmS zr5 $STRATUM_DIR/run.sh zr5
screen -dmS sib $STRATUM_DIR/run.sh sib screen -dmS sib $STRATUM_DIR/run.sh sib
screen -dmS m7m $STRATUM_DIR/run.sh m7m screen -dmS m7m $STRATUM_DIR/run.sh m7m
screen -dmS veltor $STRATUM_DIR/run.sh veltor screen -dmS veltor $STRATUM_DIR/run.sh veltor
screen -dmS velvet $STRATUM_DIR/run.sh velvet screen -dmS velvet $STRATUM_DIR/run.sh velvet
screen -dmS argon2 $STRATUM_DIR/run.sh argon2 screen -dmS argon2 $STRATUM_DIR/run.sh argon2
screen -dmS argon2d-dyn $STRATUM_DIR/run.sh argon2d-dyn
screen -dmS x22i $STRATUM_DIR/run.sh x22i
screen -dmS lbk3 $STRATUM_DIR/run.sh lbk3

View file

@ -0,0 +1,13 @@
-- Recent additions to add after db init (.gz)
-- mysql yaamp -p < file.sql
-- filled by the stratum instance, to allow to handle/watch multiple instances
ALTER TABLE `coins` ADD `hasgetinfo` tinyint(1) UNSIGNED NOT NULL DEFAULT '1' AFTER `account`;
UPDATE coins SET hassubmitblock=0 WHERE hassubmitblock IS NULL;
UPDATE coins SET hassubmitblock=1 WHERE hassubmitblock > 0;
ALTER TABLE `coins` CHANGE `hassubmitblock` `hassubmitblock` tinyint(1) UNSIGNED NOT NULL DEFAULT '1';
ALTER TABLE `coins` ADD `no_explorer` tinyint(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `visible`;

View file

@ -8,12 +8,6 @@ SQLFLAGS= `mysql_config --cflags --libs`
# if you use the auto exchange feature... # if you use the auto exchange feature...
CFLAGS += -DNO_EXCHANGE CFLAGS += -DNO_EXCHANGE
#CFLAGS += -DHASH_DEBUGLOG_
#CFLAGS += -DRPC_DEBUGLOG_
#CFLAGS += -DREMOTE_DEBUGLOG_
#CFLAGS += -DSOCKET_DEBUGLOG_
#CFLAGS += -DCLIENT_DEBUGLOG_
#CFLAGS=-c -O2 -I /usr/include/mysql #CFLAGS=-c -O2 -I /usr/include/mysql
LDFLAGS=-O2 `mysql_config --libs` LDFLAGS=-O2 `mysql_config --libs`

210
stratum/algos/Lyra2-zz.c Normal file
View file

@ -0,0 +1,210 @@
/**
* Implementation of the Lyra2 Password Hashing Scheme (PHS).
*
* Author: The Lyra PHC team (http://www.lyra-kdf.net/) -- 2014.
*
* This software is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "Lyra2-zz.h"
#include "Sponge.h"
/**
* Executes Lyra2 based on the G function from Blake2b. This version supports salts and passwords
* whose combined length is smaller than the size of the memory matrix, (i.e., (nRows x nCols x b) bits,
* where "b" is the underlying sponge's bitrate). In this implementation, the "basil" is composed by all
* integer parameters (treated as type "unsigned int") in the order they are provided, plus the value
* of nCols, (i.e., basil = kLen || pwdlen || saltlen || timeCost || nRows || nCols).
*
* @param K The derived key to be output by the algorithm
* @param kLen Desired key length
* @param pwd User password
* @param pwdlen Password length
* @param salt Salt
* @param saltlen Salt length
* @param timeCost Parameter to determine the processing time (T)
* @param nRows Number or rows of the memory matrix (R)
* @param nCols Number of columns of the memory matrix (C)
*
* @return 0 if the key is generated correctly; -1 if there is an error (usually due to lack of memory for allocation)
*/
int LYRA2ZZ(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *salt, uint64_t saltlen, uint64_t timeCost, uint64_t nRows, uint64_t nCols)
{
//============================= Basic variables ============================//
int64_t row = 2; //index of row to be processed
int64_t prev = 1; //index of prev (last row ever computed/modified)
int64_t rowa = 0; //index of row* (a previous row, deterministically picked during Setup and randomly picked while Wandering)
int64_t tau; //Time Loop iterator
int64_t step = 1; //Visitation step (used during Setup and Wandering phases)
int64_t window = 2; //Visitation window (used to define which rows can be revisited during Setup)
int64_t gap = 1; //Modifier to the step, assuming the values 1 or -1
int64_t i; //auxiliary iteration counter
//==========================================================================/
//========== Initializing the Memory Matrix and pointers to it =============//
//Tries to allocate enough space for the whole memory matrix
const int64_t ROW_LEN_INT64 = BLOCK_LEN_INT64 * nCols;
const int64_t ROW_LEN_BYTES = ROW_LEN_INT64 * 8;
i = (int64_t) ((int64_t) nRows * (int64_t) ROW_LEN_BYTES);
uint64_t *wholeMatrix = malloc(i);
if (wholeMatrix == NULL) {
return -1;
}
memset(wholeMatrix, 0, i);
//Allocates pointers to each row of the matrix
uint64_t **memMatrix = malloc(nRows * sizeof (uint64_t*));
if (memMatrix == NULL) {
return -1;
}
//Places the pointers in the correct positions
uint64_t *ptrWord = wholeMatrix;
for (i = 0; i < nRows; i++) {
memMatrix[i] = ptrWord;
ptrWord += ROW_LEN_INT64;
}
//==========================================================================/
//============= Getting the password + salt + basil padded with 10*1 ===============//
//OBS.:The memory matrix will temporarily hold the password: not for saving memory,
//but this ensures that the password copied locally will be overwritten as soon as possible
//First, we clean enough blocks for the password, salt, basil and padding
uint64_t nBlocksInput = ((saltlen + pwdlen + 6 * sizeof (uint64_t)) / BLOCK_LEN_BLAKE2_SAFE_BYTES) + 1;
byte *ptrByte = (byte*) wholeMatrix;
memset(ptrByte, 0, nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES);
//Prepends the password
memcpy(ptrByte, pwd, pwdlen);
ptrByte += pwdlen;
//Concatenates the salt
memcpy(ptrByte, salt, saltlen);
ptrByte += saltlen;
//Concatenates the basil: every integer passed as parameter, in the order they are provided by the interface
memcpy(ptrByte, &kLen, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &pwdlen, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &saltlen, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &timeCost, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &nRows, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &nCols, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
//Now comes the padding
*ptrByte = 0x80; //first byte of padding: right after the password
ptrByte = (byte*) wholeMatrix; //resets the pointer to the start of the memory matrix
ptrByte += nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES - 1; //sets the pointer to the correct position: end of incomplete block
*ptrByte ^= 0x01; //last byte of padding: at the end of the last incomplete block
//==========================================================================/
//======================= Initializing the Sponge State ====================//
//Sponge state: 16 uint64_t, BLOCK_LEN_INT64 words of them for the bitrate (b) and the remainder for the capacity (c)
uint64_t *state = malloc(16 * sizeof (uint64_t));
if (state == NULL) {
return -1;
}
initState(state);
//==========================================================================/
//================================ Setup Phase =============================//
//Absorbing salt, password and basil: this is the only place in which the block length is hard-coded to 512 bits
ptrWord = wholeMatrix;
for (i = 0; i < nBlocksInput; i++) {
absorbBlockBlake2Safe(state, ptrWord); //absorbs each block of pad(pwd || salt || basil)
ptrWord += BLOCK_LEN_BLAKE2_SAFE_INT64; //goes to next block of pad(pwd || salt || basil)
}
//Initializes M[0] and M[1]
reducedSqueezeRow0(state, memMatrix[0], nCols); //The locally copied password is most likely overwritten here
reducedDuplexRow1(state, memMatrix[0], memMatrix[1], nCols);
do {
//M[row] = rand; //M[row*] = M[row*] XOR rotW(rand)
reducedDuplexRowSetup(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols);
//updates the value of row* (deterministically picked during Setup))
rowa = (rowa + step) & (window - 1);
//update prev: it now points to the last row ever computed
prev = row;
//updates row: goes to the next row to be computed
row++;
//Checks if all rows in the window where visited.
if (rowa == 0) {
step = window + gap; //changes the step: approximately doubles its value
window *= 2; //doubles the size of the re-visitation window
gap = -gap; //inverts the modifier to the step
}
} while (row < nRows);
//==========================================================================/
//============================ Wandering Phase =============================//
row = 0; //Resets the visitation to the first row of the memory matrix
for (tau = 1; tau <= timeCost; tau++) {
//Step is approximately half the number of all rows of the memory matrix for an odd tau; otherwise, it is -1
step = (tau % 2 == 0) ? -1 : nRows / 2 - 1;
do {
//Selects a pseudorandom index row*
//------------------------------------------------------------------------------------------
//rowa = ((unsigned int)state[0]) & (nRows-1); //(USE THIS IF nRows IS A POWER OF 2)
rowa = ((uint64_t) (state[0])) % nRows; //(USE THIS FOR THE "GENERIC" CASE)
//------------------------------------------------------------------------------------------
//Performs a reduced-round duplexing operation over M[row*] XOR M[prev], updating both M[row*] and M[row]
reducedDuplexRow(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols);
//update prev: it now points to the last row ever computed
prev = row;
//updates row: goes to the next row to be computed
//------------------------------------------------------------------------------------------
//row = (row + step) & (nRows-1); //(USE THIS IF nRows IS A POWER OF 2)
row = (row + step) % nRows; //(USE THIS FOR THE "GENERIC" CASE)
//------------------------------------------------------------------------------------------
} while (row != 0);
}
//==========================================================================/
//============================ Wrap-up Phase ===============================//
//Absorbs the last block of the memory matrix
absorbBlock(state, memMatrix[rowa]);
//Squeezes the key
squeeze(state, K, kLen);
//==========================================================================/
//========================= Freeing the memory =============================//
free(memMatrix);
free(wholeMatrix);
//Wiping out the sponge's internal state before freeing it
memset(state, 0, 16 * sizeof (uint64_t));
free(state);
//==========================================================================/
return 0;
}

55
stratum/algos/Lyra2-zz.h Normal file
View file

@ -0,0 +1,55 @@
/**
* Header file for the Lyra2 Password Hashing Scheme (PHS).
*
* Author: The Lyra PHC team (http://www.lyra-kdf.net/) -- 2014.
*
* This software is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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.
*/
#ifndef LYRA2ZZ_H_
#define LYRA2ZZ_H_
#include <stdint.h>
typedef unsigned char byte;
//Block length required so Blake2's Initialization Vector (IV) is not overwritten (THIS SHOULD NOT BE MODIFIED)
#define BLOCK_LEN_BLAKE2_SAFE_INT64 12 //768 bits (=96 bytes, =12 uint64_t)
#define BLOCK_LEN_BLAKE2_SAFE_BYTES (BLOCK_LEN_BLAKE2_SAFE_INT64 * 8) //same as above, in bytes
#define LYRA2ZZ_BLOCK_HEADER_LEN_BYTES 112
#define LYRA2ZZ_BLOCK_HEADER_NONCE_OFFSET 19 /* 19 * 4 bytes */
#define LYRA2ZZ_BLOCK_HEADER_UINT32_LEN 32
#ifdef BLOCK_LEN_BITS
#define BLOCK_LEN_INT64 (BLOCK_LEN_BITS/64) //Block length: 1024 bits (=128 bytes, =16 uint64_t)
#define BLOCK_LEN_BYTES (BLOCK_LEN_BITS/8) //Block length, in bytes
#else //default block length: 1024 bits
#define BLOCK_LEN_INT64 16 //Block length: 1024 bits (=128 bytes, =16 uint64_t)
#define BLOCK_LEN_BYTES (BLOCK_LEN_INT64 * 8) //Block length, in bytes
#endif
#ifdef __cplusplus
extern "C" {
#endif
int LYRA2ZZ(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *salt, uint64_t saltlen, uint64_t timeCost, uint64_t nRows, uint64_t nCols);
#ifdef __cplusplus
}
#endif
#endif /* LYRA2ZZ_H_ */

View file

@ -44,7 +44,7 @@
* *
* @return 0 if the key is generated correctly; -1 if there is an error (usually due to lack of memory for allocation) * @return 0 if the key is generated correctly; -1 if there is an error (usually due to lack of memory for allocation)
*/ */
int LYRA2(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int64_t nRows, const int16_t nCols) int LYRA2(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int16_t nRows, const int16_t nCols)
{ {
//============================= Basic variables ============================// //============================= Basic variables ============================//
int64_t row = 2; //index of row to be processed int64_t row = 2; //index of row to be processed
@ -212,3 +212,175 @@ int LYRA2(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *sa
return 0; return 0;
} }
int LYRA2_3(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int16_t nRows, const int16_t nCols)
{
//============================= Basic variables ============================//
int64_t row = 2; //index of row to be processed
int64_t prev = 1; //index of prev (last row ever computed/modified)
int64_t rowa = 0; //index of row* (a previous row, deterministically picked during Setup and randomly picked while Wandering)
int64_t tau; //Time Loop iterator
int64_t step = 1; //Visitation step (used during Setup and Wandering phases)
int64_t window = 2; //Visitation window (used to define which rows can be revisited during Setup)
int64_t gap = 1; //Modifier to the step, assuming the values 1 or -1
int64_t i; //auxiliary iteration counter
int64_t v64; // 64bit var for memcpy
uint64_t instance = 0;
//==========================================================================/
//========== Initializing the Memory Matrix and pointers to it =============//
//Tries to allocate enough space for the whole memory matrix
const int64_t ROW_LEN_INT64 = BLOCK_LEN_INT64 * nCols;
const int64_t ROW_LEN_BYTES = ROW_LEN_INT64 * 8;
const int64_t BLOCK_LEN = BLOCK_LEN_BLAKE2_SAFE_INT64;
size_t sz = (size_t)ROW_LEN_BYTES * nRows;
uint64_t *wholeMatrix = malloc(sz);
if (wholeMatrix == NULL) {
return -1;
}
memset(wholeMatrix, 0, sz);
//Allocates pointers to each row of the matrix
uint64_t **memMatrix = malloc(sizeof(uint64_t*) * nRows);
if (memMatrix == NULL) {
return -1;
}
//Places the pointers in the correct positions
uint64_t *ptrWord = wholeMatrix;
for (i = 0; i < nRows; i++) {
memMatrix[i] = ptrWord;
ptrWord += ROW_LEN_INT64;
}
//==========================================================================/
//============= Getting the password + salt + basil padded with 10*1 ===============//
//OBS.:The memory matrix will temporarily hold the password: not for saving memory,
//but this ensures that the password copied locally will be overwritten as soon as possible
//First, we clean enough blocks for the password, salt, basil and padding
int64_t nBlocksInput = ((saltlen + pwdlen + 6 * sizeof(uint64_t)) / BLOCK_LEN_BLAKE2_SAFE_BYTES) + 1;
byte *ptrByte = (byte*) wholeMatrix;
//Prepends the password
memcpy(ptrByte, pwd, pwdlen);
ptrByte += pwdlen;
//Concatenates the salt
memcpy(ptrByte, salt, saltlen);
ptrByte += saltlen;
memset(ptrByte, 0, (size_t) (nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES - (saltlen + pwdlen)));
//Concatenates the basil: every integer passed as parameter, in the order they are provided by the interface
memcpy(ptrByte, &kLen, sizeof(int64_t));
ptrByte += sizeof(uint64_t);
v64 = pwdlen;
memcpy(ptrByte, &v64, sizeof(int64_t));
ptrByte += sizeof(uint64_t);
v64 = saltlen;
memcpy(ptrByte, &v64, sizeof(int64_t));
ptrByte += sizeof(uint64_t);
v64 = timeCost;
memcpy(ptrByte, &v64, sizeof(int64_t));
ptrByte += sizeof(uint64_t);
v64 = nRows;
memcpy(ptrByte, &v64, sizeof(int64_t));
ptrByte += sizeof(uint64_t);
v64 = nCols;
memcpy(ptrByte, &v64, sizeof(int64_t));
ptrByte += sizeof(uint64_t);
//Now comes the padding
*ptrByte = 0x80; //first byte of padding: right after the password
ptrByte = (byte*) wholeMatrix; //resets the pointer to the start of the memory matrix
ptrByte += nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES - 1; //sets the pointer to the correct position: end of incomplete block
*ptrByte ^= 0x01; //last byte of padding: at the end of the last incomplete block
//==========================================================================/
//======================= Initializing the Sponge State ====================//
//Sponge state: 16 uint64_t, BLOCK_LEN_INT64 words of them for the bitrate (b) and the remainder for the capacity (c)
uint64_t state[16];
initState(state);
//==========================================================================/
//================================ Setup Phase =============================//
//Absorbing salt, password and basil: this is the only place in which the block length is hard-coded to 512 bits
ptrWord = wholeMatrix;
for (i = 0; i < nBlocksInput; i++) {
absorbBlockBlake2Safe(state, ptrWord); //absorbs each block of pad(pwd || salt || basil)
ptrWord += BLOCK_LEN; //goes to next block of pad(pwd || salt || basil)
}
//Initializes M[0] and M[1]
reducedSqueezeRow0(state, memMatrix[0], nCols); //The locally copied password is most likely overwritten here
reducedDuplexRow1(state, memMatrix[0], memMatrix[1], nCols);
do {
//M[row] = rand; //M[row*] = M[row*] XOR rotW(rand)
reducedDuplexRowSetup(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols);
//updates the value of row* (deterministically picked during Setup))
rowa = (rowa + step) & (window - 1);
//update prev: it now points to the last row ever computed
prev = row;
//updates row: goes to the next row to be computed
row++;
//Checks if all rows in the window where visited.
if (rowa == 0) {
step = window + gap; //changes the step: approximately doubles its value
window *= 2; //doubles the size of the re-visitation window
gap = -gap; //inverts the modifier to the step
}
} while (row < nRows);
//==========================================================================/
//============================ Wandering Phase =============================//
row = 0; //Resets the visitation to the first row of the memory matrix
for (tau = 1; tau <= timeCost; tau++) {
//Step is approximately half the number of all rows of the memory matrix for an odd tau; otherwise, it is -1
step = ((tau & 1) == 0) ? -1 : (nRows >> 1) - 1;
do {
//Selects a pseudorandom index row*
//------------------------------------------------------------------------------------------
instance = state[instance & 0xF];
rowa = state[instance & 0xF] & (unsigned int)(nRows-1);
//rowa = state[0] & (unsigned int)(nRows-1); //(USE THIS IF nRows IS A POWER OF 2)
//rowa = state[0] % nRows; //(USE THIS FOR THE "GENERIC" CASE)
//------------------------------------------------------------------------------------------
//Performs a reduced-round duplexing operation over M[row*] XOR M[prev], updating both M[row*] and M[row]
reducedDuplexRow(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols);
//update prev: it now points to the last row ever computed
prev = row;
//updates row: goes to the next row to be computed
//------------------------------------------------------------------------------------------
row = (row + step) & (unsigned int)(nRows-1); //(USE THIS IF nRows IS A POWER OF 2)
//row = (row + step) % nRows; //(USE THIS FOR THE "GENERIC" CASE)
//------------------------------------------------------------------------------------------
} while (row != 0);
}
//============================ Wrap-up Phase ===============================//
//Absorbs the last block of the memory matrix
absorbBlock(state, memMatrix[rowa]);
//Squeezes the key
squeeze(state, K, (unsigned int) kLen);
//========================= Freeing the memory =============================//
free(memMatrix);
free(wholeMatrix);
return 0;
}

View file

@ -37,6 +37,8 @@ typedef unsigned char byte;
#define BLOCK_LEN_BYTES (BLOCK_LEN_INT64 * 8) //Block length, in bytes #define BLOCK_LEN_BYTES (BLOCK_LEN_INT64 * 8) //Block length, in bytes
#endif #endif
int LYRA2(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int64_t nRows, const int16_t nCols); int LYRA2(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int16_t nRows, const int16_t nCols);
int LYRA2_3(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int16_t nRows, const int16_t nCols);
#endif /* LYRA2_H_ */ #endif /* LYRA2_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,73 @@
///////////////////////////////////////////////////////////////////////////////////////////////
//
// SWIFFTX ANSI C OPTIMIZED 32BIT IMPLEMENTATION FOR NIST SHA-3 COMPETITION
//
// SWIFFTX.h
//
// October 2008
//
// This file is the exact copy from the reference implementation.
//
///////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __SWIFFTX__
#define __SWIFFTX__
#ifdef __cplusplus
extern "C"{
#endif
// See the remarks concerning compatibility issues inside stdint.h.
#include "stdint.h"
#include "stdbool.h"
// The size of SWIFFTX input in bytes.
#define SWIFFTX_INPUT_BLOCK_SIZE 256
// The size of output block in bytes. The compression function of SWIFFT outputs a block of
// this size (i.e., this is the size of the resulting hash value).
#define SWIFFTX_OUTPUT_BLOCK_SIZE 65
// Computes the result of a single SWIFFT operation.
// This is the simple implementation, where our main concern is to show our design principles.
// It is made more efficient in the optimized version, by using FFT instead of DFT, and
// through other speed-up techniques.
//
// Parameters:
// - input: the input string. Consists of 8*m input bytes, where each octet passes the DFT
// processing.
// - m: the length of the input in bytes.
// - output: the resulting hash value of SWIFFT, of size 65 bytes (520 bit). This is the
// result of summing the dot products of the DFTS with the A's after applying the base
// change transformation
// - A: the A's coefficients to work with (since every SWIFFT in SWIFFTX uses different As).
// A single application of SWIFFT uses 64*m A's.
void ComputeSingleSWIFFT(unsigned char *input, unsigned short m,
unsigned char output[SWIFFTX_OUTPUT_BLOCK_SIZE],
const swift_int16_t *a);
// Computes the result of a single SWIFFTX operation.
// NOTE: for simplicity we use 'ComputeSingleSWIFFT()' as a subroutine. This is only to show
// the design idea. In the optimized versions we don't do this for efficiency concerns, since
// there we compute the first part (which doesn't involve the A coefficients) only once for all
// of the 3 invocations of SWIFFT. This enables us to introduce a significant speedup.
//
// Parameters:
// - input: the input input of 256 bytes (2048 bit).
// - output: the resulting hash value of SWIFFT, of size 64 bytes (512 bit).
// - doSMooth: if true, a final smoothing stage is performed and the output is of size 512 bits.
//
// Returns:
// - Success value.
void ComputeSingleSWIFFTX(unsigned char input[SWIFFTX_INPUT_BLOCK_SIZE],
unsigned char output[SWIFFTX_OUTPUT_BLOCK_SIZE],
bool doSmooth);
// Calculates the powers of OMEGA and generates the bit reversal permutation.
// You must call this function before doing SWIFFT/X, otherwise you will get zeroes everywhere.
void InitializeSWIFFTX();
#ifdef __cplusplus
}
#endif
#endif // __SWIFFTX__

View file

@ -0,0 +1,39 @@
/*
inttypes.h
Contributors:
Created by Marek Michalkiewicz <marekm@linux.org.pl>
THIS SOFTWARE IS NOT COPYRIGHTED
This source code is offered for use in the public domain. You may
use, modify or distribute it freely.
This code is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
DISCLAIMED. This includes but is not limited to warranties of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __INTTYPES_H_
#define __INTTYPES_H_
/* Use [u]intN_t if you need exactly N bits.
XXX - doesn't handle the -mint8 option. */
typedef signed char swift_int8_t;
typedef unsigned char swift_uint8_t;
typedef int swift_int16_t;
typedef unsigned int swift_uint16_t;
typedef long swift_int32_t;
typedef unsigned long swift_uint32_t;
typedef long long swift_int64_t;
typedef unsigned long long swift_uint64_t;
//typedef swift_int16_t intptr_t;
//typedef swift_uint16_t uintptr_t;
#endif

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2000 Jeroen Ruigrok van der Werven <asmodai@FreeBSD.org>
* 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/include/stdbool.h,v 1.6 2002/08/16 07:33:14 alfred Exp $
*/
#ifndef _STDBOOL_H_
#define _STDBOOL_H_
#define __bool_true_false_are_defined 1
#ifndef __cplusplus
#define false 0
#define true 1
#define bool _Bool
#if __STDC_VERSION__ < 199901L && __GNUC__ < 3
typedef int _Bool;
#endif
#endif /* !__cplusplus */
#endif /* !_STDBOOL_H_ */

View file

@ -0,0 +1,54 @@
#ifndef _SWIFFT_STDINT_H
#define _SWIFFT_STDINT_H
///////////////////////////////////////////////////////////////////////////////////////////////
//
// A note from SWIFFTX implementers:
//
// Although the submission was targeted for Microsoft Visual Studio 2005 compiler, we strived
// to make the code as portable as possible. This is why we preferred to use the types defined
// here, instead of Microsoft-specific types. We compiled the code with gcc to make this sure.
// However, we couldn't use this header as is, due to VS2005 compiler objections. This is why
// we commented out certain defines and clearly marked it.
// To compile our code on gcc you may define SYS_STDINT.
//
///////////////////////////////////////////////////////////////////////////////////////////////
#ifdef SYS_STDINT
#include <stdint.h>
#else
#include "inttypes.h"
// The following was commented out by SWIFFTX implementers:
// __BEGIN_DECLS
typedef swift_int8_t swifftx_int_least8_t;
typedef swift_int16_t swifftx_int_least16_t;
typedef swift_int32_t swifftx_int_least32_t;
typedef swift_uint8_t swifftx_uint_least8_t;
typedef swift_uint16_t swifftx_uint_least16_t;
typedef swift_uint32_t swifftx_uint_least32_t;
#ifndef __STRICT_ANSI__
typedef swift_int64_t swifftx_int_least64_t;
typedef swift_uint64_t swifftx_uint_least64_t;
#endif
/*typedef signed char int_fast8_t;
typedef signed long int int_fast16_t;
typedef signed long int int_fast32_t;
typedef signed long long int int_fast64_t;
typedef unsigned char uint_fast8_t;
typedef unsigned long int uint_fast16_t;
typedef unsigned long int uint_fast32_t;
typedef unsigned long long int uint_fast64_t;*/
// The following was commented out by SWIFFTX implementers:
// #include <endian.h>
// __END_DECLS
#endif
#endif

260
stratum/algos/a5a.c Normal file
View file

@ -0,0 +1,260 @@
#include <float.h>
#include <math.h>
#include <gmp.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "a5amath.h"
#include "../sha3/sph_sha2.h"
#include "../sha3/sph_keccak.h"
#include "../sha3/sph_whirlpool.h"
#include "../sha3/sph_ripemd.h"
static void mpz_set_uint256(mpz_t r, uint8_t *u)
{
mpz_import(r, 32 / sizeof(unsigned long), -1, sizeof(unsigned long), -1, 0, u);
}
static void mpz_get_uint256(mpz_t r, uint8_t *u)
{
u=0;
mpz_export(u, 0, -1, sizeof(unsigned long), -1, 0, r);
}
static void mpz_set_uint512(mpz_t r, uint8_t *u)
{
mpz_import(r, 64 / sizeof(unsigned long), -1, sizeof(unsigned long), -1, 0, u);
}
static void set_one_if_zero(uint8_t *hash512) {
int i;
for (i = 0; i < 32; i++) {
if (hash512[i] != 0) {
return;
}
}
hash512[0] = 1;
}
#define BITS_PER_DIGIT 3.32192809488736234787
//#define EPS (std::numeric_limits<double>::epsilon())
#define EPS (DBL_EPSILON)
#define Na5a 5
#define SW_DIVS 5
//#define SW_MAX 1000
void a5a_hash(const char* input, char* output, uint32_t len)
{
unsigned int nnNonce;
uint32_t pdata[32];
memcpy(pdata, input, 80);
// memcpy(&nnNonce, input+76, 4);
int i, j, bytes, nnNonce2;
nnNonce2 = (int)(pdata[19]/2);
size_t sz = 80;
uint8_t bhash[5][64];
uint32_t hash[6];
memset(bhash, 0, 5 * 64);
sph_sha256_context ctx_final_sha256;
sph_sha256_context ctx_sha256;
sph_sha512_context ctx_sha512;
sph_keccak512_context ctx_keccak;
sph_whirlpool_context ctx_whirlpool;
sph_ripemd160_context ctx_ripemd;
sph_sha256_init(&ctx_sha256);
// ZSHA256;
sph_sha256 (&ctx_sha256, input, sz);
sph_sha256_close(&ctx_sha256, (void*)(bhash[0]));
sph_sha512_init(&ctx_sha512);
// ZSHA512;
sph_sha512 (&ctx_sha512, input, sz);
sph_sha512_close(&ctx_sha512, (void*)(bhash[1]));
sph_keccak512_init(&ctx_keccak);
// ZKECCAK;
sph_keccak512 (&ctx_keccak, input, sz);
sph_keccak512_close(&ctx_keccak, (void*)(bhash[2]));
sph_whirlpool_init(&ctx_whirlpool);
// ZWHIRLPOOL;
sph_whirlpool (&ctx_whirlpool, input, sz);
sph_whirlpool_close(&ctx_whirlpool, (void*)(bhash[3]));
sph_ripemd160_init(&ctx_ripemd);
// ZRIPEMD;
sph_ripemd160 (&ctx_ripemd, input, sz);
sph_ripemd160_close(&ctx_ripemd, (void*)(bhash[4]));
// printf("%s\n", hash[4].GetHex().c_str());
mpz_t bns[6];
for(i=0; i < 6; i++){
mpz_init(bns[i]);
}
//Take care of zeros and load gmp
for(i=0; i < 5; i++){
set_one_if_zero(bhash[i]);
mpz_set_uint512(bns[i],bhash[i]);
}
mpz_set_ui(bns[5],0);
for(i=0; i < 5; i++)
mpz_add(bns[5], bns[5], bns[i]);
mpz_t product;
mpz_init(product);
mpz_set_ui(product,1);
// mpz_pow_ui(bns[5], bns[5], 2);
for(i=0; i < 6; i++){
mpz_mul(product,product,bns[i]);
}
mpz_pow_ui(product, product, 2);
bytes = mpz_sizeinbase(product, 256);
// printf("a5a data space: %iB\n", bytes);
char *data = (char*)malloc(bytes);
mpz_export(data, NULL, -1, 1, 0, 0, product);
sph_sha256_init(&ctx_final_sha256);
// ZSHA256;
sph_sha256 (&ctx_final_sha256, data, bytes);
sph_sha256_close(&ctx_final_sha256, (void*)(hash));
free(data);
int digits=(int)((sqrt((double)(nnNonce2))*(1.+EPS))/9000+75);
// int iterations=(int)((sqrt((double)(nnNonce2))+EPS)/500+350); // <= 500
// int digits=100;
int iterations=20; // <= 500
mpf_set_default_prec((long int)(digits*BITS_PER_DIGIT+16));
mpz_t a5api;
mpz_t a5asw;
mpf_t a5afpi;
mpf_t mpa1, mpb1, mpt1, mpp1;
mpf_t mpa2, mpb2, mpt2, mpp2;
mpf_t mpsft;
mpz_init(a5api);
mpz_init(a5asw);
mpf_init(a5afpi);
mpf_init(mpsft);
mpf_init(mpa1);
mpf_init(mpb1);
mpf_init(mpt1);
mpf_init(mpp1);
mpf_init(mpa2);
mpf_init(mpb2);
mpf_init(mpt2);
mpf_init(mpp2);
uint32_t usw_;
usw_ = sw_(nnNonce2, SW_DIVS);
if (usw_ < 1) usw_ = 1;
// if(fDebuga5a) printf("usw_: %d\n", usw_);
mpz_set_ui(a5asw, usw_);
uint32_t mpzscale=mpz_size(a5asw);
for(i=0; i < Na5a; i++)
{
if (mpzscale > 1000) {
mpzscale = 1000;
}
else if (mpzscale < 1) {
mpzscale = 1;
}
// if(fDebuga5a) printf("mpzscale: %d\n", mpzscale);
mpf_set_ui(mpa1, 1);
mpf_set_ui(mpb1, 2);
mpf_set_d(mpt1, 0.25*mpzscale);
mpf_set_ui(mpp1, 1);
mpf_sqrt(mpb1, mpb1);
mpf_ui_div(mpb1, 1, mpb1);
mpf_set_ui(mpsft, 10);
for(j=0; j <= iterations; j++)
{
mpf_add(mpa2, mpa1, mpb1);
mpf_div_ui(mpa2, mpa2, 2);
mpf_mul(mpb2, mpa1, mpb1);
mpf_abs(mpb2, mpb2);
mpf_sqrt(mpb2, mpb2);
mpf_sub(mpt2, mpa1, mpa2);
mpf_abs(mpt2, mpt2);
mpf_sqrt(mpt2, mpt2);
mpf_mul(mpt2, mpt2, mpp1);
mpf_sub(mpt2, mpt1, mpt2);
mpf_mul_ui(mpp2, mpp1, 2);
mpf_swap(mpa1, mpa2);
mpf_swap(mpb1, mpb2);
mpf_swap(mpt1, mpt2);
mpf_swap(mpp1, mpp2);
}
mpf_add(a5afpi, mpa1, mpb1);
mpf_pow_ui(a5afpi, a5afpi, 2);
mpf_div_ui(a5afpi, a5afpi, 4);
mpf_abs(mpt1, mpt1);
mpf_div(a5afpi, a5afpi, mpt1);
// mpf_out_str(stdout, 10, digits+2, a5afpi);
mpf_pow_ui(mpsft, mpsft, digits/2);
mpf_mul(a5afpi, a5afpi, mpsft);
mpz_set_f(a5api, a5afpi);
//mpz_set_ui(a5api,1);
mpz_add(product,product,a5api);
mpz_add(product,product,a5asw);
mpz_set_uint256(bns[0], (void*)(hash));
mpz_add(bns[5], bns[5], bns[0]);
mpz_mul(product,product,bns[5]);
mpz_cdiv_q (product, product, bns[0]);
if (mpz_sgn(product) <= 0) mpz_set_ui(product,1);
bytes = mpz_sizeinbase(product, 256);
mpzscale=bytes;
// printf("a5a data space: %iB\n", bytes);
char *bdata = (char*)malloc(bytes);
mpz_export(bdata, NULL, -1, 1, 0, 0, product);
sph_sha256_init(&ctx_final_sha256);
// ZSHA256;
sph_sha256 (&ctx_final_sha256, bdata, bytes);
sph_sha256_close(&ctx_final_sha256, (void*)(hash));
free(bdata);
}
//Free the memory
for(i=0; i < 6; i++){
mpz_clear(bns[i]);
}
// mpz_clear(dSpectralWeight);
mpz_clear(product);
mpz_clear(a5api);
mpz_clear(a5asw);
mpf_clear(a5afpi);
mpf_clear(mpsft);
mpf_clear(mpa1);
mpf_clear(mpb1);
mpf_clear(mpt1);
mpf_clear(mpp1);
mpf_clear(mpa2);
mpf_clear(mpb2);
mpf_clear(mpt2);
mpf_clear(mpp2);
memcpy(output, hash, 32);
}

14
stratum/algos/a5a.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef SCRYPT_H
#define SCRYPT_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void a5a_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

116
stratum/algos/a5amath.c Normal file
View file

@ -0,0 +1,116 @@
// Copyright (c) 2014 The a5a developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <stdio.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
//#include <gmpxx.h>
#include "a5amath.h"
//#define EPS1 (std::numeric_limits<double>::epsilon())
#define EPS1 (DBL_EPSILON)
#define EPS2 3.0e-11
double exp_n(double xt)
{
double p1 = -700.0, p3 = -0.8e-8, p4 = 0.8e-8, p6 = 700.0;
if(xt < p1)
return 0;
else if(xt > p6)
return 1e200;
else if(xt > p3 && xt < p4)
return (1.0 + xt);
else
return exp(xt);
}
// 1 / (1 + exp(x1-x2))
double exp_n2(double x1, double x2)
{
double p1 = -700., p2 = -37., p3 = -0.8e-8, p4 = 0.8e-8, p5 = 37., p6 = 700.;
double xt = x1 - x2;
if (xt < p1+1.e-200)
return 1.;
else if (xt > p1 && xt < p2 + 1.e-200)
return ( 1. - exp(xt) );
else if (xt > p2 && xt < p3 + 1.e-200)
return ( 1. / (1. + exp(xt)) );
else if (xt > p3 && xt < p4)
return ( 1. / (2. + xt) );
else if (xt > p4 - 1.e-200 && xt < p5)
return ( exp(-xt) / (1. + exp(-xt)) );
else if (xt > p5 - 1.e-200 && xt < p6)
return ( exp(-xt) );
else if (xt > p6 - 1.e-200)
return 0.;
}
void gauleg(double x1, double x2, double x[], double w[], int n)
{
int m,j,i;
double z1, z, xm, xl, pp, p3, p2, p1;
m=(n+1)/2;
xm=0.5*(x2+x1);
xl=0.5*(x2-x1);
for (i=1;i<=m;i++) {
z=cos(3.141592654*(i-0.25)/(n+0.5));
do {
p1=1.0;
p2=0.0;
for (j=1;j<=n;j++) {
p3=p2;
p2=p1;
p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
}
pp=n*(z*p1-p2)/(z*z-1.0);
z1=z;
z=z1-p1/pp;
} while (fabs(z-z1) > EPS2);
x[i]=xm-xl*z;
x[n+1-i]=xm+xl*z;
w[i]=2.0*xl/((1.0-z*z)*pp*pp);
w[n+1-i]=w[i];
}
}
double GaussianQuad_N(double func(const double), const double a2, const double b2, int NptGQ)
{
double s=0.0;
double x[NptGQ], w[NptGQ];
int j;
// double dh=(b2-a2)/double(divs);
gauleg(a2, b2, x, w, NptGQ);
for (j=1; j<=NptGQ; j++) {
s += w[j]*func(x[j]);
}
/*
for (i=1; i<=divs; i++)
{
a0 = a2 + (i-1)*dh;
b0 = a0 + dh;
gauleg(a0, b0, x, w, NptGQ);
for (j=1; j<=NptGQ; j++)
{
s += w[j]*func(x[j]);
}
}
*/
return s;
}
double swit_(double wvnmb)
{
return pow( (5.55243*(exp_n(-0.3*wvnmb/15.762) - exp_n(-0.6*wvnmb/15.762)))*wvnmb, 0.5)
/ 1034.66 * pow(sin(wvnmb/65.), 2.);
}
uint32_t sw_(int nnounce, int divs)
{
double wmax = ((sqrt((double)(nnounce))*(1.+EPS1))/450+100);
return ((uint32_t)(GaussianQuad_N(swit_, 0., wmax, divs)*(1.+EPS1)*1.e6));
}

16
stratum/algos/a5amath.h Normal file
View file

@ -0,0 +1,16 @@
// Copyright (c) 2014 The a5a developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef a5a_MATH_H
#define a5a_MATH_H
double exp_n(double xt);
double exp_n2(double x1, double x2);
void gauleg(double x1, double x2, double x[], double w[], int n);
double GaussianQuad_N(double func(const double), const double a2, const double b2, int NptGQ);
double swit_(double wvnmb);
uint32_t sw_(int nnounce, int divs);
#endif

162
stratum/algos/aergo.c Normal file
View file

@ -0,0 +1,162 @@
#include "aergo.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_groestl.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_keccak.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_shavite.h>
#include <sha3/sph_simd.h>
#include <sha3/sph_echo.h>
#include <sha3/sph_hamsi.h>
#include <sha3/sph_fugue.h>
#include <sha3/sph_shabal.h>
#include <sha3/sph_whirlpool.h>
#include <sha3/sph_haval.h>
#include "gost.h"
#include "common.h"
void aergo_hash(const char* input, char* output, uint32_t len)
{
uint32_t hash[16];
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_skein512_context ctx_skein;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
sph_shavite512_context ctx_shavite;
sph_simd512_context ctx_simd;
sph_echo512_context ctx_echo;
sph_hamsi512_context ctx_hamsi;
sph_fugue512_context ctx_fugue;
sph_shabal512_context ctx_shabal;
sph_gost512_context ctx_gost;
sph_whirlpool_context ctx_whirlpool;
sph_haval256_5_context ctx_haval;
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, input, len);
sph_echo512_close(&ctx_echo, hash);
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, hash, 64);
sph_blake512_close(&ctx_blake, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool(&ctx_whirlpool, hash, 64);
sph_whirlpool_close(&ctx_whirlpool, hash);
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, hash, 64);
sph_groestl512_close(&ctx_groestl, hash);
sph_gost512_init(&ctx_gost);
sph_gost512(&ctx_gost, hash, 64);
sph_gost512_close(&ctx_gost, hash);
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, hash, 64);
sph_keccak512_close(&ctx_keccak, hash);
sph_gost512_init(&ctx_gost);
sph_gost512(&ctx_gost, hash, 64);
sph_gost512_close(&ctx_gost, hash);
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, hash, 64);
sph_cubehash512_close(&ctx_cubehash, hash);
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
sph_hamsi512_init(&ctx_hamsi);
sph_hamsi512(&ctx_hamsi, hash, 64);
sph_hamsi512_close(&ctx_hamsi, hash);
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, hash, 64);
sph_fugue512_close(&ctx_fugue, hash);
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, hash, 64);
sph_shabal512_close(&ctx_shabal, hash);
sph_haval256_5_init(&ctx_haval);
sph_haval256_5(&ctx_haval,(const void*) hash, 64);
sph_haval256_5_close(&ctx_haval, hash);
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_gost512_init(&ctx_gost);
sph_gost512(&ctx_gost, hash, 64);
sph_gost512_close(&ctx_gost, hash);
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, hash, 64);
sph_blake512_close(&ctx_blake, hash);
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, hash, 64);
sph_cubehash512_close(&ctx_cubehash, hash);
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
memcpy(output, hash, 32);
}

17
stratum/algos/aergo.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef AERGO_H
#define AERGO_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void aergo_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

46
stratum/algos/allium.c Normal file
View file

@ -0,0 +1,46 @@
#include <memory.h>
#include "sha3/sph_blake.h"
#include "sha3/sph_groestl.h"
#include "sha3/sph_skein.h"
#include "sha3/sph_keccak.h"
#include "sha3/sph_cubehash.h"
#include "Lyra2.h"
void allium_hash(const char* input, char* output, uint32_t len)
{
uint32_t hashA[8], hashB[8];
sph_blake256_context ctx_blake;
sph_keccak256_context ctx_keccak;
sph_cubehash512_context ctx_cubehash;
sph_skein256_context ctx_skein;
sph_groestl256_context ctx_groestl;
sph_blake256_init(&ctx_blake);
sph_blake256(&ctx_blake, input, 80);
sph_blake256_close(&ctx_blake, hashA);
sph_keccak256_init(&ctx_keccak);
sph_keccak256(&ctx_keccak, hashA, 32);
sph_keccak256_close(&ctx_keccak, hashB);
LYRA2(hashA, 32, hashB, 32, hashB, 32, 1, 8, 8);
sph_cubehash256_init(&ctx_cubehash);
sph_cubehash256(&ctx_cubehash, hashA, 32);
sph_cubehash256_close(&ctx_cubehash, hashB);
LYRA2(hashA, 32, hashB, 32, hashB, 32, 1, 8, 8);
sph_skein256_init(&ctx_skein);
sph_skein256(&ctx_skein, hashA, 32);
sph_skein256_close(&ctx_skein, hashB);
sph_groestl256_init(&ctx_groestl);
sph_groestl256(&ctx_groestl, hashB, 32);
sph_groestl256_close(&ctx_groestl, hashA);
memcpy(output, hashA, 32);
}

16
stratum/algos/allium.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef ALLIUM_H
#define ALLIUM_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void allium_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,279 +1,378 @@
/* /*
* Argon2 source code package * Argon2 reference source code package - reference C implementations
* *
* Written by Daniel Dinu and Dmitry Khovratovich, 2015 * Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
* *
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver. * You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
* *
* You should have received a copy of the CC0 Public Domain Dedication along * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* with * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* this software. If not, see *
* <http://creativecommons.org/publicdomain/zero/1.0/>. * You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/ */
#include <stdint.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <limits.h>
#include "argon2.h" #include "argon2.h"
#include "cores.h" #include "encoding.h"
#include "core.h"
/* Error messages */ const char *argon2_type2string(argon2_type type, int uppercase) {
static const char *Argon2_ErrorMessage[] = { switch (type) {
/*{ARGON2_OK, */ "OK", case Argon2_d:
/*}, return uppercase ? "Argon2d" : "argon2d";
}
{ARGON2_OUTPUT_PTR_NULL, */ "Output pointer is NULL", return NULL;
/*}, }
{ARGON2_OUTPUT_TOO_SHORT, */ "Output is too short", int argon2_ctx(argon2_context *context, argon2_type type) {
/*}, /* 1. Validate all inputs */
{ARGON2_OUTPUT_TOO_LONG, */ "Output is too long", int result = validate_inputs(context);
/*}, uint32_t memory_blocks, segment_length;
argon2_instance_t instance;
{ARGON2_PWD_TOO_SHORT, */ "Password is too short",
/*},
{ARGON2_PWD_TOO_LONG, */ "Password is too long",
/*},
{ARGON2_SALT_TOO_SHORT, */ "Salt is too short",
/*},
{ARGON2_SALT_TOO_LONG, */ "Salt is too long",
/*},
{ARGON2_AD_TOO_SHORT, */ "Associated data is too short",
/*},
{ARGON2_AD_TOO_LONG, */ "Associated date is too long",
/*},
{ARGON2_SECRET_TOO_SHORT, */ "Secret is too short",
/*},
{ARGON2_SECRET_TOO_LONG, */ "Secret is too long",
/*},
{ARGON2_TIME_TOO_SMALL, */ "Time cost is too small",
/*},
{ARGON2_TIME_TOO_LARGE, */ "Time cost is too large",
/*},
{ARGON2_MEMORY_TOO_LITTLE, */ "Memory cost is too small",
/*},
{ARGON2_MEMORY_TOO_MUCH, */ "Memory cost is too large",
/*},
{ARGON2_LANES_TOO_FEW, */ "Too few lanes",
/*},
{ARGON2_LANES_TOO_MANY, */ "Too many lanes",
/*},
{ARGON2_PWD_PTR_MISMATCH, */ "Password pointer is NULL, but password length is not 0",
/*},
{ARGON2_SALT_PTR_MISMATCH, */ "Salt pointer is NULL, but salt length is not 0",
/*},
{ARGON2_SECRET_PTR_MISMATCH, */ "Secret pointer is NULL, but secret length is not 0",
/*},
{ARGON2_AD_PTR_MISMATCH, */ "Associated data pointer is NULL, but ad length is not 0",
/*},
{ARGON2_MEMORY_ALLOCATION_ERROR, */ "Memory allocation error",
/*},
{ARGON2_FREE_MEMORY_CBK_NULL, */ "The free memory callback is NULL",
/*},
{ARGON2_ALLOCATE_MEMORY_CBK_NULL, */ "The allocate memory callback is NULL",
/*},
{ARGON2_INCORRECT_PARAMETER, */ "Argon2_Context context is NULL",
/*},
{ARGON2_INCORRECT_TYPE, */ "There is no such version of Argon2",
/*},
{ARGON2_OUT_PTR_MISMATCH, */ "Output pointer mismatch",
/*},
{ARGON2_THREADS_TOO_FEW, */ "Not enough threads",
/*},
{ARGON2_THREADS_TOO_MANY, */ "Too many threads",
/*},
{ARGON2_MISSING_ARGS, */ "Missing arguments", /*},*/
};
int argon2d(argon2_context *context) { return argon2_core(context, Argon2_d); }
int argon2i(argon2_context *context) { return argon2_core(context, Argon2_i); }
int verify_d(argon2_context *context, const char *hash) {
int result;
/*if (0 == context->outlen || NULL == hash) {
return ARGON2_OUT_PTR_MISMATCH;
}*/
result = argon2_core(context, Argon2_d);
if (ARGON2_OK != result) { if (ARGON2_OK != result) {
return result; return result;
} }
return 0 == memcmp(hash, context->out, 32); if (Argon2_d != type) {
return ARGON2_INCORRECT_TYPE;
} }
const char *error_message(int error_code) { /* 2. Align memory size */
enum { /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */
/* Make sure---at compile time---that the enum size matches the array memory_blocks = context->m_cost;
size */
ERROR_STRING_CHECK = if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) {
1 / memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
!!((sizeof(Argon2_ErrorMessage) / sizeof(Argon2_ErrorMessage[0])) ==
ARGON2_ERROR_CODES_LENGTH)
};
if (error_code < ARGON2_ERROR_CODES_LENGTH) {
return Argon2_ErrorMessage[(argon2_error_codes)error_code];
}
return "Unknown error code.";
} }
/* encoding/decoding helpers */ segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
/* Ensure that all segments have equal length */
memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
/* instance.memory = NULL;
* Some macros for constant-time comparisons. These work over values in instance.passes = context->t_cost;
* the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true". instance.memory_blocks = memory_blocks;
instance.segment_length = segment_length;
instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
instance.lanes = context->lanes;
instance.threads = context->threads;
instance.type = type;
if (instance.threads > instance.lanes) {
instance.threads = instance.lanes;
}
/* 3. Initialization: Hashing inputs, allocating memory, filling first
* blocks
*/ */
#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF) result = initialize(&instance, context);
#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
#define GE(x, y) (GT(y, x) ^ 0xFF)
#define LT(x, y) GT(y, x)
#define LE(x, y) GE(y, x)
/* if (ARGON2_OK != result) {
* Convert value x (0..63) to corresponding Base64 character. return result;
*/
static int b64_byte_to_char(unsigned x) {
return (LT(x, 26) & (x + 'A')) |
(GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
(GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
(EQ(x, 63) & '/');
} }
/* /* 4. Filling memory */
* Convert some bytes to Base64. 'dst_len' is the length (in characters) result = fill_memory_blocks(&instance);
* of the output buffer 'dst'; if that buffer is not large enough to
* receive the result (including the terminating 0), then (size_t)-1
* is returned. Otherwise, the zero-terminated Base64 string is written
* in the buffer, and the output length (counted WITHOUT the terminating
* zero) is returned.
*/
static size_t to_base64(char *dst, size_t dst_len, const void *src) {
size_t olen;
const unsigned char *buf;
unsigned acc, acc_len;
olen = 43; if (ARGON2_OK != result) {
/*switch (32 % 3) { return result;
case 2:
olen++;*/
/* fall through */
/*case 1:
olen += 2;
break;
}*/
if (dst_len <= olen) {
return (size_t)-1;
} }
acc = 0; /* 5. Finalization */
acc_len = 0; finalize(context, &instance);
buf = (const unsigned char *)src;
size_t src_len = 32; return ARGON2_OK;
while (src_len-- > 0) {
acc = (acc << 8) + (*buf++);
acc_len += 8;
while (acc_len >= 6) {
acc_len -= 6;
*dst++ = b64_byte_to_char((acc >> acc_len) & 0x3F);
}
}
if (acc_len > 0) {
*dst++ = b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
}
*dst++ = 0;
return olen;
} }
/* ==================================================================== */ int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
/* const uint32_t parallelism, const void *pwd,
* Code specific to Argon2i. const size_t pwdlen, const void *salt, const size_t saltlen,
* void *hash, const size_t hashlen, char *encoded,
* The code below applies the following format: const size_t encodedlen, argon2_type type){
*
* $argon2i$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]]
*
* where <num> is a decimal integer (positive, fits in an 'unsigned long')
* and <bin> is Base64-encoded data (no '=' padding characters, no newline
* or whitespace). The "keyid" is a binary identifier for a key (up to 8
* bytes); "data" is associated data (up to 32 bytes). When the 'keyid'
* (resp. the 'data') is empty, then it is ommitted from the output.
*
* The last two binary chunks (encoded in Base64) are, in that order,
* the salt and the output. Both are optional, but you cannot have an
* output without a salt. The binary salt length is between 8 and 48 bytes.
* The output length is always exactly 32 bytes.
*/
int encode_string(char *dst, size_t dst_len, argon2_context *ctx) { argon2_context context;
#define SS(str) \ int result;
do { \ uint8_t *out;
size_t pp_len = strlen(str); \
if (pp_len >= dst_len) { \
return 0; \
} \
memcpy(dst, str, pp_len + 1); \
dst += pp_len; \
dst_len -= pp_len; \
} while (0)
#define SX(x) \ if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
do { \ return ARGON2_PWD_TOO_LONG;
char tmp[30]; \ }
sprintf(tmp, "%lu", (unsigned long)(x)); \
SS(tmp); \ if (saltlen > ARGON2_MAX_SALT_LENGTH) {
} while (0); return ARGON2_SALT_TOO_LONG;
}
#define SB(buf) \
do { \ if (hashlen > ARGON2_MAX_OUTLEN) {
size_t sb_len = to_base64(dst, dst_len, buf); \ return ARGON2_OUTPUT_TOO_LONG;
if (sb_len == (size_t)-1) { \ }
return 0; \
} \ if (hashlen < ARGON2_MIN_OUTLEN) {
dst += sb_len; \ return ARGON2_OUTPUT_TOO_SHORT;
dst_len -= sb_len; \ }
} while (0);
out = malloc(hashlen);
SS("$argon2i$m="); if (!out) {
SX(16); return ARGON2_MEMORY_ALLOCATION_ERROR;
SS(",t="); }
SX(2);
SS(",p="); context.out = (uint8_t *)out;
SX(1); context.outlen = (uint32_t)hashlen;
context.pwd = CONST_CAST(uint8_t *)pwd;
/*if (ctx->adlen > 0) { context.pwdlen = (uint32_t)pwdlen;
SS(",data="); context.salt = CONST_CAST(uint8_t *)salt;
SB(ctx->ad, ctx->adlen); context.saltlen = (uint32_t)saltlen;
}*/ context.secret = NULL;
context.secretlen = 0;
/*if (ctx->saltlen == 0) context.ad = NULL;
return 1;*/ context.adlen = 0;
context.t_cost = t_cost;
SS("$"); context.m_cost = m_cost;
SB(ctx->salt); context.lanes = parallelism;
context.threads = parallelism;
/*if (ctx->outlen32 == 0) context.allocate_cbk = NULL;
return 1;*/ context.free_cbk = NULL;
context.flags = ARGON2_DEFAULT_FLAGS;
SS("$");
SB(ctx->out); result = argon2_ctx(&context, type);
return 1;
if (result != ARGON2_OK) {
#undef SS clear_internal_memory(out, hashlen);
#undef SX free(out);
#undef SB return result;
}
/* if raw hash requested, write it */
if (hash) {
memcpy(hash, out, hashlen);
}
/* if encoding requested, write it */
if (encoded && encodedlen) {
if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) {
clear_internal_memory(out, hashlen); /* wipe buffers if error */
clear_internal_memory(encoded, encodedlen);
free(out);
return ARGON2_ENCODING_FAIL;
}
}
clear_internal_memory(out, hashlen);
free(out);
return ARGON2_OK;
}
int argon2d_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, const size_t hashlen,
char *encoded, const size_t encodedlen) {
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
NULL, hashlen, encoded, encodedlen, Argon2_d);
}
int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, void *hash, const size_t hashlen) {
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
hash, hashlen, NULL, 0, Argon2_d);
}
static int argon2_compare(const uint8_t *b1, const uint8_t *b2, size_t len) {
size_t i;
uint8_t d = 0U;
for (i = 0U; i < len; i++) {
d |= b1[i] ^ b2[i];
}
return (int)((1 & ((d - 1) >> 8)) - 1);
}
int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
argon2_type type) {
argon2_context ctx;
uint8_t *desired_result = NULL;
int ret = ARGON2_OK;
size_t encoded_len;
uint32_t max_field_len;
if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
return ARGON2_PWD_TOO_LONG;
}
if (encoded == NULL) {
return ARGON2_DECODING_FAIL;
}
encoded_len = strlen(encoded);
if (encoded_len > UINT32_MAX) {
return ARGON2_DECODING_FAIL;
}
/* No field can be longer than the encoded length */
max_field_len = (uint32_t)encoded_len;
ctx.saltlen = max_field_len;
ctx.outlen = max_field_len;
ctx.salt = malloc(ctx.saltlen);
ctx.out = malloc(ctx.outlen);
if (!ctx.salt || !ctx.out) {
ret = ARGON2_MEMORY_ALLOCATION_ERROR;
goto fail;
}
ctx.pwd = (uint8_t *)pwd;
ctx.pwdlen = (uint32_t)pwdlen;
ret = decode_string(&ctx, encoded, type);
if (ret != ARGON2_OK) {
goto fail;
}
/* Set aside the desired result, and get a new buffer. */
desired_result = ctx.out;
ctx.out = malloc(ctx.outlen);
if (!ctx.out) {
ret = ARGON2_MEMORY_ALLOCATION_ERROR;
goto fail;
}
ret = argon2_verify_ctx(&ctx, (char *)desired_result, type);
if (ret != ARGON2_OK) {
goto fail;
}
fail:
free(ctx.salt);
free(ctx.out);
free(desired_result);
return ret;
}
int argon2d_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
return argon2_verify(encoded, pwd, pwdlen, Argon2_d);
}
int argon2d_ctx(argon2_context *context) {
return argon2_ctx(context, Argon2_d);
}
int argon2_verify_ctx(argon2_context *context, const char *hash,
argon2_type type) {
int ret = argon2_ctx(context, type);
if (ret != ARGON2_OK) {
return ret;
}
if (argon2_compare((uint8_t *)hash, context->out, context->outlen)) {
return ARGON2_VERIFY_MISMATCH;
}
return ARGON2_OK;
}
int argon2d_verify_ctx(argon2_context *context, const char *hash) {
return argon2_verify_ctx(context, hash, Argon2_d);
}
const char *argon2_error_message(int error_code) {
switch (error_code) {
case ARGON2_OK:
return "OK";
case ARGON2_OUTPUT_PTR_NULL:
return "Output pointer is NULL";
case ARGON2_OUTPUT_TOO_SHORT:
return "Output is too short";
case ARGON2_OUTPUT_TOO_LONG:
return "Output is too long";
case ARGON2_PWD_TOO_SHORT:
return "Password is too short";
case ARGON2_PWD_TOO_LONG:
return "Password is too long";
case ARGON2_SALT_TOO_SHORT:
return "Salt is too short";
case ARGON2_SALT_TOO_LONG:
return "Salt is too long";
case ARGON2_AD_TOO_SHORT:
return "Associated data is too short";
case ARGON2_AD_TOO_LONG:
return "Associated data is too long";
case ARGON2_SECRET_TOO_SHORT:
return "Secret is too short";
case ARGON2_SECRET_TOO_LONG:
return "Secret is too long";
case ARGON2_TIME_TOO_SMALL:
return "Time cost is too small";
case ARGON2_TIME_TOO_LARGE:
return "Time cost is too large";
case ARGON2_MEMORY_TOO_LITTLE:
return "Memory cost is too small";
case ARGON2_MEMORY_TOO_MUCH:
return "Memory cost is too large";
case ARGON2_LANES_TOO_FEW:
return "Too few lanes";
case ARGON2_LANES_TOO_MANY:
return "Too many lanes";
case ARGON2_PWD_PTR_MISMATCH:
return "Password pointer is NULL, but password length is not 0";
case ARGON2_SALT_PTR_MISMATCH:
return "Salt pointer is NULL, but salt length is not 0";
case ARGON2_SECRET_PTR_MISMATCH:
return "Secret pointer is NULL, but secret length is not 0";
case ARGON2_AD_PTR_MISMATCH:
return "Associated data pointer is NULL, but ad length is not 0";
case ARGON2_MEMORY_ALLOCATION_ERROR:
return "Memory allocation error";
case ARGON2_FREE_MEMORY_CBK_NULL:
return "The free memory callback is NULL";
case ARGON2_ALLOCATE_MEMORY_CBK_NULL:
return "The allocate memory callback is NULL";
case ARGON2_INCORRECT_PARAMETER:
return "Argon2_Context context is NULL";
case ARGON2_INCORRECT_TYPE:
return "There is no such version of Argon2";
case ARGON2_OUT_PTR_MISMATCH:
return "Output pointer mismatch";
case ARGON2_THREADS_TOO_FEW:
return "Not enough threads";
case ARGON2_THREADS_TOO_MANY:
return "Too many threads";
case ARGON2_MISSING_ARGS:
return "Missing arguments";
case ARGON2_ENCODING_FAIL:
return "Encoding failed";
case ARGON2_DECODING_FAIL:
return "Decoding failed";
case ARGON2_THREAD_FAIL:
return "Threading failure";
case ARGON2_DECODING_LENGTH_FAIL:
return "Some of encoded parameters are too long or too short";
case ARGON2_VERIFY_MISMATCH:
return "The password does not match the supplied hash";
default:
return "Unknown error code";
}
}
size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, uint32_t parallelism,
uint32_t saltlen, uint32_t hashlen, argon2_type type) {
return strlen("$$v=$m=,t=,p=$$") + strlen(argon2_type2string(type, 0)) +
numlen(t_cost) + numlen(m_cost) + numlen(parallelism) +
b64len(saltlen) + b64len(hashlen);
} }

View file

@ -1,18 +1,27 @@
/* /*
* Argon2 source code package * Argon2 reference source code package - reference C implementations
* *
* Written by Daniel Dinu and Dmitry Khovratovich, 2015 * Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
* *
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver. * You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
* *
* You should have received a copy of the CC0 Public Domain Dedication along * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* with * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* this software. If not, see *
* <http://creativecommons.org/publicdomain/zero/1.0/>. * You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/ */
#ifndef ARGON2_H #ifndef ARGON2_H
#define ARGON2_H #define ARGON2_H
#if defined(HAVE_CONFIG_H)
#include "config/dynamic-config.h"
#endif
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <limits.h> #include <limits.h>
@ -21,8 +30,18 @@
extern "C" { extern "C" {
#endif #endif
/*************************Argon2 input parameter /* Symbols visibility control */
* restrictions**************************************************/ #ifdef A2_VISCTL
#define ARGON2_PUBLIC __attribute__((visibility("default")))
#elif _MSC_VER
#define ARGON2_PUBLIC __declspec(dllexport)
#else
#define ARGON2_PUBLIC
#endif
/*
* Argon2 input parameter restrictions
*/
/* Minimum and maximum number of lanes (degree of parallelism) */ /* Minimum and maximum number of lanes (degree of parallelism) */
#define ARGON2_MIN_LANES UINT32_C(1) #define ARGON2_MIN_LANES UINT32_C(1)
@ -43,8 +62,7 @@ extern "C" {
#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */ #define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */
#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b)) #define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b))
/* Max memory size is half the addressing space, topping at 2^32 blocks (4 TB) /* Max memory size is addressing-space/2, topping at 2^32 blocks (4 TB) */
*/
#define ARGON2_MAX_MEMORY_BITS \ #define ARGON2_MAX_MEMORY_BITS \
ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1)) ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1))
#define ARGON2_MAX_MEMORY \ #define ARGON2_MAX_MEMORY \
@ -70,65 +88,74 @@ extern "C" {
#define ARGON2_MIN_SECRET UINT32_C(0) #define ARGON2_MIN_SECRET UINT32_C(0)
#define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF) #define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF)
/* Flags to determine which fields are securely wiped (default = no wipe). */
#define ARGON2_DEFAULT_FLAGS UINT32_C(0)
#define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0) #define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0)
#define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1) #define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1)
#define ARGON2_FLAG_CLEAR_MEMORY (UINT32_C(1) << 2)
#define ARGON2_DEFAULT_FLAGS \ /* Global flag to determine if we are wiping internal memory buffers. This flag
(ARGON2_FLAG_CLEAR_PASSWORD | ARGON2_FLAG_CLEAR_MEMORY) * is defined in core.c and deafults to 1 (wipe internal memory). */
extern int FLAG_clear_internal_memory;
/* Error codes */ /* Error codes */
typedef enum Argon2_ErrorCodes { typedef enum Argon2_ErrorCodes {
ARGON2_OK = 0, ARGON2_OK = 0,
ARGON2_OUTPUT_PTR_NULL = 1, ARGON2_OUTPUT_PTR_NULL = -1,
ARGON2_OUTPUT_TOO_SHORT = 2, ARGON2_OUTPUT_TOO_SHORT = -2,
ARGON2_OUTPUT_TOO_LONG = 3, ARGON2_OUTPUT_TOO_LONG = -3,
ARGON2_PWD_TOO_SHORT = 4, ARGON2_PWD_TOO_SHORT = -4,
ARGON2_PWD_TOO_LONG = 5, ARGON2_PWD_TOO_LONG = -5,
ARGON2_SALT_TOO_SHORT = 6, ARGON2_SALT_TOO_SHORT = -6,
ARGON2_SALT_TOO_LONG = 7, ARGON2_SALT_TOO_LONG = -7,
ARGON2_AD_TOO_SHORT = 8, ARGON2_AD_TOO_SHORT = -8,
ARGON2_AD_TOO_LONG = 9, ARGON2_AD_TOO_LONG = -9,
ARGON2_SECRET_TOO_SHORT = 10, ARGON2_SECRET_TOO_SHORT = -10,
ARGON2_SECRET_TOO_LONG = 11, ARGON2_SECRET_TOO_LONG = -11,
ARGON2_TIME_TOO_SMALL = 12, ARGON2_TIME_TOO_SMALL = -12,
ARGON2_TIME_TOO_LARGE = 13, ARGON2_TIME_TOO_LARGE = -13,
ARGON2_MEMORY_TOO_LITTLE = 14, ARGON2_MEMORY_TOO_LITTLE = -14,
ARGON2_MEMORY_TOO_MUCH = 15, ARGON2_MEMORY_TOO_MUCH = -15,
ARGON2_LANES_TOO_FEW = 16, ARGON2_LANES_TOO_FEW = -16,
ARGON2_LANES_TOO_MANY = 17, ARGON2_LANES_TOO_MANY = -17,
ARGON2_PWD_PTR_MISMATCH = 18, /* NULL ptr with non-zero length */ ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */
ARGON2_SALT_PTR_MISMATCH = 19, /* NULL ptr with non-zero length */ ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */
ARGON2_SECRET_PTR_MISMATCH = 20, /* NULL ptr with non-zero length */ ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */
ARGON2_AD_PTR_MISMATCH = 21, /* NULL ptr with non-zero length */ ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */
ARGON2_MEMORY_ALLOCATION_ERROR = 22, ARGON2_MEMORY_ALLOCATION_ERROR = -22,
ARGON2_FREE_MEMORY_CBK_NULL = 23, ARGON2_FREE_MEMORY_CBK_NULL = -23,
ARGON2_ALLOCATE_MEMORY_CBK_NULL = 24, ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24,
ARGON2_INCORRECT_PARAMETER = 25, ARGON2_INCORRECT_PARAMETER = -25,
ARGON2_INCORRECT_TYPE = 26, ARGON2_INCORRECT_TYPE = -26,
ARGON2_OUT_PTR_MISMATCH = 27, ARGON2_OUT_PTR_MISMATCH = -27,
ARGON2_THREADS_TOO_FEW = 28, ARGON2_THREADS_TOO_FEW = -28,
ARGON2_THREADS_TOO_MANY = 29, ARGON2_THREADS_TOO_MANY = -29,
ARGON2_MISSING_ARGS = 30, ARGON2_MISSING_ARGS = -30,
ARGON2_ERROR_CODES_LENGTH /* Do NOT remove; Do NOT add error codes after ARGON2_ENCODING_FAIL = -31,
this
error code */ ARGON2_DECODING_FAIL = -32,
ARGON2_THREAD_FAIL = -33,
ARGON2_DECODING_LENGTH_FAIL = -34,
ARGON2_VERIFY_MISMATCH = -35
} argon2_error_codes; } argon2_error_codes;
/* Memory allocator types --- for external allocation */ /* Memory allocator types --- for external allocation */
@ -138,7 +165,8 @@ typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate);
/* Argon2 external data structures */ /* Argon2 external data structures */
/* /*
*****Context: structure to hold Argon2 inputs: *****
* Context: structure to hold Argon2 inputs:
* output array and its length, * output array and its length,
* password and its length, * password and its length,
* salt and its length, * salt and its length,
@ -148,142 +176,159 @@ typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate);
* number of parallel threads that will be run. * number of parallel threads that will be run.
* All the parameters above affect the output hash value. * All the parameters above affect the output hash value.
* Additionally, two function pointers can be provided to allocate and * Additionally, two function pointers can be provided to allocate and
deallocate the memory (if NULL, memory will be allocated internally). * deallocate the memory (if NULL, memory will be allocated internally).
* Also, three flags indicate whether to erase password, secret as soon as they * Also, three flags indicate whether to erase password, secret as soon as they
are pre-hashed (and thus not needed anymore), and the entire memory * are pre-hashed (and thus not needed anymore), and the entire memory
**************************** *****
Simplest situation: you have output array out[8], password is stored in * Simplest situation: you have output array out[8], password is stored in
pwd[32], salt is stored in salt[16], you do not have keys nor associated data. * pwd[32], salt is stored in salt[16], you do not have keys nor associated
You need to spend 1 GB of RAM and you run 5 passes of Argon2d with 4 parallel * data. You need to spend 1 GB of RAM and you run 5 passes of Argon2d with
lanes. * 4 parallel lanes.
You want to erase the password, but you're OK with last pass not being erased. * You want to erase the password, but you're OK with last pass not being
You want to use the default memory allocator. * erased. You want to use the default memory allocator.
* Then you initialize:
Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false)
*/ */
typedef struct Argon2_Context { typedef struct Argon2_Context {
uint8_t *out; /* output array */ uint8_t *out; /* output array */
uint32_t outlen; /* digest length */
uint8_t *pwd; /* password array */ uint8_t *pwd; /* password array */
uint32_t pwdlen; /* password length */
uint8_t *salt; /* salt array */ uint8_t *salt; /* salt array */
/*uint8_t *secret;*/ /* key array */ uint32_t saltlen; /* salt length */
/*uint8_t *ad;*/ /* associated data array */
uint8_t *secret; /* key array */
uint32_t secretlen; /* key length */
uint8_t *ad; /* associated data array */
uint32_t adlen; /* associated data length */
uint32_t t_cost; /* number of passes */
uint32_t m_cost; /* amount of memory requested (KB) */
uint32_t lanes; /* number of lanes */
uint32_t threads; /* maximum number of threads */
allocate_fptr allocate_cbk; /* pointer to memory allocator */ allocate_fptr allocate_cbk; /* pointer to memory allocator */
deallocate_fptr free_cbk; /* pointer to memory deallocator */ deallocate_fptr free_cbk; /* pointer to memory deallocator */
/*uint32_t outlen;*/ /* digest length */ uint32_t flags; /* array of bool options */
uint32_t pwdlen; /* password length */
/*uint32_t saltlen;*/ /* salt length */
/*uint32_t secretlen;*/ /* key length */
/*uint32_t adlen;*/ /* associated data length */
/*uint32_t t_cost;*/ /* number of passes */
/*uint32_t m_cost;*/ /* amount of memory requested (KB) */
/*uint32_t lanes;*/ /* number of lanes */
/*uint32_t threads;*/ /* maximum number of threads */
/*uint32_t flags;*/ /* array of bool options */
} argon2_context; } argon2_context;
/* Argon2 primitive type */
typedef enum Argon2_type {
Argon2_d = 0
} argon2_type;
/*
* Function that gives the string representation of an argon2_type.
* @param type The argon2_type that we want the string for
* @param uppercase Whether the string should have the first letter uppercase
* @return NULL if invalid type, otherwise the string representation.
*/
ARGON2_PUBLIC const char *argon2_type2string(argon2_type type, int uppercase);
/*
* Function that performs memory-hard hashing with certain degree of parallelism
* @param context Pointer to the Argon2 internal structure
* @return Error code if smth is wrong, ARGON2_OK otherwise
*/
ARGON2_PUBLIC int argon2_ctx(argon2_context *context, argon2_type type);
/** /**
* Function to hash the inputs in the memory-hard fashion (uses Argon2i) * Hashes a password with Argon2i, producing a raw hash by allocating memory at
* @param out Pointer to the memory where the hash digest will be written * @hash
* @param outlen Digest length in bytes * @param t_cost Number of iterations
* @param in Pointer to the input (password) * @param m_cost Sets memory usage to m_cost kibibytes
* @param inlen Input length in bytes * @param parallelism Number of threads and compute lanes
* @param salt Pointer to the salt * @param pwd Pointer to password
* @param saltlen Salt length in bytes * @param pwdlen Password size in bytes
* @pre @a out must have at least @a outlen bytes allocated * @param salt Pointer to salt
* @pre @a in must be at least @inlen bytes long * @param saltlen Salt size in bytes
* @pre @a saltlen must be at least @saltlen bytes long * @param hash Buffer where to write the raw hash - updated by the function
* @return Zero if successful, 1 otherwise. * @param hashlen Desired length of the hash in bytes
* @pre Different parallelism levels will give different results
* @pre Returns ARGON2_OK if successful
*/ */
/*int hash_argon2i(void *out, size_t outlen, const void *in, size_t inlen, ARGON2_PUBLIC int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
const void *salt, size_t saltlen, unsigned int t_cost, const uint32_t parallelism, const void *pwd,
unsigned int m_cost);*/ const size_t pwdlen, const void *salt,
const size_t saltlen, void *hash,
const size_t hashlen);
/* same for argon2d */ ARGON2_PUBLIC int argon2d_hash_encoded(const uint32_t t_cost,
/*int hash_argon2d(void *out, size_t outlen, const void *in, size_t inlen, const uint32_t m_cost,
const void *salt, size_t saltlen, unsigned int t_cost, const uint32_t parallelism,
unsigned int m_cost);*/ const void *pwd, const size_t pwdlen,
const void *salt, const size_t saltlen,
const size_t hashlen, char *encoded,
const size_t encodedlen);
/* /* generic function underlying the above ones */
* **************Argon2d: Version of Argon2 that picks memory blocks depending ARGON2_PUBLIC int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, void *hash,
const size_t hashlen, char *encoded,
const size_t encodedlen, argon2_type type);
/**
* Verifies a password against an encoded string
* Encoded string is restricted as in validate_inputs()
* @param encoded String encoding parameters, salt, hash
* @param pwd Pointer to password
* @pre Returns ARGON2_OK if successful
*/
ARGON2_PUBLIC int argon2d_verify(const char *encoded, const void *pwd,
const size_t pwdlen);
/* generic function underlying the above ones */
ARGON2_PUBLIC int argon2_verify(const char *encoded, const void *pwd,
const size_t pwdlen, argon2_type type);
/**
* Argon2d: Version of Argon2 that picks memory blocks depending
* on the password and salt. Only for side-channel-free * on the password and salt. Only for side-channel-free
* environment!!*************** * environment!!
*****
* @param context Pointer to current Argon2 context * @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise * @return Zero if successful, a non zero error code otherwise
*/ */
int argon2d(argon2_context *context); ARGON2_PUBLIC int argon2d_ctx(argon2_context *context);
/* /**
* * **************Argon2i: Version of Argon2 that picks memory blocks
*independent on the password and salt. Good for side-channels,
******************* but worse w.r.t. tradeoff attacks if
*******************only one pass is used***************
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
int argon2i(argon2_context *context);
/*
* * **************Argon2di: Reserved name***************
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
int argon2di(argon2_context *context);
/*
* * **************Argon2ds: Argon2d hardened against GPU attacks, 20%
* slower***************
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
int argon2ds(argon2_context *context);
/*
* * **************Argon2id: First half-pass over memory is
*password-independent, the rest are password-dependent
********************OK against side channels: they reduce to 1/2-pass
*Argon2i***************
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
int argon2id(argon2_context *context);
/*
* Verify if a given password is correct for Argon2d hashing * Verify if a given password is correct for Argon2d hashing
* @param context Pointer to current Argon2 context * @param context Pointer to current Argon2 context
* @param hash The password hash to verify. The length of the hash is * @param hash The password hash to verify. The length of the hash is
* specified by the context outlen member * specified by the context outlen member
* @return Zero if successful, a non zero error code otherwise * @return Zero if successful, a non zero error code otherwise
*/ */
int verify_d(argon2_context *context, const char *hash); ARGON2_PUBLIC int argon2d_verify_ctx(argon2_context *context, const char *hash);
/* /* generic function underlying the above ones */
ARGON2_PUBLIC int argon2_verify_ctx(argon2_context *context, const char *hash,
argon2_type type);
/**
* Get the associated error message for given error code * Get the associated error message for given error code
* @return The error message associated with the given error code * @return The error message associated with the given error code
*/ */
const char *error_message(int error_code); ARGON2_PUBLIC const char *argon2_error_message(int error_code);
/* ==================================================================== */ /**
/* * Returns the encoded hash length for the given input parameters
* Code specific to Argon2i. * @param t_cost Number of iterations
* * @param m_cost Memory usage in kibibytes
* The code below applies the following format: * @param parallelism Number of threads; used to compute lanes
* * @param saltlen Salt size in bytes
* $argon2i$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]] * @param hashlen Hash size in bytes
* * @param type The argon2_type that we want the encoded length for
* where <num> is a decimal integer (positive, fits in an 'unsigned long') * @return The encoded hash length in bytes
* and <bin> is Base64-encoded data (no '=' padding characters, no newline
* or whitespace). The "keyid" is a binary identifier for a key (up to 8
* bytes); "data" is associated data (up to 32 bytes). When the 'keyid'
* (resp. the 'data') is empty, then it is ommitted from the output.
*
* The last two binary chunks (encoded in Base64) are, in that order,
* the salt and the output. Both are optional, but you cannot have an
* output without a salt. The binary salt length is between 8 and 48 bytes.
* The output length is always exactly 32 bytes.
*/ */
ARGON2_PUBLIC size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost,
int encode_string(char *dst, size_t dst_len, argon2_context *ctx); uint32_t parallelism, uint32_t saltlen,
uint32_t hashlen, argon2_type type);
#if defined(__cplusplus) #if defined(__cplusplus)
} }

View file

@ -1,111 +0,0 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef _MSC_VER
#include <intrin.h>
#endif
#include "argon2.h"
static uint64_t rdtsc(void) {
#ifdef _MSC_VER
return __rdtsc();
#else
#if defined(__amd64__) || defined(__x86_64__)
uint64_t rax, rdx;
__asm__ __volatile__("rdtsc" : "=a"(rax), "=d"(rdx) : :);
return (rdx << 32) | rax;
#elif defined(__i386__) || defined(__i386) || defined(__X86__)
uint64_t rax;
__asm__ __volatile__("rdtsc" : "=A"(rax) : :);
return rax;
#else
#error "Not implemented!"
#endif
#endif
}
/*
* Benchmarks Argon2 with salt length 16, password length 16, t_cost 1,
and different m_cost and threads
*/
static void benchmark() {
#define BENCH_OUTLEN 16
#define BENCH_INLEN 16
const uint32_t inlen = BENCH_INLEN;
const unsigned outlen = BENCH_OUTLEN;
unsigned char out[BENCH_OUTLEN];
unsigned char pwd_array[BENCH_INLEN];
unsigned char salt_array[BENCH_INLEN];
#undef BENCH_INLEN
#undef BENCH_OUTLEN
uint32_t t_cost = 1;
uint32_t m_cost;
uint32_t thread_test[6] = {1, 2, 4, 6, 8, 16};
memset(pwd_array, 0, inlen);
memset(salt_array, 1, inlen);
for (m_cost = (uint32_t)1 << 10; m_cost <= (uint32_t)1 << 22; m_cost *= 2) {
unsigned i;
for (i = 0; i < 6; ++i) {
argon2_context context;
uint32_t thread_n = thread_test[i];
uint64_t stop_cycles, stop_cycles_i;
clock_t stop_time;
uint64_t delta_d, delta_i;
double mcycles_d, mcycles_i, run_time;
clock_t start_time = clock();
uint64_t start_cycles = rdtsc();
context.out = out;
context.outlen = outlen;
context.pwd = pwd_array;
context.pwdlen = inlen;
context.salt = salt_array;
context.saltlen = inlen;
context.secret = NULL;
context.secretlen = 0;
context.ad = NULL;
context.adlen = 0;
context.t_cost = t_cost;
context.m_cost = m_cost;
context.lanes = thread_n;
context.threads = thread_n;
context.allocate_cbk = NULL;
context.free_cbk = NULL;
context.flags = 0;
argon2d(&context);
stop_cycles = rdtsc();
argon2i(&context);
stop_cycles_i = rdtsc();
stop_time = clock();
delta_d = (stop_cycles - start_cycles) / (m_cost);
delta_i = (stop_cycles_i - stop_cycles) / (m_cost);
mcycles_d = (double)(stop_cycles - start_cycles) / (1UL << 20);
mcycles_i = (double)(stop_cycles_i - stop_cycles) / (1UL << 20);
printf("Argon2d %d iterations %d MiB %d threads: %2.2f cpb %2.2f "
"Mcycles \n",
t_cost, m_cost >> 10, thread_n, (float)delta_d / 1024,
mcycles_d);
printf("Argon2i %d iterations %d MiB %d threads: %2.2f cpb %2.2f "
"Mcycles \n",
t_cost, m_cost >> 10, thread_n, (float)delta_i / 1024,
mcycles_i);
run_time = ((double)stop_time - start_time) / (CLOCKS_PER_SEC);
printf("%2.4f seconds\n\n", run_time);
}
}
}
int main() {
benchmark();
return ARGON2_OK;
}

View file

@ -1,162 +0,0 @@
#ifndef BLAKE_ROUND_MKA_OPT_H
#define BLAKE_ROUND_MKA_OPT_H
#include "blake2-impl.h"
#if defined(_MSC_VER)
#include <intrin.h>
#endif
#include <immintrin.h>
#if defined(__XOP__) && (defined(__GNUC__) || defined(__clang__))
#include <x86intrin.h>
#endif
#if !defined(__XOP__)
#if defined(__SSSE3__)
#define r16 \
(_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
#define r24 \
(_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
#define _mm_roti_epi64(x, c) \
(-(c) == 32) \
? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \
: (-(c) == 24) \
? _mm_shuffle_epi8((x), r24) \
: (-(c) == 16) \
? _mm_shuffle_epi8((x), r16) \
: (-(c) == 63) \
? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
_mm_add_epi64((x), (x))) \
: _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
_mm_slli_epi64((x), 64 - (-(c))))
#else /* defined(__SSE2__) */
#define _mm_roti_epi64(r, c) \
_mm_xor_si128(_mm_srli_epi64((r), -(c)), _mm_slli_epi64((r), 64 - (-(c))))
#endif
#else
#endif
static BLAKE2_INLINE __m128i fBlaMka(__m128i x, __m128i y) {
const __m128i z = _mm_mul_epu32(x, y);
return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z));
}
#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = fBlaMka(A0, B0); \
A1 = fBlaMka(A1, B1); \
\
D0 = _mm_xor_si128(D0, A0); \
D1 = _mm_xor_si128(D1, A1); \
\
D0 = _mm_roti_epi64(D0, -32); \
D1 = _mm_roti_epi64(D1, -32); \
\
C0 = fBlaMka(C0, D0); \
C1 = fBlaMka(C1, D1); \
\
B0 = _mm_xor_si128(B0, C0); \
B1 = _mm_xor_si128(B1, C1); \
\
B0 = _mm_roti_epi64(B0, -24); \
B1 = _mm_roti_epi64(B1, -24); \
} while ((void)0, 0)
#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = fBlaMka(A0, B0); \
A1 = fBlaMka(A1, B1); \
\
D0 = _mm_xor_si128(D0, A0); \
D1 = _mm_xor_si128(D1, A1); \
\
D0 = _mm_roti_epi64(D0, -16); \
D1 = _mm_roti_epi64(D1, -16); \
\
C0 = fBlaMka(C0, D0); \
C1 = fBlaMka(C1, D1); \
\
B0 = _mm_xor_si128(B0, C0); \
B1 = _mm_xor_si128(B1, C1); \
\
B0 = _mm_roti_epi64(B0, -63); \
B1 = _mm_roti_epi64(B1, -63); \
} while ((void)0, 0)
#if defined(__SSSE3__)
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = _mm_alignr_epi8(B1, B0, 8); \
__m128i t1 = _mm_alignr_epi8(B0, B1, 8); \
B0 = t0; \
B1 = t1; \
\
t0 = C0; \
C0 = C1; \
C1 = t0; \
\
t0 = _mm_alignr_epi8(D1, D0, 8); \
t1 = _mm_alignr_epi8(D0, D1, 8); \
D0 = t1; \
D1 = t0; \
} while ((void)0, 0)
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = _mm_alignr_epi8(B0, B1, 8); \
__m128i t1 = _mm_alignr_epi8(B1, B0, 8); \
B0 = t0; \
B1 = t1; \
\
t0 = C0; \
C0 = C1; \
C1 = t0; \
\
t0 = _mm_alignr_epi8(D0, D1, 8); \
t1 = _mm_alignr_epi8(D1, D0, 8); \
D0 = t1; \
D1 = t0; \
} while ((void)0, 0)
#else /* SSE2 */
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = D0; \
__m128i t1 = B0; \
D0 = C0; \
C0 = C1; \
C1 = D0; \
D0 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t0, t0)); \
D1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(D1, D1)); \
B0 = _mm_unpackhi_epi64(B0, _mm_unpacklo_epi64(B1, B1)); \
B1 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(t1, t1)); \
} while ((void)0, 0)
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = C0; \
C0 = C1; \
C1 = t0; \
t0 = B0; \
__m128i t1 = D0; \
B0 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(B0, B0)); \
B1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(B1, B1)); \
D0 = _mm_unpackhi_epi64(D0, _mm_unpacklo_epi64(D1, D1)); \
D1 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t1, t1)); \
} while ((void)0, 0)
#endif
#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
\
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
} while ((void)0, 0)
#endif

View file

@ -1,305 +0,0 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>
#include "blake2/blake2.h"
#include "blake2/blake2-impl.h"
static const uint64_t blake2b_IV[8] = {
UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b),
UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1),
UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f),
UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179)
};
static const unsigned int blake2b_sigma[12][16] = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
{12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
{13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
{6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
{10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
};
static BLAKE2_INLINE void blake2b_set_lastnode(blake2b_state *S) {
S->f[1] = (uint64_t)-1;
}
static BLAKE2_INLINE void blake2b_set_lastblock(blake2b_state *S) {
if (S->last_node) {
blake2b_set_lastnode(S);
}
S->f[0] = (uint64_t)-1;
}
static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S,
uint64_t inc) {
S->t[0] += inc;
S->t[1] += (S->t[0] < inc);
}
static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) {
burn(S, sizeof(*S)); /* wipe */
blake2b_set_lastblock(S); /* invalidate for further use */
}
static BLAKE2_INLINE void blake2b_init0(blake2b_state *S) {
memset(S, 0, sizeof(*S));
memcpy(S->h, blake2b_IV, sizeof(S->h));
}
/*void print_state(blake2b_state BlakeHash) {
printf(".h = {UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 "),\n"
"UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 "),\n"
"UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 "),\n"
"UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 ")},\n"
".t = {UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 ")},\n"
".f = {UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 ")}\n",
BlakeHash.h[0], BlakeHash.h[1], BlakeHash.h[2], BlakeHash.h[3],
BlakeHash.h[4], BlakeHash.h[5], BlakeHash.h[6], BlakeHash.h[7],
BlakeHash.t[0], BlakeHash.t[1],
BlakeHash.f[0], BlakeHash.f[1]);
printf(".buf = {");
for (register uint8_t i = 0; i < BLAKE2B_BLOCKBYTES; i++)
printf("%" PRIu8 ", ", BlakeHash.buf[i]);
puts("\n");
printf("}\n.buflen = %d\n.outlen = %d\n",
BlakeHash.buflen, BlakeHash.outlen);
printf(".last_node = %" PRIu8 "\n", BlakeHash.last_node);
fflush(stdout);
}*/
static const blake2b_state miou = {
.h = {
UINT64_C(7640891576939301128), UINT64_C(13503953896175478587),
UINT64_C(4354685564936845355), UINT64_C(11912009170470909681),
UINT64_C(5840696475078001361), UINT64_C(11170449401992604703),
UINT64_C(2270897969802886507), UINT64_C(6620516959819538809)
},
.t = {UINT64_C(0), UINT64_C(0)},
.f = {UINT64_C(0), UINT64_C(0)},
.buf = {
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, 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, 0, 0
},
.buflen = 0,
.outlen = 64,
.last_node = 0
};
int blake2b_init_param(blake2b_state *S, const blake2b_param *P) {
const unsigned char *p = (const unsigned char *)P;
unsigned int i;
if (NULL == P || NULL == S) {
return -1;
}
blake2b_init0(S);
/* IV XOR Parameter Block */
for (i = 0; i < 8; ++i) {
S->h[i] ^= load64(&p[i * sizeof(S->h[i])]);
}
S->outlen = P->digest_length;
return 0;
}
void compare_buffs(uint64_t *h, size_t outlen)
{
// printf("CMP : %d", memcmp(h, miou.h, 8*(sizeof(uint64_t))));
printf("miou : %" PRIu64 " - h : %" PRIu64 " - outlen : %ld\n", miou.h[0], h[0], outlen);
fflush(stdout);
}
/* Sequential blake2b initialization */
int blake2b_init(blake2b_state *S, size_t outlen) {
memcpy(S, &miou, sizeof(*S));
S->h[0] += outlen;
return 0;
}
void print64(const char *name, const uint64_t *array, uint16_t size) {
printf("%s = {", name);
for (uint8_t i = 0; i < size; i++) printf("UINT64_C(%" PRIu64 "), ", array[i]);
printf("};\n");
}
int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
size_t keylen) {
return 0;
}
static void blake2b_compress(blake2b_state *S, const uint8_t *block) {
uint64_t m[16];
uint64_t v[16];
unsigned int i, r;
for (i = 0; i < 16; ++i) {
m[i] = load64(block + i * 8);
}
for (i = 0; i < 8; ++i) {
v[i] = S->h[i];
}
v[8] = blake2b_IV[0];
v[9] = blake2b_IV[1];
v[10] = blake2b_IV[2];
v[11] = blake2b_IV[3];
v[12] = blake2b_IV[4] ^ S->t[0];
v[13] = blake2b_IV[5]/* ^ S->t[1]*/;
v[14] = blake2b_IV[6] ^ S->f[0];
v[15] = blake2b_IV[7]/* ^ S->f[1]*/;
#define G(r, i, a, b, c, d) \
do { \
a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \
d = rotr64(d ^ a, 32); \
c = c + d; \
b = rotr64(b ^ c, 24); \
a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \
d = rotr64(d ^ a, 16); \
c = c + d; \
b = rotr64(b ^ c, 63); \
} while ((void)0, 0)
#define ROUND(r) \
do { \
G(r, 0, v[0], v[4], v[8], v[12]); \
G(r, 1, v[1], v[5], v[9], v[13]); \
G(r, 2, v[2], v[6], v[10], v[14]); \
G(r, 3, v[3], v[7], v[11], v[15]); \
G(r, 4, v[0], v[5], v[10], v[15]); \
G(r, 5, v[1], v[6], v[11], v[12]); \
G(r, 6, v[2], v[7], v[8], v[13]); \
G(r, 7, v[3], v[4], v[9], v[14]); \
} while ((void)0, 0)
for (r = 0; r < 12; ++r) ROUND(r);
for (i = 0; i < 8; ++i) S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
#undef G
#undef ROUND
}
int blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
const uint8_t *pin = (const uint8_t *)in;
/* Complete current block */
memcpy(&S->buf[4], pin, 124);
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress(S, S->buf);
S->buflen = 0;
pin += 124;
register int8_t i = 7;
/* Avoid buffer copies when possible */
while (i--) {
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress(S, pin);
pin += BLAKE2B_BLOCKBYTES;
}
memcpy(&S->buf[S->buflen], pin, 4);
S->buflen += 4;
return 0;
}
void my_blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
memcpy(&S->buf[S->buflen], in, inlen);
S->buflen += (unsigned int)inlen;
}
int blake2b_final(blake2b_state *S, void *out, size_t outlen) {
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
unsigned int i;
blake2b_increment_counter(S, S->buflen);
blake2b_set_lastblock(S);
memset(&S->buf[S->buflen], 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
blake2b_compress(S, S->buf);
for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
}
memcpy(out, buffer, S->outlen);
burn(buffer, sizeof(buffer));
burn(S->buf, sizeof(S->buf));
burn(S->h, sizeof(S->h));
return 0;
}
int blake2b(void *out, const void *in, const void *key, size_t keylen)
{
blake2b_state S;
blake2b_init(&S, 64);
my_blake2b_update(&S, in, 64);
blake2b_final(&S, out, 64);
burn(&S, sizeof(S));
return 0;
}
void blake2b_too(void *pout, const void *in)
{
uint8_t *out = (uint8_t *)pout;
uint8_t out_buffer[64];
uint8_t in_buffer[64];
blake2b_state blake_state;
blake2b_init(&blake_state, 64);
blake_state.buflen = blake_state.buf[1] = 4;
my_blake2b_update(&blake_state, in, 72);
blake2b_final(&blake_state, out_buffer, 64);
memcpy(out, out_buffer, 32);
out += 32;
register uint8_t i = 29;
while (i--) {
memcpy(in_buffer, out_buffer, 64);
blake2b(out_buffer, in_buffer, NULL, 0);
memcpy(out, out_buffer, 32);
out += 32;
}
memcpy(in_buffer, out_buffer, 64);
blake2b(out_buffer, in_buffer, NULL, 0);
memcpy(out, out_buffer, 64);
burn(&blake_state, sizeof(blake_state));
}
/* Argon2 Team - Begin Code */
int blake2b_long(void *pout, const void *in)
{
uint8_t *out = (uint8_t *)pout;
blake2b_state blake_state;
uint8_t outlen_bytes[sizeof(uint32_t)] = {0};
store32(outlen_bytes, 32);
blake2b_init(&blake_state, 32);
my_blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes));
blake2b_update(&blake_state, in, 1024);
blake2b_final(&blake_state, out, 32);
burn(&blake_state, sizeof(blake_state));
return 0;
}
/* Argon2 Team - End Code */

615
stratum/algos/ar2/core.c Normal file
View file

@ -0,0 +1,615 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
/*For memory wiping*/
#ifdef _MSC_VER
#include <windows.h>
#include <winbase.h> /* For SecureZeroMemory */
#endif
#if defined __STDC_LIB_EXT1__
#define __STDC_WANT_LIB_EXT1__ 1
#endif
#define VC_GE_2005(version) (version >= 1400)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "core.h"
#include "thread.h"
#include "../blake2/blake2.h"
#include "../blake2/blake2-impl.h"
#if defined(__clang__)
#if __has_attribute(optnone)
#define NOT_OPTIMIZED __attribute__((optnone))
#endif
#elif defined(__GNUC__)
#define GCC_VERSION \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION >= 40400
#define NOT_OPTIMIZED __attribute__((optimize("O0")))
#endif
#endif
#ifndef NOT_OPTIMIZED
#define NOT_OPTIMIZED
#endif
/***************Instance and Position constructors**********/
void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); }
void copy_block(block *dst, const block *src) {
memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);
}
void xor_block(block *dst, const block *src) {
int i;
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
dst->v[i] ^= src->v[i];
}
}
static void load_block(block *dst, const void *input) {
unsigned i;
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i]));
}
}
static void store_block(void *output, const block *src) {
unsigned i;
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);
}
}
/***************Memory functions*****************/
int allocate_memory(const argon2_context *context, uint8_t **memory,
size_t num, size_t size) {
size_t memory_size = num*size;
if (memory == NULL) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
/* 1. Check for multiplication overflow */
if (size != 0 && memory_size / size != num) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
/* 2. Try to allocate with appropriate allocator */
if (context->allocate_cbk) {
(context->allocate_cbk)(memory, memory_size);
} else {
*memory = malloc(memory_size);
}
if (*memory == NULL) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
return ARGON2_OK;
}
void free_memory(const argon2_context *context, uint8_t *memory,
size_t num, size_t size) {
size_t memory_size = num*size;
clear_internal_memory(memory, memory_size);
if (context->free_cbk) {
(context->free_cbk)(memory, memory_size);
} else {
free(memory);
}
}
void NOT_OPTIMIZED secure_wipe_memory(void *v, size_t n) {
#if defined(_MSC_VER) && VC_GE_2005(_MSC_VER)
SecureZeroMemory(v, n);
#elif defined memset_s
memset_s(v, n, 0, n);
#elif defined(__OpenBSD__)
explicit_bzero(v, n);
#else
static void *(*const volatile memset_sec)(void *, int, size_t) = &memset;
memset_sec(v, 0, n);
#endif
}
/* Memory clear flag defaults to true. */
int FLAG_clear_internal_memory = 1;
void clear_internal_memory(void *v, size_t n) {
if (FLAG_clear_internal_memory && v) {
secure_wipe_memory(v, n);
}
}
void finalize(const argon2_context *context, argon2_instance_t *instance) {
if (context != NULL && instance != NULL) {
block blockhash;
uint32_t l;
copy_block(&blockhash, instance->memory + instance->lane_length - 1);
/* XOR the last blocks */
for (l = 1; l < instance->lanes; ++l) {
uint32_t last_block_in_lane =
l * instance->lane_length + (instance->lane_length - 1);
xor_block(&blockhash, instance->memory + last_block_in_lane);
}
/* Hash the result */
{
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
store_block(blockhash_bytes, &blockhash);
blake2b_long(context->out, context->outlen, blockhash_bytes,
ARGON2_BLOCK_SIZE);
/* clear blockhash and blockhash_bytes */
clear_internal_memory(blockhash.v, ARGON2_BLOCK_SIZE);
clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
}
free_memory(context, (uint8_t *)instance->memory,
instance->memory_blocks, sizeof(block));
}
}
uint32_t index_alpha(const argon2_instance_t *instance,
const argon2_position_t *position, uint32_t pseudo_rand,
int same_lane) {
/*
* Pass 0:
* This lane : all already finished segments plus already constructed
* blocks in this segment
* Other lanes : all already finished segments
* Pass 1+:
* This lane : (SYNC_POINTS - 1) last segments plus already constructed
* blocks in this segment
* Other lanes : (SYNC_POINTS - 1) last segments
*/
uint32_t reference_area_size;
uint64_t relative_position;
uint32_t start_position, absolute_position;
if (0 == position->pass) {
/* First pass */
if (0 == position->slice) {
/* First slice */
reference_area_size =
position->index - 1; /* all but the previous */
} else {
if (same_lane) {
/* The same lane => add current segment */
reference_area_size =
position->slice * instance->segment_length +
position->index - 1;
} else {
reference_area_size =
position->slice * instance->segment_length +
((position->index == 0) ? (-1) : 0);
}
}
} else {
/* Second pass */
if (same_lane) {
reference_area_size = instance->lane_length -
instance->segment_length + position->index -
1;
} else {
reference_area_size = instance->lane_length -
instance->segment_length +
((position->index == 0) ? (-1) : 0);
}
}
/* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce
* relative position */
relative_position = pseudo_rand;
relative_position = relative_position * relative_position >> 32;
relative_position = reference_area_size - 1 -
(reference_area_size * relative_position >> 32);
/* 1.2.5 Computing starting position */
start_position = 0;
if (0 != position->pass) {
start_position = (position->slice == ARGON2_SYNC_POINTS - 1)
? 0
: (position->slice + 1) * instance->segment_length;
}
/* 1.2.6. Computing absolute position */
absolute_position = (start_position + relative_position) %
instance->lane_length; /* absolute position */
return absolute_position;
}
/* Single-threaded version for p=1 case */
static int fill_memory_blocks_st(argon2_instance_t *instance) {
uint32_t r, s, l;
for (r = 0; r < instance->passes; ++r) {
for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
for (l = 0; l < instance->lanes; ++l) {
argon2_position_t position = {r, l, (uint8_t)s, 0};
fill_segment(instance, position);
}
}
}
return ARGON2_OK;
}
#if !defined(ARGON2_NO_THREADS)
#ifdef _WIN32
static unsigned __stdcall fill_segment_thr(void *thread_data)
#else
static void *fill_segment_thr(void *thread_data)
#endif
{
argon2_thread_data *my_data = thread_data;
fill_segment(my_data->instance_ptr, my_data->pos);
argon2_thread_exit();
return 0;
}
/* Multi-threaded version for p > 1 case */
static int fill_memory_blocks_mt(argon2_instance_t *instance) {
uint32_t r, s;
argon2_thread_handle_t *thread = NULL;
argon2_thread_data *thr_data = NULL;
int rc = ARGON2_OK;
/* 1. Allocating space for threads */
thread = calloc(instance->lanes, sizeof(argon2_thread_handle_t));
if (thread == NULL) {
rc = ARGON2_MEMORY_ALLOCATION_ERROR;
goto fail;
}
thr_data = calloc(instance->lanes, sizeof(argon2_thread_data));
if (thr_data == NULL) {
rc = ARGON2_MEMORY_ALLOCATION_ERROR;
goto fail;
}
for (r = 0; r < instance->passes; ++r) {
for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
uint32_t l;
/* 2. Calling threads */
for (l = 0; l < instance->lanes; ++l) {
argon2_position_t position;
/* 2.1 Join a thread if limit is exceeded */
if (l >= instance->threads) {
if (argon2_thread_join(thread[l - instance->threads])) {
rc = ARGON2_THREAD_FAIL;
goto fail;
}
}
/* 2.2 Create thread */
position.pass = r;
position.lane = l;
position.slice = (uint8_t)s;
position.index = 0;
thr_data[l].instance_ptr =
instance; /* preparing the thread input */
memcpy(&(thr_data[l].pos), &position,
sizeof(argon2_position_t));
if (argon2_thread_create(&thread[l], &fill_segment_thr,
(void *)&thr_data[l])) {
rc = ARGON2_THREAD_FAIL;
goto fail;
}
/* fill_segment(instance, position); */
/*Non-thread equivalent of the lines above */
}
/* 3. Joining remaining threads */
for (l = instance->lanes - instance->threads; l < instance->lanes;
++l) {
if (argon2_thread_join(thread[l])) {
rc = ARGON2_THREAD_FAIL;
goto fail;
}
}
}
}
fail:
if (thread != NULL) {
free(thread);
}
if (thr_data != NULL) {
free(thr_data);
}
return rc;
}
#endif /* ARGON2_NO_THREADS */
int fill_memory_blocks(argon2_instance_t *instance) {
if (instance == NULL || instance->lanes == 0) {
return ARGON2_INCORRECT_PARAMETER;
}
#if defined(ARGON2_NO_THREADS)
return fill_memory_blocks_st(instance);
#else
return instance->threads == 1 ?
fill_memory_blocks_st(instance) : fill_memory_blocks_mt(instance);
#endif
}
int validate_inputs(const argon2_context *context) {
if (NULL == context) {
return ARGON2_INCORRECT_PARAMETER;
}
if (NULL == context->out) {
return ARGON2_OUTPUT_PTR_NULL;
}
/* Validate output length */
if (ARGON2_MIN_OUTLEN > context->outlen) {
return ARGON2_OUTPUT_TOO_SHORT;
}
if (ARGON2_MAX_OUTLEN < context->outlen) {
return ARGON2_OUTPUT_TOO_LONG;
}
/* Validate password (required param) */
if (NULL == context->pwd) {
if (0 != context->pwdlen) {
return ARGON2_PWD_PTR_MISMATCH;
}
}
if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) {
return ARGON2_PWD_TOO_SHORT;
}
if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) {
return ARGON2_PWD_TOO_LONG;
}
/* Validate salt (required param) */
if (NULL == context->salt) {
if (0 != context->saltlen) {
return ARGON2_SALT_PTR_MISMATCH;
}
}
if (ARGON2_MIN_SALT_LENGTH > context->saltlen) {
return ARGON2_SALT_TOO_SHORT;
}
if (ARGON2_MAX_SALT_LENGTH < context->saltlen) {
return ARGON2_SALT_TOO_LONG;
}
/* Validate secret (optional param) */
if (NULL == context->secret) {
if (0 != context->secretlen) {
return ARGON2_SECRET_PTR_MISMATCH;
}
} else {
if (ARGON2_MIN_SECRET > context->secretlen) {
return ARGON2_SECRET_TOO_SHORT;
}
if (ARGON2_MAX_SECRET < context->secretlen) {
return ARGON2_SECRET_TOO_LONG;
}
}
/* Validate associated data (optional param) */
if (NULL == context->ad) {
if (0 != context->adlen) {
return ARGON2_AD_PTR_MISMATCH;
}
} else {
if (ARGON2_MIN_AD_LENGTH > context->adlen) {
return ARGON2_AD_TOO_SHORT;
}
if (ARGON2_MAX_AD_LENGTH < context->adlen) {
return ARGON2_AD_TOO_LONG;
}
}
/* Validate memory cost */
if (ARGON2_MIN_MEMORY > context->m_cost) {
return ARGON2_MEMORY_TOO_LITTLE;
}
if (ARGON2_MAX_MEMORY < context->m_cost) {
return ARGON2_MEMORY_TOO_MUCH;
}
if (context->m_cost < 8 * context->lanes) {
return ARGON2_MEMORY_TOO_LITTLE;
}
/* Validate time cost */
if (ARGON2_MIN_TIME > context->t_cost) {
return ARGON2_TIME_TOO_SMALL;
}
if (ARGON2_MAX_TIME < context->t_cost) {
return ARGON2_TIME_TOO_LARGE;
}
/* Validate lanes */
if (ARGON2_MIN_LANES > context->lanes) {
return ARGON2_LANES_TOO_FEW;
}
if (ARGON2_MAX_LANES < context->lanes) {
return ARGON2_LANES_TOO_MANY;
}
/* Validate threads */
if (ARGON2_MIN_THREADS > context->threads) {
return ARGON2_THREADS_TOO_FEW;
}
if (ARGON2_MAX_THREADS < context->threads) {
return ARGON2_THREADS_TOO_MANY;
}
if (NULL != context->allocate_cbk && NULL == context->free_cbk) {
return ARGON2_FREE_MEMORY_CBK_NULL;
}
if (NULL == context->allocate_cbk && NULL != context->free_cbk) {
return ARGON2_ALLOCATE_MEMORY_CBK_NULL;
}
return ARGON2_OK;
}
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
uint32_t l;
/* Make the first and second block in each lane as G(H0||0||i) or
G(H0||1||i) */
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
for (l = 0; l < instance->lanes; ++l) {
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
ARGON2_PREHASH_SEED_LENGTH);
load_block(&instance->memory[l * instance->lane_length + 0],
blockhash_bytes);
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
ARGON2_PREHASH_SEED_LENGTH);
load_block(&instance->memory[l * instance->lane_length + 1],
blockhash_bytes);
}
clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
}
void initial_hash(uint8_t *blockhash, argon2_context *context,
argon2_type type) {
blake2b_state BlakeHash;
uint8_t value[sizeof(uint32_t)];
if (NULL == context || NULL == blockhash) {
return;
}
blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH);
store32(&value, context->lanes);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, context->outlen);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, context->m_cost);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, context->t_cost);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, ARGON2_VERSION_NUMBER);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, (uint32_t)type);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, context->pwdlen);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
if (context->pwd != NULL) {
blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
context->pwdlen);
if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
secure_wipe_memory(context->pwd, context->pwdlen);
context->pwdlen = 0;
}
}
store32(&value, context->saltlen);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
if (context->salt != NULL) {
blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
context->saltlen);
}
store32(&value, context->secretlen);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
if (context->secret != NULL) {
blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
context->secretlen);
if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
secure_wipe_memory(context->secret, context->secretlen);
context->secretlen = 0;
}
}
store32(&value, context->adlen);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
if (context->ad != NULL) {
blake2b_update(&BlakeHash, (const uint8_t *)context->ad,
context->adlen);
}
blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
}
int initialize(argon2_instance_t *instance, argon2_context *context) {
uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
int result = ARGON2_OK;
if (instance == NULL || context == NULL)
return ARGON2_INCORRECT_PARAMETER;
instance->context_ptr = context;
/* 1. Memory allocation */
result = allocate_memory(context, (uint8_t **)&(instance->memory),
instance->memory_blocks, sizeof(block));
if (result != ARGON2_OK) {
return result;
}
/* 2. Initial hashing */
/* H_0 + 8 extra bytes to produce the first blocks */
/* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */
/* Hashing all inputs */
initial_hash(blockhash, context, instance->type);
/* Zeroing 8 extra bytes */
clear_internal_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
ARGON2_PREHASH_SEED_LENGTH -
ARGON2_PREHASH_DIGEST_LENGTH);
/* 3. Creating first blocks, we always have at least two blocks in a slice
*/
fill_first_blocks(blockhash, instance);
/* Clearing the hash */
clear_internal_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH);
return ARGON2_OK;
}

View file

@ -1,38 +1,38 @@
/* /*
* Argon2 source code package * Argon2 reference source code package - reference C implementations
* *
* Written by Daniel Dinu and Dmitry Khovratovich, 2015 * Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
* *
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver. * You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
* *
* You should have received a copy of the CC0 Public Domain Dedication along * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* with * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* this software. If not, see *
* <http://creativecommons.org/publicdomain/zero/1.0/>. * You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/ */
#ifndef ARGON2_CORES_H #ifndef ARGON2_CORE_H
#define ARGON2_CORES_H #define ARGON2_CORE_H
#if defined(_MSC_VER) #include "argon2.h"
#define ALIGN(n) __declspec(align(16))
#elif defined(__GNUC__) || defined(__clang)
#define ALIGN(x) __attribute__((__aligned__(x)))
#else
#define ALIGN(x)
#endif
/*************************Argon2 internal #define CONST_CAST(x) (x)(uintptr_t)
* constants**************************************************/
/**********************Argon2 internal constants*******************************/
enum argon2_core_constants { enum argon2_core_constants {
/* Version of the algorithm */ /* Version of the algorithm */
ARGON2_VERSION_NUMBER = 0x10, ARGON2_VERSION_NUMBER = 0x10,
/* Memory block size in bytes */ /* Memory block size in bytes */
ARGON2_BLOCK_SIZE = 1024, ARGON2_BLOCK_SIZE = 1024,
ARGON2_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8, ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
ARGON2_QWORDS_IN_BLOCK = 64, ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32,
ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64,
/* Number of pseudo-random values generated by one call to Blake in Argon2i /* Number of pseudo-random values generated by one call to Blake in Argon2i
to to
@ -44,18 +44,14 @@ enum argon2_core_constants {
ARGON2_PREHASH_SEED_LENGTH = 72 ARGON2_PREHASH_SEED_LENGTH = 72
}; };
/* Argon2 primitive type */ /*************************Argon2 internal data types***********************/
typedef enum Argon2_type { Argon2_d = 0, Argon2_i = 1 } argon2_type;
/*************************Argon2 internal data
* types**************************************************/
/* /*
* Structure for the (1KB) memory block implemented as 128 64-bit words. * Structure for the (1KB) memory block implemented as 128 64-bit words.
* Memory blocks can be copied, XORed. Internal words can be accessed by [] (no * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
* bounds checking). * bounds checking).
*/ */
typedef struct _block { uint64_t v[ARGON2_WORDS_IN_BLOCK]; } __attribute__ ((aligned (16))) block; typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block;
/*****************Functions that work with the block******************/ /*****************Functions that work with the block******************/
@ -76,8 +72,16 @@ void xor_block(block *dst, const block *src);
*/ */
typedef struct Argon2_instance_t { typedef struct Argon2_instance_t {
block *memory; /* Memory pointer */ block *memory; /* Memory pointer */
uint32_t version;
uint32_t passes; /* Number of passes */
uint32_t memory_blocks; /* Number of blocks in memory */
uint32_t segment_length;
uint32_t lane_length;
uint32_t lanes;
uint32_t threads;
argon2_type type; argon2_type type;
int print_internals; /* whether to print the memory blocks */ int print_internals; /* whether to print the memory blocks */
argon2_context *context_ptr; /* points back to original context */
} argon2_instance_t; } argon2_instance_t;
/* /*
@ -97,32 +101,43 @@ typedef struct Argon2_thread_data {
argon2_position_t pos; argon2_position_t pos;
} argon2_thread_data; } argon2_thread_data;
/*************************Argon2 core /*************************Argon2 core functions********************************/
* functions**************************************************/
/* Allocates memory to the given pointer /* Allocates memory to the given pointer, uses the appropriate allocator as
* specified in the context. Total allocated memory is num*size.
* @param context argon2_context which specifies the allocator
* @param memory pointer to the pointer to the memory * @param memory pointer to the pointer to the memory
* @param m_cost number of blocks to allocate in the memory * @param size the size in bytes for each element to be allocated
* @param num the number of elements to be allocated
* @return ARGON2_OK if @memory is a valid pointer and memory is allocated * @return ARGON2_OK if @memory is a valid pointer and memory is allocated
*/ */
int allocate_memory(block **memory, uint32_t m_cost); int allocate_memory(const argon2_context *context, uint8_t **memory,
size_t num, size_t size);
/* Function that securely cleans the memory /*
* Frees memory at the given pointer, uses the appropriate deallocator as
* specified in the context. Also cleans the memory using clear_internal_memory.
* @param context argon2_context which specifies the deallocator
* @param memory pointer to buffer to be freed
* @param size the size in bytes for each element to be deallocated
* @param num the number of elements to be deallocated
*/
void free_memory(const argon2_context *context, uint8_t *memory,
size_t num, size_t size);
/* Function that securely cleans the memory. This ignores any flags set
* regarding clearing memory. Usually one just calls clear_internal_memory.
* @param mem Pointer to the memory * @param mem Pointer to the memory
* @param s Memory size in bytes * @param s Memory size in bytes
*/ */
void secure_wipe_memory(void *v, size_t n); void secure_wipe_memory(void *v, size_t n);
/* Clears memory /* Function that securely clears the memory if FLAG_clear_internal_memory is
* @param instance pointer to the current instance * set. If the flag isn't set, this function does nothing.
* @param clear_memory indicates if we clear the memory with zeros. * @param mem Pointer to the memory
* @param s Memory size in bytes
*/ */
void clear_memory(argon2_instance_t *instance, int clear); void clear_internal_memory(void *v, size_t n);
/* Deallocates memory
* @param memory pointer to the blocks
*/
void free_memory(block *memory);
/* /*
* Computes absolute position of reference block in the lane following a skewed * Computes absolute position of reference block in the lane following a skewed
@ -166,7 +181,7 @@ void initial_hash(uint8_t *blockhash, argon2_context *context,
* @param blockhash Pointer to the pre-hashing digest * @param blockhash Pointer to the pre-hashing digest
* @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values * @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
*/ */
void fill_firsts_blocks(uint8_t *blockhash, const argon2_instance_t *instance); void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
/* /*
* Function allocates memory, hashes the inputs with Blake, and creates first * Function allocates memory, hashes the inputs with Blake, and creates first
@ -196,6 +211,7 @@ void finalize(const argon2_context *context, argon2_instance_t *instance);
/* /*
* Function that fills the segment using previous segments also from other * Function that fills the segment using previous segments also from other
* threads * threads
* @param context current context
* @param instance Pointer to the current instance * @param instance Pointer to the current instance
* @param position Current position * @param position Current position
* @pre all block pointers must be valid * @pre all block pointers must be valid
@ -207,14 +223,8 @@ void fill_segment(const argon2_instance_t *instance,
* Function that fills the entire memory t_cost times based on the first two * Function that fills the entire memory t_cost times based on the first two
* blocks in each lane * blocks in each lane
* @param instance Pointer to the current instance * @param instance Pointer to the current instance
* @return ARGON2_OK if successful, @context->state
*/ */
void fill_memory_blocks(argon2_instance_t *instance); int fill_memory_blocks(argon2_instance_t *instance);
/*
* Function that performs memory-hard hashing with certain degree of parallelism
* @param context Pointer to the Argon2 internal structure
* @return Error code if smth is wrong, ARGON2_OK otherwise
*/
int argon2_core(argon2_context *context, argon2_type type);
#endif #endif

View file

@ -1,341 +0,0 @@
/*
* Argon2 source code package
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* You should have received a copy of the CC0 Public Domain Dedication along
* with
* this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
/*For memory wiping*/
#ifdef _MSC_VER
#include <windows.h>
#include <winbase.h> /* For SecureZeroMemory */
#endif
#if defined __STDC_LIB_EXT1__
#define __STDC_WANT_LIB_EXT1__ 1
#endif
#define VC_GE_2005(version) (version >= 1400)
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "argon2.h"
#include "cores.h"
#include "blake2/blake2.h"
#include "blake2/blake2-impl.h"
#ifdef GENKAT
#include "genkat.h"
#endif
#if defined(__clang__)
#if __has_attribute(optnone)
#define NOT_OPTIMIZED __attribute__((optnone))
#endif
#elif defined(__GNUC__)
#define GCC_VERSION \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION >= 40400
#define NOT_OPTIMIZED __attribute__((optimize("O0")))
#endif
#endif
#ifndef NOT_OPTIMIZED
#define NOT_OPTIMIZED
#endif
/***************Instance and Position constructors**********/
void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); }
void copy_block(block *dst, const block *src) {
memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_WORDS_IN_BLOCK);
}
void xor_block(block *dst, const block *src) {
int i;
for (i = 0; i < ARGON2_WORDS_IN_BLOCK; ++i) {
dst->v[i] ^= src->v[i];
}
}
static void load_block(block *dst, const void *input) {
unsigned i;
for (i = 0; i < ARGON2_WORDS_IN_BLOCK; ++i) {
dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i]));
}
}
static void store_block(void *output, const block *src) {
unsigned i;
for (i = 0; i < ARGON2_WORDS_IN_BLOCK; ++i) {
store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);
}
}
/***************Memory allocators*****************/
int allocate_memory(block **memory, uint32_t m_cost) {
if (memory != NULL) {
size_t memory_size = sizeof(block) * m_cost;
if (m_cost != 0 &&
memory_size / m_cost !=
sizeof(block)) { /*1. Check for multiplication overflow*/
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
*memory = (block *)malloc(memory_size); /*2. Try to allocate*/
if (!*memory) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
return ARGON2_OK;
} else {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
}
void secure_wipe_memory(void *v, size_t n) { memset(v, 0, n); }
/*********Memory functions*/
void clear_memory(argon2_instance_t *instance, int clear) {
if (instance->memory != NULL && clear) {
secure_wipe_memory(instance->memory,
sizeof(block) * /*instance->memory_blocks*/16);
}
}
void free_memory(block *memory) { free(memory); }
void finalize(const argon2_context *context, argon2_instance_t *instance) {
if (context != NULL && instance != NULL) {
block blockhash;
copy_block(&blockhash, instance->memory + 15);
/* Hash the result */
{
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
store_block(blockhash_bytes, &blockhash);
blake2b_long(context->out, blockhash_bytes);
secure_wipe_memory(blockhash.v, ARGON2_BLOCK_SIZE);
secure_wipe_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); /* clear blockhash_bytes */
}
#ifdef GENKAT
print_tag(context->out, context->outlen);
#endif
/* Clear memory */
clear_memory(instance, 1);
free_memory(instance->memory);
}
}
uint32_t index_alpha(const argon2_instance_t *instance,
const argon2_position_t *position, uint32_t pseudo_rand,
int same_lane) {
/*
* Pass 0:
* This lane : all already finished segments plus already constructed
* blocks in this segment
* Other lanes : all already finished segments
* Pass 1+:
* This lane : (SYNC_POINTS - 1) last segments plus already constructed
* blocks in this segment
* Other lanes : (SYNC_POINTS - 1) last segments
*/
uint32_t reference_area_size;
uint64_t relative_position;
uint32_t start_position, absolute_position;
if (0 == position->pass) {
/* First pass */
if (0 == position->slice) {
/* First slice */
reference_area_size =
position->index - 1; /* all but the previous */
} else {
if (same_lane) {
/* The same lane => add current segment */
reference_area_size =
position->slice * 4 +
position->index - 1;
} else {
reference_area_size =
position->slice * 4 +
((position->index == 0) ? (-1) : 0);
}
}
} else {
/* Second pass */
if (same_lane) {reference_area_size = 11 + position->index;}
else {reference_area_size = 12 - (position->index == 0);}
}
/* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce
* relative position */
relative_position = pseudo_rand;
relative_position = relative_position * relative_position >> 32;
relative_position = reference_area_size - 1 -
(reference_area_size * relative_position >> 32);
/* 1.2.5 Computing starting position */
start_position = 0;
if (0 != position->pass) {
start_position = (position->slice == ARGON2_SYNC_POINTS - 1)
? 0 : (position->slice + 1) * 4;
}
/* 1.2.6. Computing absolute position */
absolute_position = (start_position + relative_position) % 16;
return absolute_position;
}
void fill_memory_blocks(argon2_instance_t *instance) {
uint32_t r, s;
for (r = 0; r < 2; ++r) {
for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
argon2_position_t position;
position.pass = r;
position.lane = 0;
position.slice = (uint8_t)s;
position.index = 0;
fill_segment(instance, position);
}
#ifdef GENKAT
internal_kat(instance, r); /* Print all memory blocks */
#endif
}
}
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
/* Make the first and second block in each lane as G(H0||i||0) or
G(H0||i||1) */
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, 0);
blake2b_too(blockhash_bytes, blockhash);
load_block(&instance->memory[0], blockhash_bytes);
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
blake2b_too(blockhash_bytes, blockhash);
load_block(&instance->memory[1], blockhash_bytes);
secure_wipe_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
}
static const blake2b_state base_hash = {
.h = {
UINT64_C(7640891576939301192), UINT64_C(13503953896175478587),
UINT64_C(4354685564936845355), UINT64_C(11912009170470909681),
UINT64_C(5840696475078001361), UINT64_C(11170449401992604703),
UINT64_C(2270897969802886507), UINT64_C(6620516959819538809)
},
.t = {UINT64_C(0),UINT64_C(0)},
.f = {UINT64_C(0),UINT64_C(0)},
.buf = {
1, 0, 0, 0, 32, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 16, 0, 0, 0, 1, 0,
0, 0, 32, 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, 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},
.buflen = 28,
.outlen = 64,
.last_node = 0
};
#define PWDLEN 32
#define SALTLEN 32
#define SECRETLEN 0
#define ADLEN 0
void initial_hash(uint8_t *blockhash, argon2_context *context,
argon2_type type) {
uint8_t value[sizeof(uint32_t)];
/* Is it generating cache invalidation between cores ? */
blake2b_state BlakeHash = base_hash;
BlakeHash.buf[20] = (uint8_t) type;
my_blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
PWDLEN);
secure_wipe_memory(context->pwd, PWDLEN);
context->pwdlen = 0;
store32(&value, SALTLEN);
my_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
my_blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
SALTLEN);
store32(&value, SECRETLEN);
my_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, ADLEN);
my_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
}
int initialize(argon2_instance_t *instance, argon2_context *context) {
/* 1. Memory allocation */
allocate_memory(&(instance->memory), 16);
/* 2. Initial hashing */
/* H_0 + 8 extra bytes to produce the first blocks */
/* Hashing all inputs */
uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
initial_hash(blockhash, context, instance->type);
/* Zeroing 8 extra bytes */
secure_wipe_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
ARGON2_PREHASH_SEED_LENGTH -
ARGON2_PREHASH_DIGEST_LENGTH);
#ifdef GENKAT
initial_kat(blockhash, context, instance->type);
#endif
/* 3. Creating first blocks, we always have at least two blocks in a slice
*/
fill_first_blocks(blockhash, instance);
/* Clearing the hash */
secure_wipe_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH);
return ARGON2_OK;
}
int argon2_core(argon2_context *context, argon2_type type) {
argon2_instance_t instance;
instance.memory = NULL;
instance.type = type;
/* 3. Initialization: Hashing inputs, allocating memory, filling first
* blocks
*/
int result = initialize(&instance, context);
if (ARGON2_OK != result) return result;
/* 4. Filling memory */
fill_memory_blocks(&instance);
/* 5. Finalization */
finalize(context, &instance);
return ARGON2_OK;
}

View file

@ -0,0 +1,455 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "encoding.h"
#include "core.h"
/*
* Example code for a decoder and encoder of "hash strings", with Argon2
* parameters.
*
* This code comprises three sections:
*
* -- The first section contains generic Base64 encoding and decoding
* functions. It is conceptually applicable to any hash function
* implementation that uses Base64 to encode and decode parameters,
* salts and outputs. It could be made into a library, provided that
* the relevant functions are made public (non-static) and be given
* reasonable names to avoid collisions with other functions.
*
* -- The second section is specific to Argon2. It encodes and decodes
* the parameters, salts and outputs. It does not compute the hash
* itself.
*
* The code was originally written by Thomas Pornin <pornin@bolet.org>,
* to whom comments and remarks may be sent. It is released under what
* should amount to Public Domain or its closest equivalent; the
* following mantra is supposed to incarnate that fact with all the
* proper legal rituals:
*
* ---------------------------------------------------------------------
* This file is provided under the terms of Creative Commons CC0 1.0
* Public Domain Dedication. To the extent possible under law, the
* author (Thomas Pornin) has waived all copyright and related or
* neighboring rights to this file. This work is published from: Canada.
* ---------------------------------------------------------------------
*
* Copyright (c) 2015 Thomas Pornin
*/
/* ==================================================================== */
/*
* Common code; could be shared between different hash functions.
*
* Note: the Base64 functions below assume that uppercase letters (resp.
* lowercase letters) have consecutive numerical codes, that fit on 8
* bits. All modern systems use ASCII-compatible charsets, where these
* properties are true. If you are stuck with a dinosaur of a system
* that still defaults to EBCDIC then you already have much bigger
* interoperability issues to deal with.
*/
/*
* Some macros for constant-time comparisons. These work over values in
* the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
*/
#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
#define GE(x, y) (GT(y, x) ^ 0xFF)
#define LT(x, y) GT(y, x)
#define LE(x, y) GE(y, x)
/*
* Convert value x (0..63) to corresponding Base64 character.
*/
static int b64_byte_to_char(unsigned x) {
return (LT(x, 26) & (x + 'A')) |
(GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
(GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
(EQ(x, 63) & '/');
}
/*
* Convert character c to the corresponding 6-bit value. If character c
* is not a Base64 character, then 0xFF (255) is returned.
*/
static unsigned b64_char_to_byte(int c) {
unsigned x;
x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
(GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
(GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
(EQ(c, '/') & 63);
return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
}
/*
* Convert some bytes to Base64. 'dst_len' is the length (in characters)
* of the output buffer 'dst'; if that buffer is not large enough to
* receive the result (including the terminating 0), then (size_t)-1
* is returned. Otherwise, the zero-terminated Base64 string is written
* in the buffer, and the output length (counted WITHOUT the terminating
* zero) is returned.
*/
static size_t to_base64(char *dst, size_t dst_len, const void *src,
size_t src_len) {
size_t olen;
const unsigned char *buf;
unsigned acc, acc_len;
olen = (src_len / 3) << 2;
switch (src_len % 3) {
case 2:
olen++;
/* fall through */
case 1:
olen += 2;
break;
}
if (dst_len <= olen) {
return (size_t)-1;
}
acc = 0;
acc_len = 0;
buf = (const unsigned char *)src;
while (src_len-- > 0) {
acc = (acc << 8) + (*buf++);
acc_len += 8;
while (acc_len >= 6) {
acc_len -= 6;
*dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F);
}
}
if (acc_len > 0) {
*dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
}
*dst++ = 0;
return olen;
}
/*
* Decode Base64 chars into bytes. The '*dst_len' value must initially
* contain the length of the output buffer '*dst'; when the decoding
* ends, the actual number of decoded bytes is written back in
* '*dst_len'.
*
* Decoding stops when a non-Base64 character is encountered, or when
* the output buffer capacity is exceeded. If an error occurred (output
* buffer is too small, invalid last characters leading to unprocessed
* buffered bits), then NULL is returned; otherwise, the returned value
* points to the first non-Base64 character in the source stream, which
* may be the terminating zero.
*/
static const char *from_base64(void *dst, size_t *dst_len, const char *src) {
size_t len;
unsigned char *buf;
unsigned acc, acc_len;
buf = (unsigned char *)dst;
len = 0;
acc = 0;
acc_len = 0;
for (;;) {
unsigned d;
d = b64_char_to_byte(*src);
if (d == 0xFF) {
break;
}
src++;
acc = (acc << 6) + d;
acc_len += 6;
if (acc_len >= 8) {
acc_len -= 8;
if ((len++) >= *dst_len) {
return NULL;
}
*buf++ = (acc >> acc_len) & 0xFF;
}
}
/*
* If the input length is equal to 1 modulo 4 (which is
* invalid), then there will remain 6 unprocessed bits;
* otherwise, only 0, 2 or 4 bits are buffered. The buffered
* bits must also all be zero.
*/
if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) {
return NULL;
}
*dst_len = len;
return src;
}
/*
* Decode decimal integer from 'str'; the value is written in '*v'.
* Returned value is a pointer to the next non-decimal character in the
* string. If there is no digit at all, or the value encoding is not
* minimal (extra leading zeros), or the value does not fit in an
* 'unsigned long', then NULL is returned.
*/
static const char *decode_decimal(const char *str, unsigned long *v) {
const char *orig;
unsigned long acc;
acc = 0;
for (orig = str;; str++) {
int c;
c = *str;
if (c < '0' || c > '9') {
break;
}
c -= '0';
if (acc > (ULONG_MAX / 10)) {
return NULL;
}
acc *= 10;
if ((unsigned long)c > (ULONG_MAX - acc)) {
return NULL;
}
acc += (unsigned long)c;
}
if (str == orig || (*orig == '0' && str != (orig + 1))) {
return NULL;
}
*v = acc;
return str;
}
/* ==================================================================== */
/*
* Code specific to Argon2.
*
* The code below applies the following format:
*
* $argon2<T>[$v=<num>]$m=<num>,t=<num>,p=<num>$<bin>$<bin>
*
* where <T> is either 'd', 'id', or 'i', <num> is a decimal integer (positive,
* fits in an 'unsigned long'), and <bin> is Base64-encoded data (no '=' padding
* characters, no newline or whitespace).
*
* The last two binary chunks (encoded in Base64) are, in that order,
* the salt and the output. Both are required. The binary salt length and the
* output length must be in the allowed ranges defined in argon2.h.
*
* The ctx struct must contain buffers large enough to hold the salt and pwd
* when it is fed into decode_string.
*/
int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
/* check for prefix */
#define CC(prefix) \
do { \
size_t cc_len = strlen(prefix); \
if (strncmp(str, prefix, cc_len) != 0) { \
return ARGON2_DECODING_FAIL; \
} \
str += cc_len; \
} while ((void)0, 0)
/* optional prefix checking with supplied code */
#define CC_opt(prefix, code) \
do { \
size_t cc_len = strlen(prefix); \
if (strncmp(str, prefix, cc_len) == 0) { \
str += cc_len; \
{ code; } \
} \
} while ((void)0, 0)
/* Decoding prefix into decimal */
#define DECIMAL(x) \
do { \
unsigned long dec_x; \
str = decode_decimal(str, &dec_x); \
if (str == NULL) { \
return ARGON2_DECODING_FAIL; \
} \
(x) = dec_x; \
} while ((void)0, 0)
/* Decoding prefix into uint32_t decimal */
#define DECIMAL_U32(x) \
do { \
unsigned long dec_x; \
str = decode_decimal(str, &dec_x); \
if (str == NULL || dec_x > UINT32_MAX) { \
return ARGON2_DECODING_FAIL; \
} \
(x) = (uint32_t)dec_x; \
} while ((void)0, 0)
/* Decoding base64 into a binary buffer */
#define BIN(buf, max_len, len) \
do { \
size_t bin_len = (max_len); \
str = from_base64(buf, &bin_len, str); \
if (str == NULL || bin_len > UINT32_MAX) { \
return ARGON2_DECODING_FAIL; \
} \
(len) = (uint32_t)bin_len; \
} while ((void)0, 0)
size_t maxsaltlen = ctx->saltlen;
size_t maxoutlen = ctx->outlen;
int validation_result;
const char* type_string;
/* We should start with the argon2_type we are using */
type_string = argon2_type2string(type, 0);
if (!type_string) {
return ARGON2_INCORRECT_TYPE;
}
CC("$");
CC(type_string);
CC("$m=");
DECIMAL_U32(ctx->m_cost);
CC(",t=");
DECIMAL_U32(ctx->t_cost);
CC(",p=");
DECIMAL_U32(ctx->lanes);
ctx->threads = ctx->lanes;
CC("$");
BIN(ctx->salt, maxsaltlen, ctx->saltlen);
CC("$");
BIN(ctx->out, maxoutlen, ctx->outlen);
/* The rest of the fields get the default values */
ctx->secret = NULL;
ctx->secretlen = 0;
ctx->ad = NULL;
ctx->adlen = 0;
ctx->allocate_cbk = NULL;
ctx->free_cbk = NULL;
ctx->flags = ARGON2_DEFAULT_FLAGS;
/* On return, must have valid context */
validation_result = validate_inputs(ctx);
if (validation_result != ARGON2_OK) {
return validation_result;
}
/* Can't have any additional characters */
if (*str == 0) {
return ARGON2_OK;
} else {
return ARGON2_DECODING_FAIL;
}
#undef CC
#undef CC_opt
#undef DECIMAL
#undef BIN
}
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
argon2_type type) {
#define SS(str) \
do { \
size_t pp_len = strlen(str); \
if (pp_len >= dst_len) { \
return ARGON2_ENCODING_FAIL; \
} \
memcpy(dst, str, pp_len + 1); \
dst += pp_len; \
dst_len -= pp_len; \
} while ((void)0, 0)
#define SX(x) \
do { \
char tmp[30]; \
sprintf(tmp, "%lu", (unsigned long)(x)); \
SS(tmp); \
} while ((void)0, 0)
#define SB(buf, len) \
do { \
size_t sb_len = to_base64(dst, dst_len, buf, len); \
if (sb_len == (size_t)-1) { \
return ARGON2_ENCODING_FAIL; \
} \
dst += sb_len; \
dst_len -= sb_len; \
} while ((void)0, 0)
const char* type_string = argon2_type2string(type, 0);
int validation_result = validate_inputs(ctx);
if (!type_string) {
return ARGON2_ENCODING_FAIL;
}
if (validation_result != ARGON2_OK) {
return validation_result;
}
SS("$");
SS(type_string);
SS("$m=");
SX(ctx->m_cost);
SS(",t=");
SX(ctx->t_cost);
SS(",p=");
SX(ctx->lanes);
SS("$");
SB(ctx->salt, ctx->saltlen);
SS("$");
SB(ctx->out, ctx->outlen);
return ARGON2_OK;
#undef SS
#undef SX
#undef SB
}
size_t b64len(uint32_t len) {
size_t olen = ((size_t)len / 3) << 2;
switch (len % 3) {
case 2:
olen++;
/* fall through */
case 1:
olen += 2;
break;
}
return olen;
}
size_t numlen(uint32_t num) {
size_t len = 1;
while (num >= 10) {
++len;
num = num / 10;
}
return len;
}

View file

@ -0,0 +1,57 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef ENCODING_H
#define ENCODING_H
#include "argon2.h"
#define ARGON2_MAX_DECODED_LANES UINT32_C(255)
#define ARGON2_MIN_DECODED_SALT_LEN UINT32_C(8)
#define ARGON2_MIN_DECODED_OUT_LEN UINT32_C(12)
/*
* encode an Argon2 hash string into the provided buffer. 'dst_len'
* contains the size, in characters, of the 'dst' buffer; if 'dst_len'
* is less than the number of required characters (including the
* terminating 0), then this function returns ARGON2_ENCODING_ERROR.
*
* on success, ARGON2_OK is returned.
*/
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
argon2_type type);
/*
* Decodes an Argon2 hash string into the provided structure 'ctx'.
* The only fields that must be set prior to this call are ctx.saltlen and
* ctx.outlen (which must be the maximal salt and out length values that are
* allowed), ctx.salt and ctx.out (which must be buffers of the specified
* length), and ctx.pwd and ctx.pwdlen which must hold a valid password.
*
* Invalid input string causes an error. On success, the ctx is valid and all
* fields have been initialized.
*
* Returned value is ARGON2_OK on success, other ARGON2_ codes on error.
*/
int decode_string(argon2_context *ctx, const char *str, argon2_type type);
/* Returns the length of the encoded byte stream with length len */
size_t b64len(uint32_t len);
/* Returns the length of the encoded number num */
size_t numlen(uint32_t num);
#endif

View file

@ -1,182 +0,0 @@
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "argon2.h"
#include "cores.h"
void initial_kat(const uint8_t *blockhash, const argon2_context *context,
argon2_type type) {
unsigned i;
if (blockhash != NULL && context != NULL) {
printf("=======================================");
switch (type) {
case Argon2_d:
printf("Argon2d\n");
break;
case Argon2_i:
printf("Argon2i\n");
break;
default:
break;
}
printf("Memory: %u KiB, Iterations: %u, Parallelism: %u lanes, Tag "
"length: %u bytes\n",
context->m_cost, context->t_cost, context->lanes,
context->outlen);
printf("Password[%u]: ", context->pwdlen);
if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
printf("CLEARED\n");
} else {
for (i = 0; i < context->pwdlen; ++i) {
printf("%2.2x ", ((unsigned char *)context->pwd)[i]);
}
printf("\n");
}
printf("Salt[%u]: ", context->saltlen);
for (i = 0; i < context->saltlen; ++i) {
printf("%2.2x ", ((unsigned char *)context->salt)[i]);
}
printf("\n");
printf("Secret[%u]: ", context->secretlen);
if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
printf("CLEARED\n");
} else {
for (i = 0; i < context->secretlen; ++i) {
printf("%2.2x ", ((unsigned char *)context->secret)[i]);
}
printf("\n");
}
printf("Associated data[%u]: ", context->adlen);
for (i = 0; i < context->adlen; ++i) {
printf("%2.2x ", ((unsigned char *)context->ad)[i]);
}
printf("\n");
printf("Pre-hashing digest: ");
for (i = 0; i < ARGON2_PREHASH_DIGEST_LENGTH; ++i) {
printf("%2.2x ", ((unsigned char *)blockhash)[i]);
}
printf("\n");
}
}
void print_tag(const void *out, uint32_t outlen) {
unsigned i;
if (out != NULL) {
printf("Tag: ");
for (i = 0; i < outlen; ++i) {
printf("%2.2x ", ((uint8_t *)out)[i]);
}
printf("\n");
}
}
void internal_kat(const argon2_instance_t *instance, uint32_t pass) {
if (instance != NULL) {
uint32_t i, j;
printf("\n After pass %u:\n", pass);
for (i = 0; i < instance->memory_blocks; ++i) {
uint32_t how_many_words =
(instance->memory_blocks > ARGON2_WORDS_IN_BLOCK)
? 1
: ARGON2_WORDS_IN_BLOCK;
for (j = 0; j < how_many_words; ++j)
printf("Block %.4u [%3u]: %016" PRIx64 "\n", i, j,
instance->memory[i].v[j]);
}
}
}
static void fatal(const char *error) {
fprintf(stderr, "Error: %s\n", error);
exit(1);
}
static void generate_testvectors(const char *type) {
#define TEST_OUTLEN 32
#define TEST_PWDLEN 32
#define TEST_SALTLEN 16
#define TEST_SECRETLEN 8
#define TEST_ADLEN 12
argon2_context context;
unsigned char out[TEST_OUTLEN];
unsigned char pwd[TEST_PWDLEN];
unsigned char salt[TEST_SALTLEN];
unsigned char secret[TEST_SECRETLEN];
unsigned char ad[TEST_ADLEN];
const allocate_fptr myown_allocator = NULL;
const deallocate_fptr myown_deallocator = NULL;
unsigned t_cost = 3;
unsigned m_cost = 16;
unsigned lanes = 4;
memset(pwd, 1, TEST_OUTLEN);
memset(salt, 2, TEST_SALTLEN);
memset(secret, 3, TEST_SECRETLEN);
memset(ad, 4, TEST_ADLEN);
context.out = out;
context.outlen = TEST_OUTLEN;
context.pwd = pwd;
context.pwdlen = TEST_PWDLEN;
context.salt = salt;
context.saltlen = TEST_SALTLEN;
context.secret = secret;
context.secretlen = TEST_SECRETLEN;
context.ad = ad;
context.adlen = TEST_ADLEN;
context.t_cost = t_cost;
context.m_cost = m_cost;
context.lanes = lanes;
context.threads = lanes;
context.allocate_cbk = myown_allocator;
context.free_cbk = myown_deallocator;
context.flags = 0;
#undef TEST_OUTLEN
#undef TEST_PWDLEN
#undef TEST_SALTLEN
#undef TEST_SECRETLEN
#undef TEST_ADLEN
if (!strcmp(type, "d")) {
argon2d(&context);
} else if (!strcmp(type, "i")) {
argon2i(&context);
} else
fatal("wrong Argon2 type");
}
int main(int argc, char *argv[]) {
const char *type = (argc > 1) ? argv[1] : "i";
generate_testvectors(type);
return ARGON2_OK;
}

View file

@ -1,45 +0,0 @@
/*
* Argon2 source code package
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* You should have received a copy of the CC0 Public Domain Dedication along
* with
* this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef ARGON2_KAT_H
#define ARGON2_KAT_H
/*
* Initial KAT function that prints the inputs to the file
* @param blockhash Array that contains pre-hashing digest
* @param context Holds inputs
* @param type Argon2 type
* @pre blockhash must point to INPUT_INITIAL_HASH_LENGTH bytes
* @pre context member pointers must point to allocated memory of size according
* to the length values
*/
void initial_kat(const uint8_t *blockhash, const argon2_context *context,
argon2_type type);
/*
* Function that prints the output tag
* @param out output array pointer
* @param outlen digest length
* @pre out must point to @a outlen bytes
**/
void print_tag(const void *out, uint32_t outlen);
/*
* Function that prints the internal state at given moment
* @param instance pointer to the current instance
* @param pass current pass number
* @pre instance must have necessary memory allocated
**/
void internal_kat(const argon2_instance_t *instance, uint32_t pass);
#endif

View file

@ -1,150 +1,214 @@
/* /*
* Argon2 source code package * Argon2 reference source code package - reference C implementations
* *
* Written by Daniel Dinu and Dmitry Khovratovich, 2015 * Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
* *
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver. * You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
* *
* You should have received a copy of the CC0 Public Domain Dedication along * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* with * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* this software. If not, see *
* <http://creativecommons.org/publicdomain/zero/1.0/>. * You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/ */
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <immintrin.h>
#include "argon2.h" #include "argon2.h"
#include "cores.h" #include "core.h"
#include "opt.h"
#include "blake2/blake2.h" #include "../blake2/blake2.h"
#include "blake2/blamka-round-opt.h" #include "../blake2/blamka-round-opt.h"
void fill_block(__m128i *state, __m128i const *ref_block, __m128i *next_block) /*
{ * Function fills a new memory block and optionally XORs the old block over the new one.
__m128i block_XY[ARGON2_QWORDS_IN_BLOCK] __attribute__ ((aligned (16))); * Memory must be initialized.
uint32_t i; * @param state Pointer to the just produced block. Content will be updated(!)
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++) { * @param ref_block Pointer to the reference block
block_XY[i] = state[i] = _mm_xor_si128( * @param next_block Pointer to the block to be XORed over. May coincide with @ref_block
state[i], _mm_load_si128(&ref_block[i])); * @param with_xor Whether to XOR into the new block (1) or just overwrite (0)
* @pre all block pointers must be valid
*/
#if defined(__AVX512F__)
static void fill_block(__m512i *state, const block *ref_block,
block *next_block, int with_xor) {
__m512i block_XY[ARGON2_512BIT_WORDS_IN_BLOCK];
unsigned int i;
if (with_xor) {
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
state[i] = _mm512_xor_si512(
state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i));
block_XY[i] = _mm512_xor_si512(
state[i], _mm512_loadu_si512((const __m512i *)next_block->v + i));
}
} else {
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
block_XY[i] = state[i] = _mm512_xor_si512(
state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i));
}
} }
BLAKE2_ROUND(state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7]); for (i = 0; i < 2; ++i) {
BLAKE2_ROUND(state[8], state[9], state[10], state[11], state[12], state[13], state[14], state[15]); BLAKE2_ROUND_1(
BLAKE2_ROUND(state[16], state[17], state[18], state[19], state[20], state[21], state[22], state[23]); state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], state[8 * i + 3],
BLAKE2_ROUND(state[24], state[25], state[26], state[27], state[28], state[29], state[30], state[31]); state[8 * i + 4], state[8 * i + 5], state[8 * i + 6], state[8 * i + 7]);
BLAKE2_ROUND(state[32], state[33], state[34], state[35], state[36], state[37], state[38], state[39]); }
BLAKE2_ROUND(state[40], state[41], state[42], state[43], state[44], state[45], state[46], state[47]);
BLAKE2_ROUND(state[48], state[49], state[50], state[51], state[52], state[53], state[54], state[55]); for (i = 0; i < 2; ++i) {
BLAKE2_ROUND(state[56], state[57], state[58], state[59], state[60], state[61], state[62], state[63]); BLAKE2_ROUND_2(
/*for (i = 0; i < 8; ++i) { state[2 * 0 + i], state[2 * 1 + i], state[2 * 2 + i], state[2 * 3 + i],
state[2 * 4 + i], state[2 * 5 + i], state[2 * 6 + i], state[2 * 7 + i]);
}
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
state[i] = _mm512_xor_si512(state[i], block_XY[i]);
_mm512_storeu_si512((__m512i *)next_block->v + i, state[i]);
}
}
#elif defined(__AVX2__)
static void fill_block(__m256i *state, const block *ref_block,
block *next_block, int with_xor) {
__m256i block_XY[ARGON2_HWORDS_IN_BLOCK];
unsigned int i;
if (with_xor) {
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
state[i] = _mm256_xor_si256(
state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i));
block_XY[i] = _mm256_xor_si256(
state[i], _mm256_loadu_si256((const __m256i *)next_block->v + i));
}
} else {
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
block_XY[i] = state[i] = _mm256_xor_si256(
state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i));
}
}
for (i = 0; i < 4; ++i) {
BLAKE2_ROUND_1(state[8 * i + 0], state[8 * i + 4], state[8 * i + 1], state[8 * i + 5],
state[8 * i + 2], state[8 * i + 6], state[8 * i + 3], state[8 * i + 7]);
}
for (i = 0; i < 4; ++i) {
BLAKE2_ROUND_2(state[ 0 + i], state[ 4 + i], state[ 8 + i], state[12 + i],
state[16 + i], state[20 + i], state[24 + i], state[28 + i]);
}
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
state[i] = _mm256_xor_si256(state[i], block_XY[i]);
_mm256_storeu_si256((__m256i *)next_block->v + i, state[i]);
}
}
#else
static void fill_block(__m128i *state, const block *ref_block,
block *next_block, int with_xor) {
__m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
unsigned int i;
if (with_xor) {
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
state[i] = _mm_xor_si128(
state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i));
block_XY[i] = _mm_xor_si128(
state[i], _mm_loadu_si128((const __m128i *)next_block->v + i));
}
} else {
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
block_XY[i] = state[i] = _mm_xor_si128(
state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i));
}
}
for (i = 0; i < 8; ++i) {
BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
state[8 * i + 3], state[8 * i + 4], state[8 * i + 5], state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
state[8 * i + 6], state[8 * i + 7]); state[8 * i + 6], state[8 * i + 7]);
}*/ }
BLAKE2_ROUND(state[0], state[8], state[16], state[24], state[32], state[40], state[48], state[56]); for (i = 0; i < 8; ++i) {
BLAKE2_ROUND(state[1], state[9], state[17], state[25], state[33], state[41], state[49], state[57]);
BLAKE2_ROUND(state[2], state[10], state[18], state[26], state[34], state[42], state[50], state[58]);
BLAKE2_ROUND(state[3], state[11], state[19], state[27], state[35], state[43], state[51], state[59]);
BLAKE2_ROUND(state[4], state[12], state[20], state[28], state[36], state[44], state[52], state[60]);
BLAKE2_ROUND(state[5], state[13], state[21], state[29], state[37], state[45], state[53], state[61]);
BLAKE2_ROUND(state[6], state[14], state[22], state[30], state[38], state[46], state[54], state[62]);
BLAKE2_ROUND(state[7], state[15], state[23], state[31], state[39], state[47], state[55], state[63]);
/*for (i = 0; i < 8; ++i) {
BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i], BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i], state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
state[8 * 6 + i], state[8 * 7 + i]); state[8 * 6 + i], state[8 * 7 + i]);
}*/ }
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++) { for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
state[i] = _mm_xor_si128(state[i], block_XY[i]); state[i] = _mm_xor_si128(state[i], block_XY[i]);
_mm_storeu_si128(&next_block[i], state[i]); _mm_storeu_si128((__m128i *)next_block->v + i, state[i]);
} }
} }
#endif
static const uint64_t bad_rands[32] = { static void next_addresses(block *address_block, block *input_block) {
UINT64_C(17023632018251376180), UINT64_C(4911461131397773491), /*Temporary zero-initialized blocks*/
UINT64_C(15927076453364631751), UINT64_C(7860239898779391109), #if defined(__AVX512F__)
__m512i zero_block[ARGON2_512BIT_WORDS_IN_BLOCK];
__m512i zero2_block[ARGON2_512BIT_WORDS_IN_BLOCK];
#elif defined(__AVX2__)
__m256i zero_block[ARGON2_HWORDS_IN_BLOCK];
__m256i zero2_block[ARGON2_HWORDS_IN_BLOCK];
#else
__m128i zero_block[ARGON2_OWORDS_IN_BLOCK];
__m128i zero2_block[ARGON2_OWORDS_IN_BLOCK];
#endif
UINT64_C(11820267568857244377), UINT64_C(12188179869468676617), memset(zero_block, 0, sizeof(zero_block));
UINT64_C(3732913385414474778), UINT64_C(7651458777762572084), memset(zero2_block, 0, sizeof(zero2_block));
UINT64_C(3062274162574341415), UINT64_C(17922653540258786897), /*Increasing index counter*/
UINT64_C(17393848266100524980), UINT64_C(8539695715554563839), input_block->v[6]++;
UINT64_C(13824538050656654359), UINT64_C(12078939433126460936), /*First iteration of G*/
UINT64_C(15331979418564540430), UINT64_C(12058346794217174273), fill_block(zero_block, input_block, address_block, 0);
UINT64_C(13593922096015221049), UINT64_C(18356682276374416500), /*Second iteration of G*/
UINT64_C(4968040514092703824), UINT64_C(11202790346130235567), fill_block(zero2_block, address_block, address_block, 0);
UINT64_C(2276229735041314644), UINT64_C(220837743321691382),
UINT64_C(4861211596230784273), UINT64_C(6330592584132590331),
UINT64_C(3515580430960296763), UINT64_C(9869356316971855173),
UINT64_C(485533243489193056), UINT64_C(14596447761048148032),
UINT64_C(16531790085730132900), UINT64_C(17328824500878824371),
UINT64_C(8548260058287621283), UINT64_C(8641748798041936364)
};
void generate_addresses(const argon2_instance_t *instance,
const argon2_position_t *position,
uint64_t *pseudo_rands)
{
uint8_t offset = position->pass * 16 + position->slice * 4;
pseudo_rands[0] = bad_rands[offset++];
pseudo_rands[1] = bad_rands[offset++];
pseudo_rands[2] = bad_rands[offset++];
pseudo_rands[3] = bad_rands[offset++];
/*if ((position->pass == 1 && position->slice == 3))
print64("pseudo_rands", pseudo_rands, 4);*/
} }
#define SEGMENT_LENGTH 4
#define LANE_LENGTH 16
#define POS_LANE 0
void fill_segment(const argon2_instance_t *instance, void fill_segment(const argon2_instance_t *instance,
argon2_position_t position) argon2_position_t position) {
{
block *ref_block = NULL, *curr_block = NULL; block *ref_block = NULL, *curr_block = NULL;
uint64_t pseudo_rand, ref_index; block address_block, input_block;
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset; uint32_t prev_offset, curr_offset;
uint8_t i; uint32_t starting_index, i;
__m128i state[64]; #if defined(__AVX512F__)
int data_independent_addressing = (instance->type == Argon2_i); __m512i state[ARGON2_512BIT_WORDS_IN_BLOCK];
#elif defined(__AVX2__)
__m256i state[ARGON2_HWORDS_IN_BLOCK];
#else
__m128i state[ARGON2_OWORDS_IN_BLOCK];
#endif
int data_independent_addressing;
/* Pseudo-random values that determine the reference block position */ if (instance == NULL) {
uint64_t *pseudo_rands = NULL; return;
pseudo_rands = (uint64_t *)malloc(/*sizeof(uint64_t) * 4*/32);
if (data_independent_addressing) {
generate_addresses(instance, &position, pseudo_rands);
} }
i = 0; starting_index = 0;
if ((0 == position.pass) && (0 == position.slice)) { if ((0 == position.pass) && (0 == position.slice)) {
i = 2; /* we have already generated the first two blocks */ starting_index = 2; /* we have already generated the first two blocks */
/* Don't forget to generate the first block of addresses: */
if (data_independent_addressing) {
next_addresses(&address_block, &input_block);
}
} }
/*printf("Position.lane = %d\nPosition.slice = %d\nStarting index : %d\n", position.lane, position.slice, starting_index);*/
/* Offset of the current block */ /* Offset of the current block */
curr_offset = position.slice * 4 + i; curr_offset = position.lane * instance->lane_length +
position.slice * instance->segment_length + starting_index;
if (0 == curr_offset % 16) { if (0 == curr_offset % instance->lane_length) {
/* Last block in this lane */ /* Last block in this lane */
prev_offset = curr_offset + /*instance->lane_length - 1*/15; prev_offset = curr_offset + instance->lane_length - 1;
} else { } else {
/* Previous block */ /* Previous block */
prev_offset = curr_offset - 1; prev_offset = curr_offset - 1;
@ -152,34 +216,45 @@ void fill_segment(const argon2_instance_t *instance,
memcpy(state, ((instance->memory + prev_offset)->v), ARGON2_BLOCK_SIZE); memcpy(state, ((instance->memory + prev_offset)->v), ARGON2_BLOCK_SIZE);
for (; i < SEGMENT_LENGTH; for (i = starting_index; i < instance->segment_length;
++i, ++curr_offset, ++prev_offset) { ++i, ++curr_offset, ++prev_offset) {
/*1.1 Rotating prev_offset if needed */ /*1.1 Rotating prev_offset if needed */
if (curr_offset % LANE_LENGTH == 1) { if (curr_offset % instance->lane_length == 1) {
prev_offset = curr_offset - 1; prev_offset = curr_offset - 1;
} }
/* 1.2 Computing the index of the reference block */ /* 1.2 Computing the index of the reference block */
/* 1.2.1 Taking pseudo-random value from the previous block */ /* 1.2.1 Taking pseudo-random value from the previous block */
if (data_independent_addressing) { if (data_independent_addressing) {
pseudo_rand = pseudo_rands[i]; if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
next_addresses(&address_block, &input_block);
}
pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
} else { } else {
pseudo_rand = instance->memory[prev_offset].v[0]; pseudo_rand = instance->memory[prev_offset].v[0];
} }
/* 1.2.2 Computing the lane of the reference block */ /* 1.2.2 Computing the lane of the reference block */
ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
if ((position.pass == 0) && (position.slice == 0)) {
/* Can not reference other lanes yet */
ref_lane = position.lane;
}
/* 1.2.3 Computing the number of possible reference block within the /* 1.2.3 Computing the number of possible reference block within the
* lane. * lane.
*/ */
position.index = i; position.index = i;
ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,1); ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
ref_lane == position.lane);
/* 2 Creating a new block */ /* 2 Creating a new block */
ref_block = instance->memory + ref_index; ref_block =
instance->memory + instance->lane_length * ref_lane + ref_index;
curr_block = instance->memory + curr_offset; curr_block = instance->memory + curr_offset;
fill_block(state, (__m128i const *)ref_block->v, (__m128i *)curr_block->v);
}
free(pseudo_rands); fill_block(state, ref_block, curr_block, 0);
}
} }

View file

@ -1,49 +0,0 @@
/*
* Argon2 source code package
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* You should have received a copy of the CC0 Public Domain Dedication along
* with
* this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef ARGON2_OPT_H
#define ARGON2_OPT_H
/*
* Function fills a new memory block. Differs from the
* @param state Pointer to the just produced block. Content will be updated(!)
* @param ref_block Pointer to the reference block
* @param next_block Pointer to the block to be constructed
* @pre all block pointers must be valid
*/
void fill_block(__m128i *state, __m128i const *ref_block, __m128i *next_block);
/*
* Generate pseudo-random values to reference blocks in the segment and puts
* them into the array
* @param instance Pointer to the current instance
* @param position Pointer to the current position
* @param pseudo_rands Pointer to the array of 64-bit values
* @pre pseudo_rands must point to @a instance->segment_length allocated values
*/
void generate_addresses(const argon2_instance_t *instance,
const argon2_position_t *position,
uint64_t *pseudo_rands);
/*
* Function that fills the segment using previous segments also from other
* threads.
* Identical to the reference code except that it calls optimized FillBlock()
* @param instance Pointer to the current instance
* @param position Current position
* @pre all block pointers must be valid
*/
void fill_segment(const argon2_instance_t *instance,
argon2_position_t position);
#endif /* ARGON2_OPT_H */

View file

@ -1,174 +0,0 @@
/*
* Argon2 source code package
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* You should have received a copy of the CC0 Public Domain Dedication along
* with
* this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "argon2.h"
#include "cores.h"
#include "ref.h"
#include "blake2/blamka-round-ref.h"
#include "blake2/blake2-impl.h"
#include "blake2/blake2.h"
void fill_block(const block *prev_block, const block *ref_block,
block *next_block) {
block blockR, block_tmp;
unsigned i;
copy_block(&blockR, ref_block);
xor_block(&blockR, prev_block);
copy_block(&block_tmp, &blockR);
/* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
(16,17,..31)... finally (112,113,...127) */
for (i = 0; i < 8; ++i) {
BLAKE2_ROUND_NOMSG(
blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2],
blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5],
blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8],
blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11],
blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14],
blockR.v[16 * i + 15]);
}
/* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
(2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
for (i = 0; i < 8; i++) {
BLAKE2_ROUND_NOMSG(
blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16],
blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33],
blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64],
blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81],
blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112],
blockR.v[2 * i + 113]);
}
copy_block(next_block, &block_tmp);
xor_block(next_block, &blockR);
}
void generate_addresses(const argon2_instance_t *instance,
const argon2_position_t *position,
uint64_t *pseudo_rands) {
block zero_block, input_block, address_block;
uint32_t i;
init_block_value(&zero_block, 0);
init_block_value(&input_block, 0);
init_block_value(&address_block, 0);
if (instance != NULL && position != NULL) {
input_block.v[0] = position->pass;
input_block.v[1] = position->lane;
input_block.v[2] = position->slice;
input_block.v[3] = 16;
input_block.v[4] = 2;
input_block.v[5] = instance->type;
for (i = 0; i < 4; ++i) {
if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
input_block.v[6]++;
fill_block(&zero_block, &input_block, &address_block);
fill_block(&zero_block, &address_block, &address_block);
}
pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
}
}
}
void fill_segment(const argon2_instance_t *instance,
argon2_position_t position) {
block *ref_block = NULL, *curr_block = NULL;
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
uint32_t starting_index;
uint32_t i;
int data_independent_addressing = (instance->type == Argon2_i);
/* Pseudo-random values that determine the reference block position */
uint64_t *pseudo_rands = NULL;
if (instance == NULL) {
return;
}
pseudo_rands =
(uint64_t *)malloc(sizeof(uint64_t) * 4);
if (pseudo_rands == NULL) {
return;
}
if (data_independent_addressing) {
generate_addresses(instance, &position, pseudo_rands);
}
starting_index = 0;
if ((0 == position.pass) && (0 == position.slice)) {
starting_index = 2; /* we have already generated the first two blocks */
}
/* Offset of the current block */
curr_offset = position.lane * 16 +
position.slice * 4 + starting_index;
if (0 == curr_offset % 16) {
/* Last block in this lane */
prev_offset = curr_offset + 16 - 1;
} else {
/* Previous block */
prev_offset = curr_offset - 1;
}
for (i = starting_index; i < 4; ++i, ++curr_offset, ++prev_offset) {
/*1.1 Rotating prev_offset if needed */
if (curr_offset % 16 == 1) {
prev_offset = curr_offset - 1;
}
/* 1.2 Computing the index of the reference block */
/* 1.2.1 Taking pseudo-random value from the previous block */
if (data_independent_addressing) {
pseudo_rand = pseudo_rands[i];
} else {
pseudo_rand = instance->memory[prev_offset].v[0];
}
/* 1.2.2 Computing the lane of the reference block */
ref_lane = ((pseudo_rand >> 32)) % 1;
if ((position.pass == 0) && (position.slice == 0)) {
/* Can not reference other lanes yet */
ref_lane = position.lane;
}
/* 1.2.3 Computing the number of possible reference block within the
* lane.
*/
position.index = i;
ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
ref_lane == position.lane);
/* 2 Creating a new block */
ref_block =
instance->memory + 16 * ref_lane + ref_index;
curr_block = instance->memory + curr_offset;
fill_block(instance->memory + prev_offset, ref_block, curr_block);
}
free(pseudo_rands);
}

View file

@ -1,49 +0,0 @@
/*
* Argon2 source code package
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* You should have received a copy of the CC0 Public Domain Dedication along
* with
* this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef ARGON2_REF_H
#define ARGON2_REF_H
/*
* Function fills a new memory block
* @param prev_block Pointer to the previous block
* @param ref_block Pointer to the reference block
* @param next_block Pointer to the block to be constructed
* @pre all block pointers must be valid
*/
void fill_block(const block *prev_block, const block *ref_block,
block *next_block);
/*
* Generate pseudo-random values to reference blocks in the segment and puts
* them into the array
* @param instance Pointer to the current instance
* @param position Pointer to the current position
* @param pseudo_rands Pointer to the array of 64-bit values
* @pre pseudo_rands must point to @a instance->segment_length allocated values
*/
void generate_addresses(const argon2_instance_t *instance,
const argon2_position_t *position,
uint64_t *pseudo_rands);
/*
* Function that fills the segment using previous segments also from other
* threads
* @param instance Pointer to the current instance
* @param position Current position
* @pre all block pointers must be valid
*/
void fill_segment(const argon2_instance_t *instance,
argon2_position_t position);
#endif /* ARGON2_REF_H */

View file

@ -1,223 +0,0 @@
/*
* Argon2 source code package
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* You should have received a copy of the CC0 Public Domain Dedication along
* with
* this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "argon2.h"
#include "cores.h"
#define T_COST_DEF 3
#define LOG_M_COST_DEF 12 /* 2^12 = 4 MiB */
#define LANES_DEF 1
#define THREADS_DEF 1
#define OUT_LEN 32
#define SALT_LEN 16
#define UNUSED_PARAMETER(x) (void)(x)
static void usage(const char *cmd) {
printf("Usage: %s pwd salt [-y version] [-t iterations] [-m memory] [-p "
"parallelism]\n",
cmd);
printf("Parameters:\n");
printf("\tpwd\t\tThe password to hash\n");
printf("\tsalt\t\tThe salt to use, at most 16 characters\n");
printf("\t-d\t\tUse Argon2d instead of Argon2i (which is the default)\n");
printf("\t-t N\t\tSets the number of iterations to N (default = %d)\n",
T_COST_DEF);
printf("\t-m N\t\tSets the memory usage of 2^N KiB (default %d)\n",
LOG_M_COST_DEF);
printf("\t-p N\t\tSets parallelism to N threads (default %d)\n",
THREADS_DEF);
}
static void fatal(const char *error) {
fprintf(stderr, "Error: %s\n", error);
exit(1);
}
/*
Runs Argon2 with certain inputs and parameters, inputs not cleared. Prints the
Base64-encoded hash string
@out output array with at least 32 bytes allocated
@pwd NULL-terminated string, presumably from argv[]
@salt salt array with at least SALTLEN_DEF bytes allocated
@t_cost number of iterations
@m_cost amount of requested memory in KB
@lanes amount of requested parallelism
@threads actual parallelism
@type String, only "d" and "i" are accepted
*/
static void run(uint8_t *out, char *pwd, uint8_t *salt, uint32_t t_cost,
uint32_t m_cost, uint32_t lanes, uint32_t threads,
const char *type) {
clock_t start_time, stop_time;
unsigned pwd_length;
argon2_context context;
int i;
start_time = clock();
if (!pwd) {
fatal("password missing");
}
if (!salt) {
secure_wipe_memory(pwd, strlen(pwd));
fatal("salt missing");
}
pwd_length = strlen(pwd);
UNUSED_PARAMETER(threads);
context.out = out;
context.outlen = OUT_LEN;
context.pwd = (uint8_t *)pwd;
context.pwdlen = pwd_length;
context.salt = salt;
context.saltlen = SALT_LEN;
context.secret = NULL;
context.secretlen = 0;
context.ad = NULL;
context.adlen = 0;
context.t_cost = t_cost;
context.m_cost = m_cost;
context.lanes = lanes;
context.threads = lanes;
context.allocate_cbk = NULL;
context.free_cbk = NULL;
context.flags = ARGON2_FLAG_CLEAR_PASSWORD;
if (!strcmp(type, "d")) {
int result = argon2d(&context);
if (result != ARGON2_OK)
fatal(error_message(result));
} else if (!strcmp(type, "i")) {
int result = argon2i(&context);
if (result != ARGON2_OK)
fatal(error_message(result));
} else {
secure_wipe_memory(pwd, strlen(pwd));
fatal("wrong Argon2 type");
}
stop_time = clock();
/* add back when proper decoding */
/*
char encoded[300];
encode_string(encoded, sizeof encoded, &context);
printf("%s\n", encoded);
*/
printf("Hash:\t\t");
for (i = 0; i < context.outlen; ++i) {
printf("%02x", context.out[i]);
}
printf("\n");
printf("%2.3f seconds\n",
((double)stop_time - start_time) / (CLOCKS_PER_SEC));
}
int main(int argc, char *argv[]) {
unsigned char out[OUT_LEN];
uint32_t m_cost = 1 << LOG_M_COST_DEF;
uint32_t t_cost = T_COST_DEF;
uint32_t lanes = LANES_DEF;
uint32_t threads = THREADS_DEF;
char *pwd = NULL;
uint8_t salt[SALT_LEN];
const char *type = "i";
int i;
if (argc < 3) {
usage(argv[0]);
return ARGON2_MISSING_ARGS;
}
/* get password and salt from command line */
pwd = argv[1];
if (strlen(argv[2]) > SALT_LEN) {
fatal("salt too long");
}
memset(salt, 0x00, SALT_LEN); /* pad with null bytes */
memcpy(salt, argv[2], strlen(argv[2]));
/* parse options */
for (i = 3; i < argc; i++) {
const char *a = argv[i];
unsigned long input = 0;
if (!strcmp(a, "-m")) {
if (i < argc - 1) {
i++;
input = strtoul(argv[i], NULL, 10);
if (input == 0 || input == ULONG_MAX ||
input > ARGON2_MAX_MEMORY_BITS) {
fatal("bad numeric input for -m");
}
m_cost = ARGON2_MIN(UINT64_C(1) << input, UINT32_C(0xFFFFFFFF));
if (m_cost > ARGON2_MAX_MEMORY) {
fatal("m_cost overflow");
}
continue;
} else {
fatal("missing -m argument");
}
} else if (!strcmp(a, "-t")) {
if (i < argc - 1) {
i++;
input = strtoul(argv[i], NULL, 10);
if (input == 0 || input == ULONG_MAX ||
input > ARGON2_MAX_TIME) {
fatal("bad numeric input for -t");
}
t_cost = input;
continue;
} else {
fatal("missing -t argument");
}
} else if (!strcmp(a, "-p")) {
if (i < argc - 1) {
i++;
input = strtoul(argv[i], NULL, 10);
if (input == 0 || input == ULONG_MAX ||
input > ARGON2_MAX_THREADS || input > ARGON2_MAX_LANES) {
fatal("bad numeric input for -p");
}
threads = input;
lanes = threads;
continue;
} else {
fatal("missing -p argument");
}
} else if (!strcmp(a, "-d")) {
type = "d";
} else {
fatal("unknown argument");
}
}
printf("Type:\t\tArgon2%c\n", type[0]);
printf("Iterations:\t%" PRIu32 " \n", t_cost);
printf("Memory:\t\t%" PRIu32 " KiB\n", m_cost);
printf("Parallelism:\t%" PRIu32 " \n", lanes);
run(out, pwd, salt, t_cost, m_cost, lanes, threads, type);
return ARGON2_OK;
}

View file

@ -0,0 +1,57 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#if !defined(ARGON2_NO_THREADS)
#include "thread.h"
#if defined(_WIN32)
#include <windows.h>
#endif
int argon2_thread_create(argon2_thread_handle_t *handle,
argon2_thread_func_t func, void *args) {
if (NULL == handle || func == NULL) {
return -1;
}
#if defined(_WIN32)
*handle = _beginthreadex(NULL, 0, func, args, 0, NULL);
return *handle != 0 ? 0 : -1;
#else
return pthread_create(handle, NULL, func, args);
#endif
}
int argon2_thread_join(argon2_thread_handle_t handle) {
#if defined(_WIN32)
if (WaitForSingleObject((HANDLE)handle, INFINITE) == WAIT_OBJECT_0) {
return CloseHandle((HANDLE)handle) != 0 ? 0 : -1;
}
return -1;
#else
return pthread_join(handle, NULL);
#endif
}
void argon2_thread_exit(void) {
#if defined(_WIN32)
_endthreadex(0);
#else
pthread_exit(NULL);
#endif
}
#endif /* ARGON2_NO_THREADS */

View file

@ -0,0 +1,67 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef ARGON2_THREAD_H
#define ARGON2_THREAD_H
#if !defined(ARGON2_NO_THREADS)
/*
Here we implement an abstraction layer for the simpĺe requirements
of the Argon2 code. We only require 3 primitives---thread creation,
joining, and termination---so full emulation of the pthreads API
is unwarranted. Currently we wrap pthreads and Win32 threads.
The API defines 2 types: the function pointer type,
argon2_thread_func_t,
and the type of the thread handle---argon2_thread_handle_t.
*/
#if defined(_WIN32)
#include <process.h>
typedef unsigned(__stdcall *argon2_thread_func_t)(void *);
typedef uintptr_t argon2_thread_handle_t;
#else
#include <pthread.h>
typedef void *(*argon2_thread_func_t)(void *);
typedef pthread_t argon2_thread_handle_t;
#endif
/* Creates a thread
* @param handle pointer to a thread handle, which is the output of this
* function. Must not be NULL.
* @param func A function pointer for the thread's entry point. Must not be
* NULL.
* @param args Pointer that is passed as an argument to @func. May be NULL.
* @return 0 if @handle and @func are valid pointers and a thread is successfuly
* created.
*/
int argon2_thread_create(argon2_thread_handle_t *handle,
argon2_thread_func_t func, void *args);
/* Waits for a thread to terminate
* @param handle Handle to a thread created with argon2_thread_create.
* @return 0 if @handle is a valid handle, and joining completed successfully.
*/
int argon2_thread_join(argon2_thread_handle_t handle);
/* Terminate the current thread. Must be run inside a thread created by
* argon2_thread_create.
*/
void argon2_thread_exit(void);
#endif /* ARGON2_NO_THREADS */
#endif

View file

@ -5,8 +5,9 @@
#include "sysendian.h" #include "sysendian.h"
#include "argon2a.h"
#include "ar2/argon2.h" #include "ar2/argon2.h"
#include "ar2/cores.h" #include "ar2/core.h"
#include "ar2/ar2-scrypt-jane.h" #include "ar2/ar2-scrypt-jane.h"
#define _ALIGN(x) __attribute__ ((aligned(x))) #define _ALIGN(x) __attribute__ ((aligned(x)))
@ -24,10 +25,10 @@ inline void argon_call(void *out, void *in, void *salt, int type)
context.pwd = (uint8_t *)in; context.pwd = (uint8_t *)in;
context.salt = (uint8_t *)salt; context.salt = (uint8_t *)salt;
argon2_core(&context, type); argon2_ctx(&context, type);
} }
void argon2_hash(const char* input, char* output, uint32_t len) void argon2a_hash(const char* input, char* output, uint32_t len)
{ {
uint32_t _ALIGN(32) hashA[8], hashB[8]; uint32_t _ALIGN(32) hashA[8], hashB[8];

View file

@ -7,7 +7,7 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
void argon2_hash(const char* input, char* output, uint32_t len); void argon2a_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -0,0 +1,43 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "sysendian.h"
#include "ar2/argon2.h"
#include "ar2/core.h"
static const size_t INPUT_BYTES = 80; // Lenth of a block header in bytes. Input Length = Salt Length (salt = input)
static const size_t OUTPUT_BYTES = 32; // Length of output needed for a 256-bit hash
static const unsigned int DEFAULT_ARGON2_FLAG = 2; //Same as ARGON2_DEFAULT_FLAGS
void argon2d_call(const void *input, void *output)
{
argon2_context context;
context.out = (uint8_t *)output;
context.outlen = (uint32_t)OUTPUT_BYTES;
context.pwd = (uint8_t *)input;
context.pwdlen = (uint32_t)INPUT_BYTES;
context.salt = (uint8_t *)input; //salt = input
context.saltlen = (uint32_t)INPUT_BYTES;
context.secret = NULL;
context.secretlen = 0;
context.ad = NULL;
context.adlen = 0;
context.allocate_cbk = NULL;
context.free_cbk = NULL;
context.flags = DEFAULT_ARGON2_FLAG; // = ARGON2_DEFAULT_FLAGS
// main configurable Argon2 hash parameters
context.m_cost = 500; // Memory in KiB (512KB)
context.lanes = 8; // Degree of Parallelism
context.threads = 1; // Threads
context.t_cost = 2; // Iterations
argon2_ctx(&context, Argon2_d);
}
void argon2d_dyn_hash(const unsigned char* input, unsigned char* output, unsigned int len)
{
argon2d_call(input, output);
}

View file

@ -0,0 +1,16 @@
#ifndef ARGON2D_H
#define ARGON2D_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void argon2d_dyn_hash(const char* input, char* output, unsigned int len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,3 +1,20 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef PORTABLE_BLAKE2_IMPL_H #ifndef PORTABLE_BLAKE2_IMPL_H
#define PORTABLE_BLAKE2_IMPL_H #define PORTABLE_BLAKE2_IMPL_H
@ -134,10 +151,6 @@ static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) {
return (w >> c) | (w << (64 - c)); return (w >> c) | (w << (64 - c));
} }
/* prevents compiler optimizing out memset() */ void clear_internal_memory(void *v, size_t n);
static BLAKE2_INLINE void burn(void *v, size_t n) {
static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
memset_v(v, 0, n);
}
#endif #endif

View file

@ -1,3 +1,20 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef PORTABLE_BLAKE2_H #ifndef PORTABLE_BLAKE2_H
#define PORTABLE_BLAKE2_H #define PORTABLE_BLAKE2_H
@ -37,10 +54,10 @@ typedef struct __blake2b_state {
uint64_t h[8]; uint64_t h[8];
uint64_t t[2]; uint64_t t[2];
uint64_t f[2]; uint64_t f[2];
uint8_t buf[BLAKE2B_BLOCKBYTES];
unsigned buflen; unsigned buflen;
unsigned outlen; unsigned outlen;
uint8_t last_node; uint8_t last_node;
uint8_t buf[BLAKE2B_BLOCKBYTES];
} blake2b_state; } blake2b_state;
/* Ensure param structs have not been wrongly padded */ /* Ensure param structs have not been wrongly padded */
@ -57,17 +74,15 @@ int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
size_t keylen); size_t keylen);
int blake2b_init_param(blake2b_state *S, const blake2b_param *P); int blake2b_init_param(blake2b_state *S, const blake2b_param *P);
int blake2b_update(blake2b_state *S, const void *in, size_t inlen); int blake2b_update(blake2b_state *S, const void *in, size_t inlen);
void my_blake2b_update(blake2b_state *S, const void *in, size_t inlen);
int blake2b_final(blake2b_state *S, void *out, size_t outlen); int blake2b_final(blake2b_state *S, void *out, size_t outlen);
/* Simple API */ /* Simple API */
int blake2b(void *out, const void *in, const void *key, size_t keylen); int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
const void *key, size_t keylen);
/* Argon2 Team - Begin Code */ /* Argon2 Team - Begin Code */
int blake2b_long(void *out, const void *in); int blake2b_long(void *out, size_t outlen, const void *in, size_t inlen);
/* Argon2 Team - End Code */ /* Argon2 Team - End Code */
/* Miouyouyou */
void blake2b_too(void *out, const void *in);
#if defined(__cplusplus) #if defined(__cplusplus)
} }

View file

@ -0,0 +1,390 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "blake2.h"
#include "blake2-impl.h"
static const uint64_t blake2b_IV[8] = {
UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b),
UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1),
UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f),
UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179)};
static const unsigned int blake2b_sigma[12][16] = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
{12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
{13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
{6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
{10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
};
static BLAKE2_INLINE void blake2b_set_lastnode(blake2b_state *S) {
S->f[1] = (uint64_t)-1;
}
static BLAKE2_INLINE void blake2b_set_lastblock(blake2b_state *S) {
if (S->last_node) {
blake2b_set_lastnode(S);
}
S->f[0] = (uint64_t)-1;
}
static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S,
uint64_t inc) {
S->t[0] += inc;
S->t[1] += (S->t[0] < inc);
}
static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) {
clear_internal_memory(S, sizeof(*S)); /* wipe */
blake2b_set_lastblock(S); /* invalidate for further use */
}
static BLAKE2_INLINE void blake2b_init0(blake2b_state *S) {
memset(S, 0, sizeof(*S));
memcpy(S->h, blake2b_IV, sizeof(S->h));
}
int blake2b_init_param(blake2b_state *S, const blake2b_param *P) {
const unsigned char *p = (const unsigned char *)P;
unsigned int i;
if (NULL == P || NULL == S) {
return -1;
}
blake2b_init0(S);
/* IV XOR Parameter Block */
for (i = 0; i < 8; ++i) {
S->h[i] ^= load64(&p[i * sizeof(S->h[i])]);
}
S->outlen = P->digest_length;
return 0;
}
/* Sequential blake2b initialization */
int blake2b_init(blake2b_state *S, size_t outlen) {
blake2b_param P;
if (S == NULL) {
return -1;
}
if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) {
blake2b_invalidate_state(S);
return -1;
}
/* Setup Parameter Block for unkeyed BLAKE2 */
P.digest_length = (uint8_t)outlen;
P.key_length = 0;
P.fanout = 1;
P.depth = 1;
P.leaf_length = 0;
P.node_offset = 0;
P.node_depth = 0;
P.inner_length = 0;
memset(P.reserved, 0, sizeof(P.reserved));
memset(P.salt, 0, sizeof(P.salt));
memset(P.personal, 0, sizeof(P.personal));
return blake2b_init_param(S, &P);
}
int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
size_t keylen) {
blake2b_param P;
if (S == NULL) {
return -1;
}
if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) {
blake2b_invalidate_state(S);
return -1;
}
if ((key == 0) || (keylen == 0) || (keylen > BLAKE2B_KEYBYTES)) {
blake2b_invalidate_state(S);
return -1;
}
/* Setup Parameter Block for keyed BLAKE2 */
P.digest_length = (uint8_t)outlen;
P.key_length = (uint8_t)keylen;
P.fanout = 1;
P.depth = 1;
P.leaf_length = 0;
P.node_offset = 0;
P.node_depth = 0;
P.inner_length = 0;
memset(P.reserved, 0, sizeof(P.reserved));
memset(P.salt, 0, sizeof(P.salt));
memset(P.personal, 0, sizeof(P.personal));
if (blake2b_init_param(S, &P) < 0) {
blake2b_invalidate_state(S);
return -1;
}
{
uint8_t block[BLAKE2B_BLOCKBYTES];
memset(block, 0, BLAKE2B_BLOCKBYTES);
memcpy(block, key, keylen);
blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
/* Burn the key from stack */
clear_internal_memory(block, BLAKE2B_BLOCKBYTES);
}
return 0;
}
static void blake2b_compress(blake2b_state *S, const uint8_t *block) {
uint64_t m[16];
uint64_t v[16];
unsigned int i, r;
for (i = 0; i < 16; ++i) {
m[i] = load64(block + i * sizeof(m[i]));
}
for (i = 0; i < 8; ++i) {
v[i] = S->h[i];
}
v[8] = blake2b_IV[0];
v[9] = blake2b_IV[1];
v[10] = blake2b_IV[2];
v[11] = blake2b_IV[3];
v[12] = blake2b_IV[4] ^ S->t[0];
v[13] = blake2b_IV[5] ^ S->t[1];
v[14] = blake2b_IV[6] ^ S->f[0];
v[15] = blake2b_IV[7] ^ S->f[1];
#define G(r, i, a, b, c, d) \
do { \
a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \
d = rotr64(d ^ a, 32); \
c = c + d; \
b = rotr64(b ^ c, 24); \
a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \
d = rotr64(d ^ a, 16); \
c = c + d; \
b = rotr64(b ^ c, 63); \
} while ((void)0, 0)
#define ROUND(r) \
do { \
G(r, 0, v[0], v[4], v[8], v[12]); \
G(r, 1, v[1], v[5], v[9], v[13]); \
G(r, 2, v[2], v[6], v[10], v[14]); \
G(r, 3, v[3], v[7], v[11], v[15]); \
G(r, 4, v[0], v[5], v[10], v[15]); \
G(r, 5, v[1], v[6], v[11], v[12]); \
G(r, 6, v[2], v[7], v[8], v[13]); \
G(r, 7, v[3], v[4], v[9], v[14]); \
} while ((void)0, 0)
for (r = 0; r < 12; ++r) {
ROUND(r);
}
for (i = 0; i < 8; ++i) {
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
}
#undef G
#undef ROUND
}
int blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
const uint8_t *pin = (const uint8_t *)in;
if (inlen == 0) {
return 0;
}
/* Sanity check */
if (S == NULL || in == NULL) {
return -1;
}
/* Is this a reused state? */
if (S->f[0] != 0) {
return -1;
}
if (S->buflen + inlen > BLAKE2B_BLOCKBYTES) {
/* Complete current block */
size_t left = S->buflen;
size_t fill = BLAKE2B_BLOCKBYTES - left;
memcpy(&S->buf[left], pin, fill);
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress(S, S->buf);
S->buflen = 0;
inlen -= fill;
pin += fill;
/* Avoid buffer copies when possible */
while (inlen > BLAKE2B_BLOCKBYTES) {
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress(S, pin);
inlen -= BLAKE2B_BLOCKBYTES;
pin += BLAKE2B_BLOCKBYTES;
}
}
memcpy(&S->buf[S->buflen], pin, inlen);
S->buflen += (unsigned int)inlen;
return 0;
}
int blake2b_final(blake2b_state *S, void *out, size_t outlen) {
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
unsigned int i;
/* Sanity checks */
if (S == NULL || out == NULL || outlen < S->outlen) {
return -1;
}
/* Is this a reused state? */
if (S->f[0] != 0) {
return -1;
}
blake2b_increment_counter(S, S->buflen);
blake2b_set_lastblock(S);
memset(&S->buf[S->buflen], 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
blake2b_compress(S, S->buf);
for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
}
memcpy(out, buffer, S->outlen);
clear_internal_memory(buffer, sizeof(buffer));
clear_internal_memory(S->buf, sizeof(S->buf));
clear_internal_memory(S->h, sizeof(S->h));
return 0;
}
int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
const void *key, size_t keylen) {
blake2b_state S;
int ret = -1;
/* Verify parameters */
if (NULL == in && inlen > 0) {
goto fail;
}
if (NULL == out || outlen == 0 || outlen > BLAKE2B_OUTBYTES) {
goto fail;
}
if ((NULL == key && keylen > 0) || keylen > BLAKE2B_KEYBYTES) {
goto fail;
}
if (keylen > 0) {
if (blake2b_init_key(&S, outlen, key, keylen) < 0) {
goto fail;
}
} else {
if (blake2b_init(&S, outlen) < 0) {
goto fail;
}
}
if (blake2b_update(&S, in, inlen) < 0) {
goto fail;
}
ret = blake2b_final(&S, out, outlen);
fail:
clear_internal_memory(&S, sizeof(S));
return ret;
}
/* Argon2 Team - Begin Code */
int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) {
uint8_t *out = (uint8_t *)pout;
blake2b_state blake_state;
uint8_t outlen_bytes[sizeof(uint32_t)] = {0};
int ret = -1;
if (outlen > UINT32_MAX) {
goto fail;
}
/* Ensure little-endian byte order! */
store32(outlen_bytes, (uint32_t)outlen);
#define TRY(statement) \
do { \
ret = statement; \
if (ret < 0) { \
goto fail; \
} \
} while ((void)0, 0)
if (outlen <= BLAKE2B_OUTBYTES) {
TRY(blake2b_init(&blake_state, outlen));
TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
TRY(blake2b_update(&blake_state, in, inlen));
TRY(blake2b_final(&blake_state, out, outlen));
} else {
uint32_t toproduce;
uint8_t out_buffer[BLAKE2B_OUTBYTES];
uint8_t in_buffer[BLAKE2B_OUTBYTES];
TRY(blake2b_init(&blake_state, BLAKE2B_OUTBYTES));
TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
TRY(blake2b_update(&blake_state, in, inlen));
TRY(blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES));
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
out += BLAKE2B_OUTBYTES / 2;
toproduce = (uint32_t)outlen - BLAKE2B_OUTBYTES / 2;
while (toproduce > BLAKE2B_OUTBYTES) {
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
TRY(blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer,
BLAKE2B_OUTBYTES, NULL, 0));
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
out += BLAKE2B_OUTBYTES / 2;
toproduce -= BLAKE2B_OUTBYTES / 2;
}
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
TRY(blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL,
0));
memcpy(out, out_buffer, toproduce);
}
fail:
clear_internal_memory(&blake_state, sizeof(blake_state));
return ret;
#undef TRY
}
/* Argon2 Team - End Code */

View file

@ -0,0 +1,476 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef BLAKE_ROUND_MKA_OPT_H
#define BLAKE_ROUND_MKA_OPT_H
#if defined(HAVE_CONFIG_H)
#include "config/dynamic-config.h"
#endif
#include "blake2-impl.h"
#include <emmintrin.h>
#if defined(__SSSE3__)
#include <tmmintrin.h> /* for _mm_shuffle_epi8 and _mm_alignr_epi8 */
#endif
#if defined(__XOP__) && (defined(__GNUC__) || defined(__clang__))
#include <x86intrin.h>
#endif
#if !defined(__AVX512F__)
#if !defined(__AVX2__)
#if !defined(__XOP__)
#if defined(__SSSE3__)
#define r16 \
(_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
#define r24 \
(_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
#define _mm_roti_epi64(x, c) \
(-(c) == 32) \
? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \
: (-(c) == 24) \
? _mm_shuffle_epi8((x), r24) \
: (-(c) == 16) \
? _mm_shuffle_epi8((x), r16) \
: (-(c) == 63) \
? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
_mm_add_epi64((x), (x))) \
: _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
_mm_slli_epi64((x), 64 - (-(c))))
#else /* defined(__SSE2__) */
#define _mm_roti_epi64(r, c) \
_mm_xor_si128(_mm_srli_epi64((r), -(c)), _mm_slli_epi64((r), 64 - (-(c))))
#endif
#else
#endif
static BLAKE2_INLINE __m128i fBlaMka(__m128i x, __m128i y) {
const __m128i z = _mm_mul_epu32(x, y);
return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z));
}
#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = fBlaMka(A0, B0); \
A1 = fBlaMka(A1, B1); \
\
D0 = _mm_xor_si128(D0, A0); \
D1 = _mm_xor_si128(D1, A1); \
\
D0 = _mm_roti_epi64(D0, -32); \
D1 = _mm_roti_epi64(D1, -32); \
\
C0 = fBlaMka(C0, D0); \
C1 = fBlaMka(C1, D1); \
\
B0 = _mm_xor_si128(B0, C0); \
B1 = _mm_xor_si128(B1, C1); \
\
B0 = _mm_roti_epi64(B0, -24); \
B1 = _mm_roti_epi64(B1, -24); \
} while ((void)0, 0)
#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = fBlaMka(A0, B0); \
A1 = fBlaMka(A1, B1); \
\
D0 = _mm_xor_si128(D0, A0); \
D1 = _mm_xor_si128(D1, A1); \
\
D0 = _mm_roti_epi64(D0, -16); \
D1 = _mm_roti_epi64(D1, -16); \
\
C0 = fBlaMka(C0, D0); \
C1 = fBlaMka(C1, D1); \
\
B0 = _mm_xor_si128(B0, C0); \
B1 = _mm_xor_si128(B1, C1); \
\
B0 = _mm_roti_epi64(B0, -63); \
B1 = _mm_roti_epi64(B1, -63); \
} while ((void)0, 0)
#if defined(__SSSE3__)
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = _mm_alignr_epi8(B1, B0, 8); \
__m128i t1 = _mm_alignr_epi8(B0, B1, 8); \
B0 = t0; \
B1 = t1; \
\
t0 = C0; \
C0 = C1; \
C1 = t0; \
\
t0 = _mm_alignr_epi8(D1, D0, 8); \
t1 = _mm_alignr_epi8(D0, D1, 8); \
D0 = t1; \
D1 = t0; \
} while ((void)0, 0)
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = _mm_alignr_epi8(B0, B1, 8); \
__m128i t1 = _mm_alignr_epi8(B1, B0, 8); \
B0 = t0; \
B1 = t1; \
\
t0 = C0; \
C0 = C1; \
C1 = t0; \
\
t0 = _mm_alignr_epi8(D0, D1, 8); \
t1 = _mm_alignr_epi8(D1, D0, 8); \
D0 = t1; \
D1 = t0; \
} while ((void)0, 0)
#else /* SSE2 */
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = D0; \
__m128i t1 = B0; \
D0 = C0; \
C0 = C1; \
C1 = D0; \
D0 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t0, t0)); \
D1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(D1, D1)); \
B0 = _mm_unpackhi_epi64(B0, _mm_unpacklo_epi64(B1, B1)); \
B1 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(t1, t1)); \
} while ((void)0, 0)
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0, t1; \
t0 = C0; \
C0 = C1; \
C1 = t0; \
t0 = B0; \
t1 = D0; \
B0 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(B0, B0)); \
B1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(B1, B1)); \
D0 = _mm_unpackhi_epi64(D0, _mm_unpacklo_epi64(D1, D1)); \
D1 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t1, t1)); \
} while ((void)0, 0)
#endif
#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
\
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
} while ((void)0, 0)
#else /* __AVX2__ */
#include <immintrin.h>
#define rotr32(x) _mm256_shuffle_epi32(x, _MM_SHUFFLE(2, 3, 0, 1))
#define rotr24(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
#define rotr16(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
#define rotr63(x) _mm256_xor_si256(_mm256_srli_epi64((x), 63), _mm256_add_epi64((x), (x)))
#define G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
__m256i ml = _mm256_mul_epu32(A0, B0); \
ml = _mm256_add_epi64(ml, ml); \
A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
D0 = _mm256_xor_si256(D0, A0); \
D0 = rotr32(D0); \
\
ml = _mm256_mul_epu32(C0, D0); \
ml = _mm256_add_epi64(ml, ml); \
C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
\
B0 = _mm256_xor_si256(B0, C0); \
B0 = rotr24(B0); \
\
ml = _mm256_mul_epu32(A1, B1); \
ml = _mm256_add_epi64(ml, ml); \
A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
D1 = _mm256_xor_si256(D1, A1); \
D1 = rotr32(D1); \
\
ml = _mm256_mul_epu32(C1, D1); \
ml = _mm256_add_epi64(ml, ml); \
C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
\
B1 = _mm256_xor_si256(B1, C1); \
B1 = rotr24(B1); \
} while((void)0, 0);
#define G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
__m256i ml = _mm256_mul_epu32(A0, B0); \
ml = _mm256_add_epi64(ml, ml); \
A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
D0 = _mm256_xor_si256(D0, A0); \
D0 = rotr16(D0); \
\
ml = _mm256_mul_epu32(C0, D0); \
ml = _mm256_add_epi64(ml, ml); \
C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
B0 = _mm256_xor_si256(B0, C0); \
B0 = rotr63(B0); \
\
ml = _mm256_mul_epu32(A1, B1); \
ml = _mm256_add_epi64(ml, ml); \
A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
D1 = _mm256_xor_si256(D1, A1); \
D1 = rotr16(D1); \
\
ml = _mm256_mul_epu32(C1, D1); \
ml = _mm256_add_epi64(ml, ml); \
C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
B1 = _mm256_xor_si256(B1, C1); \
B1 = rotr63(B1); \
} while((void)0, 0);
#define DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
\
B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
} while((void)0, 0);
#define DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
__m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
__m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
B1 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
B0 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
\
tmp1 = C0; \
C0 = C1; \
C1 = tmp1; \
\
tmp1 = _mm256_blend_epi32(D0, D1, 0xCC); \
tmp2 = _mm256_blend_epi32(D0, D1, 0x33); \
D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
} while(0);
#define UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
\
B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
} while((void)0, 0);
#define UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
__m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
__m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
B0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
B1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
\
tmp1 = C0; \
C0 = C1; \
C1 = tmp1; \
\
tmp1 = _mm256_blend_epi32(D0, D1, 0x33); \
tmp2 = _mm256_blend_epi32(D0, D1, 0xCC); \
D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
} while((void)0, 0);
#define BLAKE2_ROUND_1(A0, A1, B0, B1, C0, C1, D0, D1) \
do{ \
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
\
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
} while((void)0, 0);
#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
do{ \
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
} while((void)0, 0);
#endif /* __AVX2__ */
#else /* __AVX512F__ */
#include <immintrin.h>
#define ror64(x, n) _mm512_ror_epi64((x), (n))
static __m512i muladd(__m512i x, __m512i y)
{
__m512i z = _mm512_mul_epu32(x, y);
return _mm512_add_epi64(_mm512_add_epi64(x, y), _mm512_add_epi64(z, z));
}
#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = muladd(A0, B0); \
A1 = muladd(A1, B1); \
\
D0 = _mm512_xor_si512(D0, A0); \
D1 = _mm512_xor_si512(D1, A1); \
\
D0 = ror64(D0, 32); \
D1 = ror64(D1, 32); \
\
C0 = muladd(C0, D0); \
C1 = muladd(C1, D1); \
\
B0 = _mm512_xor_si512(B0, C0); \
B1 = _mm512_xor_si512(B1, C1); \
\
B0 = ror64(B0, 24); \
B1 = ror64(B1, 24); \
} while ((void)0, 0)
#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = muladd(A0, B0); \
A1 = muladd(A1, B1); \
\
D0 = _mm512_xor_si512(D0, A0); \
D1 = _mm512_xor_si512(D1, A1); \
\
D0 = ror64(D0, 16); \
D1 = ror64(D1, 16); \
\
C0 = muladd(C0, D0); \
C1 = muladd(C1, D1); \
\
B0 = _mm512_xor_si512(B0, C0); \
B1 = _mm512_xor_si512(B1, C1); \
\
B0 = ror64(B0, 63); \
B1 = ror64(B1, 63); \
} while ((void)0, 0)
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
\
C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
\
D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
} while ((void)0, 0)
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
\
C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
\
D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
} while ((void)0, 0)
#define BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
\
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
} while ((void)0, 0)
#define SWAP_HALVES(A0, A1) \
do { \
__m512i t0, t1; \
t0 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(1, 0, 1, 0)); \
t1 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(3, 2, 3, 2)); \
A0 = t0; \
A1 = t1; \
} while((void)0, 0)
#define SWAP_QUARTERS(A0, A1) \
do { \
SWAP_HALVES(A0, A1); \
A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
} while((void)0, 0)
#define UNSWAP_QUARTERS(A0, A1) \
do { \
A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
SWAP_HALVES(A0, A1); \
} while((void)0, 0)
#define BLAKE2_ROUND_1(A0, C0, B0, D0, A1, C1, B1, D1) \
do { \
SWAP_HALVES(A0, B0); \
SWAP_HALVES(C0, D0); \
SWAP_HALVES(A1, B1); \
SWAP_HALVES(C1, D1); \
BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
SWAP_HALVES(A0, B0); \
SWAP_HALVES(C0, D0); \
SWAP_HALVES(A1, B1); \
SWAP_HALVES(C1, D1); \
} while ((void)0, 0)
#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
SWAP_QUARTERS(A0, A1); \
SWAP_QUARTERS(B0, B1); \
SWAP_QUARTERS(C0, C1); \
SWAP_QUARTERS(D0, D1); \
BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
UNSWAP_QUARTERS(A0, A1); \
UNSWAP_QUARTERS(B0, B1); \
UNSWAP_QUARTERS(C0, C1); \
UNSWAP_QUARTERS(D0, D1); \
} while ((void)0, 0)
#endif /* __AVX512F__ */
#endif /* BLAKE_ROUND_MKA_OPT_H */

View file

@ -1,3 +1,20 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef BLAKE_ROUND_MKA_H #ifndef BLAKE_ROUND_MKA_H
#define BLAKE_ROUND_MKA_H #define BLAKE_ROUND_MKA_H

23
stratum/algos/blake2b.c Normal file
View file

@ -0,0 +1,23 @@
/**
* Blake2-B Implementation
* tpruvot@github 2016-2018
*/
#include <string.h>
#include <stdint.h>
#include <sha3/blake2b.h>
#include <sha3/sph_types.h>
void blake2b_hash(const char* input, char* output, uint32_t len)
{
uint32_t ALIGN(64) hash[8];
blake2b_ctx ctx;
blake2b_init(&ctx, 32, NULL, 0);
blake2b_update(&ctx, input, len);
blake2b_final(&ctx, hash);
memcpy(output, hash, 32);
}

16
stratum/algos/blake2b.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef BLAKE2B_H
#define BLAKE2B_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void blake2b_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

157
stratum/algos/exosis.c Normal file
View file

@ -0,0 +1,157 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HASH_FUNC_BASE_TIMESTAMP 1538556426 // Exosis: Genesis Timestamp
#define HASH_FUNC_COUNT 8
#define HASH_FUNC_COUNT_PERMUTATIONS 40320
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_groestl.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_keccak.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_cubehash.h>
#define _ALIGN(x) __attribute__ ((aligned(x)))
// helpers
inline void swap(int *a, int *b) {
int c = *a;
*a = *b;
*b = c;
}
static void reverse(int *pbegin, int *pend) {
while ( (pbegin != pend) && (pbegin != --pend) )
swap(pbegin++, pend);
}
static void next_permutation(int *pbegin, int *pend) {
if (pbegin == pend)
return;
int *i = pbegin;
++i;
if (i == pend)
return;
i = pend;
--i;
while (1) {
int *j = i;
--i;
if (*i < *j) {
int *k = pend;
while (!(*i < *--k))
/* pass */;
swap(i, k);
reverse(j, pend);
return; // true
}
if (i == pbegin) {
reverse(pbegin, pend);
return; // false
}
}
}
// helpers
void exosis_hash(const char* input, char* output, uint32_t len)
{
uint32_t _ALIGN(64) hash[16 * HASH_FUNC_COUNT];
uint32_t *hashA, *hashB;
uint32_t dataLen = 64;
uint32_t *work_data = (uint32_t *)input;
const uint32_t timestamp = work_data[17];
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_skein512_context ctx_skein;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
// We want to permute algorithms. To get started we
// initialize an array with a sorted sequence of unique
// integers where every integer represents its own algorithm.
uint32_t permutation[HASH_FUNC_COUNT];
for (uint32_t i = 0; i < HASH_FUNC_COUNT; i++) {
permutation[i]=i;
}
// Compute the next permuation
uint32_t steps = (timestamp - HASH_FUNC_BASE_TIMESTAMP) % HASH_FUNC_COUNT_PERMUTATIONS;
for (uint32_t i = 0; i < steps; i++) {
next_permutation(permutation, permutation + HASH_FUNC_COUNT);
}
for (uint32_t i = 0; i < HASH_FUNC_COUNT; i++) {
if (i == 0) {
dataLen = len;
hashA = work_data;
} else {
dataLen = 64;
hashA = &hash[16 * (i - 1)];
}
hashB = &hash[16 * i];
switch(permutation[i]) {
case 0:
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, hashA, dataLen);
sph_blake512_close(&ctx_blake, hashB);
break;
case 1:
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hashA, dataLen);
sph_bmw512_close(&ctx_bmw, hashB);
break;
case 2:
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, hashA, dataLen);
sph_groestl512_close(&ctx_groestl, hashB);
break;
case 3:
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, hashA, dataLen);
sph_skein512_close(&ctx_skein, hashB);
break;
case 4:
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, hashA, dataLen);
sph_jh512_close(&ctx_jh, hashB);
break;
case 5:
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, hashA, dataLen);
sph_keccak512_close(&ctx_keccak, hashB);
break;
case 6:
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, hashA, dataLen);
sph_luffa512_close(&ctx_luffa, hashB);
break;
case 7:
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, hashA, dataLen);
sph_cubehash512_close(&ctx_cubehash, hashB);
break;
default:
break;
}
}
memcpy(output, &hash[16 * (HASH_FUNC_COUNT - 1)], 32);
}

16
stratum/algos/exosis.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef EXOSIS_H
#define EXOSIS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void exosis_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

180
stratum/algos/hex.c Normal file
View file

@ -0,0 +1,180 @@
// Copyright (c) 2018 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <stdint.h>
#include <stdio.h>
#include <memory.h>
#include "hex.h"
#include "../sha3/sph_blake.h"
#include "../sha3/sph_bmw.h"
#include "../sha3/sph_groestl.h"
#include "../sha3/sph_skein.h"
#include "../sha3/sph_jh.h"
#include "../sha3/sph_keccak.h"
#include "../sha3/sph_luffa.h"
#include "../sha3/sph_cubehash.h"
#include "../sha3/sph_shavite.h"
#include "../sha3/sph_simd.h"
#include "../sha3/sph_echo.h"
#include "../sha3/sph_hamsi.h"
#include "../sha3/sph_fugue.h"
#include "../sha3/sph_shabal.h"
#include "../sha3/sph_whirlpool.h"
#include "../sha3/sph_sha2.h"
enum Algo {
BLAKE = 0,
BMW,
GROESTL,
JH,
KECCAK,
SKEIN,
LUFFA,
CUBEHASH,
SHAVITE,
SIMD,
ECHO,
HAMSI,
FUGUE,
SHABAL,
WHIRLPOOL,
SHA512,
HASH_FUNC_COUNT
};
static const int TOTAL_CYCLES = 16;
static uint8_t get_first_algo(const uint32_t* prevblock) {
uint8_t* data = (uint8_t*)prevblock;
return data[7] >> 4;
}
void hex_hash(const char* input, char* output, uint32_t len)
{
unsigned char hash[128];
uint8_t curr_algo;
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_skein512_context ctx_skein;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
sph_shavite512_context ctx_shavite;
sph_simd512_context ctx_simd;
sph_echo512_context ctx_echo;
sph_hamsi512_context ctx_hamsi;
sph_fugue512_context ctx_fugue;
sph_shabal512_context ctx_shabal;
sph_whirlpool_context ctx_whirlpool;
sph_sha512_context ctx_sha512;
const void *in = input;
int size = len;
uint32_t *in32 = (uint32_t*) input;
// initial algo = first digit of prev block hashorder (cheers, x16r)
curr_algo = get_first_algo(&in32[1]);
for (int i = 0; i < TOTAL_CYCLES; i++)
{
// Only 4 test algos yet
switch (curr_algo) {
case BLAKE:
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, in, size);
sph_blake512_close(&ctx_blake, hash);
break;
case BMW:
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, in, size);
sph_bmw512_close(&ctx_bmw, hash);
break;
case GROESTL:
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, in, size);
sph_groestl512_close(&ctx_groestl, hash);
break;
case JH:
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, in, size);
sph_jh512_close(&ctx_jh, hash);
break;
case KECCAK:
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, in, size);
sph_keccak512_close(&ctx_keccak, hash);
break;
case SKEIN:
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, in, size);
sph_skein512_close(&ctx_skein, hash);
break;
case LUFFA:
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, in, size);
sph_luffa512_close(&ctx_luffa, hash);
break;
case CUBEHASH:
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, in, size);
sph_cubehash512_close(&ctx_cubehash, hash);
break;
case SHAVITE:
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, in, size);
sph_shavite512_close(&ctx_shavite, hash);
break;
case SIMD:
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, in, size);
sph_simd512_close(&ctx_simd, hash);
break;
case ECHO:
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, in, size);
sph_echo512_close(&ctx_echo, hash);
break;
case HAMSI:
sph_hamsi512_init(&ctx_hamsi);
sph_hamsi512(&ctx_hamsi, in, size);
sph_hamsi512_close(&ctx_hamsi, hash);
break;
case FUGUE:
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, in, size);
sph_fugue512_close(&ctx_fugue, hash);
break;
case SHABAL:
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, in, size);
sph_shabal512_close(&ctx_shabal, hash);
break;
case WHIRLPOOL:
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool(&ctx_whirlpool, in, size);
sph_whirlpool_close(&ctx_whirlpool, hash);
break;
case SHA512:
sph_sha512_init(&ctx_sha512);
sph_sha512(&ctx_sha512,(const void*) in, size);
sph_sha512_close(&ctx_sha512,(void*) hash);
break;
}
// next algos = first digit on prev hash
curr_algo = (uint8_t)hash[0] % HASH_FUNC_COUNT;
in = (void*)hash;
size = 64;
}
memcpy(output, hash, 32);
}

20
stratum/algos/hex.h Normal file
View file

@ -0,0 +1,20 @@
// Copyright (c) 2018 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef HEXHASH_H
#define HEXHASH_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void hex_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif // HEXHASH_H

36
stratum/algos/lbk3.c Normal file
View file

@ -0,0 +1,36 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_keccak.h>
#define _ALIGN(x) __attribute__ ((aligned(x)))
extern uint64_t lbk3_height;
void lbk3_hash(const char* input, char* output, uint32_t len)
{
sph_bmw256_context ctx_bmw;
sph_blake256_context ctx_blake;
sph_keccak256_context ctx_keccak;
uint8_t _ALIGN(128) hash[96];
memset(&hash[32], 0, 64);
sph_bmw256_init(&ctx_bmw);
sph_bmw256 (&ctx_bmw, input, 80);
sph_bmw256_close(&ctx_bmw, &hash[0]);
sph_blake256_init(&ctx_blake);
sph_blake256 (&ctx_blake, &hash[0], 64);
sph_blake256_close(&ctx_blake, &hash[32]);
sph_keccak256_init(&ctx_keccak);
sph_keccak256 (&ctx_keccak, &hash[32], 64);
sph_keccak256_close(&ctx_keccak, &hash[64]);
memcpy(output, &hash[64], 32);
}

16
stratum/algos/lbk3.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef LBK3_H
#define LBK3_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void lbk3_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

68
stratum/algos/lyra2v3.c Normal file
View file

@ -0,0 +1,68 @@
/*-
* Copyright(or left) 2019 YiiMP
*
* 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.
*/
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "../sha3/sph_blake.h"
#include "../sha3/sph_cubehash.h"
#include "../sha3/sph_bmw.h"
#include "Lyra2.h"
void lyra2v3_hash(const char* input, char* output, uint32_t len)
{
uint32_t hash[8], hashB[8];
sph_blake256_context ctx_blake;
sph_cubehash256_context ctx_cubehash;
sph_bmw256_context ctx_bmw;
sph_blake256_set_rounds(14);
sph_blake256_init(&ctx_blake);
sph_blake256(&ctx_blake, input, len); /* 80 */
sph_blake256_close(&ctx_blake, hash);
LYRA2_3(hashB, 32, hash, 32, hash, 32, 1, 4, 4);
sph_cubehash256_init(&ctx_cubehash);
sph_cubehash256(&ctx_cubehash, hashB, 32);
sph_cubehash256_close(&ctx_cubehash, hash);
LYRA2_3(hashB, 32, hash, 32, hash, 32, 1, 4, 4);
sph_bmw256_init(&ctx_bmw);
sph_bmw256(&ctx_bmw, hashB, 32);
sph_bmw256_close(&ctx_bmw, hash);
memcpy(output, hash, 32);
}

16
stratum/algos/lyra2v3.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef LYRA2V3_H
#define LYRA2V3_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void lyra2v3_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -3,7 +3,7 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include "Lyra2z.h" #include "Lyra2-z.h"
#include <sha3/sph_blake.h> #include <sha3/sph_blake.h>

28
stratum/algos/lyra2zz.c Normal file
View file

@ -0,0 +1,28 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "Lyra2-zz.h"
#include <sha3/sph_blake.h>
#define _ALIGN(x) __attribute__ ((aligned(x)))
extern uint64_t lyra2z_height;
void lyra2zz_hash(const char* input, char* output, uint32_t len)
{
uint32_t _ALIGN(64) hashB[8], hash[8];
sph_blake256_context ctx_blake;
sph_blake256_set_rounds(14);
sph_blake256_init(&ctx_blake);
sph_blake256(&ctx_blake, input, 112);
sph_blake256_close(&ctx_blake, hashB);
LYRA2ZZ(hash, 32, hashB, 32, hashB, 32, 8, 8, 8);
memcpy(output, hash, 32);
}

16
stratum/algos/lyra2zz.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef LYRA2ZZ_H
#define LYRA2ZZ_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void lyra2zz_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -8,18 +8,19 @@ CXXFLAGS = -O2 -I.. -march=native
CFLAGS= $(CXXFLAGS) -std=gnu99 CFLAGS= $(CXXFLAGS) -std=gnu99
LDFLAGS=-O2 -lgmp LDFLAGS=-O2 -lgmp
SOURCES=lyra2re.c lyra2v2.c Lyra2.c lyra2z.c Lyra2z.c Sponge.c \ SOURCES=lyra2re.c lyra2v2.c lyra2v3.c Lyra2.c lyra2z.c Lyra2-z.c lyra2zz.c Lyra2-zz.c Sponge.c allium.c \
blake.c scrypt.c c11.c x11.c x13.c sha256.c sha256t.c jha.c keccak.c deep.c tribus.c \ c11.c x11.c x12.c x13.c hsr14.c sm3.c x14.c x15.c x17.c \
hsr14.c sm3.c \ x22i.c SWIFFTX/SWIFFTX.c \
x14.c x15.c x17.c nist5.c fresh.c quark.c neoscrypt.c scryptn.c qubit.c skein.c groestl.c \ blake.c blakecoin.c blake2b.c blake2s.c jha.c keccak.c lbry.c tribus.c exosis.c \
bitcore.c timetravel.c xevan.c bastion.c hmq17.c \ deep.c fresh.c groestl.c neoscrypt.c nist5.c quark.c qubit.c skein.c skein2.c \
skein2.c zr5.c bmw.c luffa.c pentablake.c whirlpool.c whirlpoolx.c blakecoin.c \ bitcore.c timetravel.c x11evo.c x16r.c x16rv2.c x16s.c xevan.c bastion.c hmq17.c sonoa.c \
blake2.c \ bmw.c luffa.c pentablake.c vitalium.c whirlpool.c whirlpoolx.c zr5.c \
yescrypt.c yescrypt-opt.c sha256_Y.c lbry.c \ scrypt.c scryptn.c sha256.c sha256t.c sha256q.c \
m7m.c magimath.cpp velvet.c \ yescrypt.c yescrypt-opt.c sha256_Y.c \
argon2a.c ar2/blake2b.c ar2/argon2.c ar2/ref.c ar2/cores.c ar2/ar2-scrypt-jane.c \ a5a.c a5amath.c m7m.c magimath.cpp velvet.c \
hive.c pomelo.c \ argon2a.c blake2/blake2b.c ar2/argon2.c ar2/core.c ar2/encoding.c ar2/opt.c ar2/thread.c ar2/ar2-scrypt-jane.c \
phi.c polytimos.c skunk.c sib.c veltor.c gost.c x11evo.c hive.c pomelo.c hex.c argon2d-dyn.c \
phi.c phi2.c polytimos.c rainforest.c skunk.c sib.c veltor.c gost.c aergo.c lbk3.c
OBJECTS=$(SOURCES:%.c=%.o) $(SOURCES:%.cpp=%.o) OBJECTS=$(SOURCES:%.c=%.o) $(SOURCES:%.cpp=%.o)
OUTPUT=libalgos.a OUTPUT=libalgos.a
@ -41,4 +42,5 @@ $(OUTPUT): $(OBJECTS)
clean: clean:
rm -f *.o rm -f *.o
rm -f ar2/*.o rm -f ar2/*.o
rm -f blake2/*.o
rm -f SWIFFTX/*.o

62
stratum/algos/phi2.c Normal file
View file

@ -0,0 +1,62 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_echo.h>
#include <sha3/sph_skein.h>
#include "gost.h"
#include "Lyra2.h"
#include "common.h"
void phi2_hash(const char* input, char* output, uint32_t len)
{
unsigned char _ALIGN(128) hash[64];
unsigned char _ALIGN(128) hashA[64];
unsigned char _ALIGN(128) hashB[64];
sph_cubehash512_context ctx_cubehash;
sph_jh512_context ctx_jh;
sph_gost512_context ctx_gost;
sph_echo512_context ctx_echo;
sph_skein512_context ctx_skein;
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, input, len);
sph_cubehash512_close(&ctx_cubehash, (void*)hashB);
LYRA2(&hashA[ 0], 32, &hashB[ 0], 32, &hashB[ 0], 32, 1, 8, 8);
LYRA2(&hashA[32], 32, &hashB[32], 32, &hashB[32], 32, 1, 8, 8);
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, (const void*)hashA, 64);
sph_jh512_close(&ctx_jh, (void*)hash);
if (hash[0] & 1) {
sph_gost512_init(&ctx_gost);
sph_gost512(&ctx_gost, (const void*)hash, 64);
sph_gost512_close(&ctx_gost, (void*)hash);
} else {
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, (const void*)hash, 64);
sph_echo512_close(&ctx_echo, (void*)hash);
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, (const void*)hash, 64);
sph_echo512_close(&ctx_echo, (void*)hash);
}
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, (const void*)hash, 64);
sph_skein512_close(&ctx_skein, (void*)hash);
for (int i=0; i<32; i++)
hash[i] ^= hash[i+32];
memcpy(output, hash, 32);
}

16
stratum/algos/phi2.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef PHI2_H
#define PHI2_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void phi2_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

802
stratum/algos/rainforest.c Normal file
View file

@ -0,0 +1,802 @@
// RainForest hash algorithm
// Author: Bill Schneider
// Date: Feb 13th, 2018
//
// RainForest uses native integer operations which are extremely fast on
// modern 64-bit processors, significantly slower on 32-bit processors such
// as GPUs, and extremely slow if at all implementable on FPGAs and ASICs.
// It makes an intensive use of the L1 cache to maintain a heavy intermediary
// state favoring modern CPUs compared to GPUs (small L1 cache shared by many
// shaders) or FPGAs (very hard to implement the required low-latency cache)
// when scanning ranges for nonces. The purpose is to create a fair balance
// between all mining equipments, from mobile phones to extreme performance
// GPUs and to rule out farming factories relying on ASICs and FPGAs. The
// CRC32 instruction is used a lot as it is extremely fast on low-power ARM
// chips and allows such devices to rival high-end PCs mining performance.
//
// Tests on various devices have shown the following performance :
// +--------------------------------------------------------------------------+
// | CPU/GPU Clock Threads Full hash Nonce scan Watts Cost |
// | (MHz) (80 bytes) (4 bytes) total |
// | Core i7-6700k 4000 8 390 kH/s 1642 kH/s 200 ~$350+PC |
// | Radeon RX560 1300 1024 1100 kH/s 1650 kH/s 300 ~$180+PC |
// | RK3368 (8*A53) 1416 8 534 kH/s 1582 kH/s 6 $60 (Geekbox) |
// +--------------------------------------------------------------------------+
//
// Build instructions on Ubuntu 16.04 :
// - on x86: use gcc -march=native or -maes to enable AES-NI
// - on ARMv8: use gcc -march=native or -march=armv8-a+crypto+crc to enable
// CRC32 and AES extensions.
//
// Note: always use the same options to build all files!
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
//#define DEBUG_ALGO
/* Rijndael's substitution box for sub_bytes step */
static uint8_t SBOX[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
/*--- The parts below are not used when crypto extensions are available ---*/
/* Use -march=armv8-a+crypto on ARMv8 to use crypto extensions */
/* Use -maes on x86_64 to use AES-NI */
#if defined(RF_NOASM) || (!defined(__aarch64__) || !defined(__ARM_FEATURE_CRYPTO)) && (!defined(__x86_64__) || !defined(__AES__))
/* shifts to do for shift_rows step */
static uint8_t shifts[16] = {
0, 5, 10, 15,
4, 9, 14, 3,
8, 13, 2, 7,
12, 1, 6, 11
};
/* add the round key to the state with simple XOR operation */
static void add_round_key(uint8_t * state, uint8_t * rkey) {
uint8_t i;
for (i = 0; i < 16; i++)
state[i] ^= rkey[i];
}
/* substitute all bytes using Rijndael's substitution box */
static void sub_bytes(uint8_t * state) {
uint8_t i;
for (i = 0; i < 16; i++)
state[i] = SBOX[state[i]];
}
/* imagine the state not as 1-dimensional, but a 4x4 grid;
* this step shifts the rows of this grid around */
static void shift_rows(uint8_t * state) {
uint8_t temp[16];
uint8_t i;
for (i = 0; i < 16; i++) {
temp[i] = state[shifts[i]];
}
for (i = 0; i < 16; i++) {
state[i] = temp[i];
}
}
/* mix columns */
static void mix_columns(uint8_t * state) {
uint8_t a[4];
uint8_t b[4];
uint8_t h, i, k;
for (k = 0; k < 4; k++) {
for (i = 0; i < 4; i++) {
a[i] = state[i + 4 * k];
h = state[i + 4 * k] & 0x80; /* hi bit */
b[i] = state[i + 4 * k] << 1;
if (h == 0x80) {
b[i] ^= 0x1b; /* Rijndael's Galois field */
}
}
state[4 * k] = b[0] ^ a[3] ^ a[2] ^ b[1] ^ a[1];
state[1 + 4 * k] = b[1] ^ a[0] ^ a[3] ^ b[2] ^ a[2];
state[2 + 4 * k] = b[2] ^ a[1] ^ a[0] ^ b[3] ^ a[3];
state[3 + 4 * k] = b[3] ^ a[2] ^ a[1] ^ b[0] ^ a[0];
}
}
#endif // (!defined(__aarch64__) || !defined(__ARM_FEATURE_CRYPTO)) && (!defined(__x86_64__) || !defined(__AES__))
/* key schedule stuff */
/* simple function to rotate 4 byte array */
static inline uint32_t rotate32(uint32_t in) {
#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
in = (in >> 8) | (in << 24);
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
in = (in << 8) | (in >> 24);
#else
uint8_t *b = (uint8_t *)&in, temp = b[0];
b[0] = b[1]; b[1] = b[2]; b[2] = b[3]; b[3] = temp;
#endif
return in;
}
/* key schedule core operation */
static inline uint32_t sbox(uint32_t in, uint8_t n) {
in = (SBOX[in & 255]) | (SBOX[(in >> 8) & 255] << 8) | (SBOX[(in >> 16) & 255] << 16) | (SBOX[(in >> 24) & 255] << 24);
#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
in ^= n;
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
in ^= n << 24;
#else
*(uint8_t *)&in ^= n;
#endif
return in;
}
// this version is optimized for exactly two rounds.
// _state_ must be 16-byte aligned.
static void aes2r_encrypt(uint8_t * state, uint8_t * key) {
uint32_t key_schedule[12] __attribute__((aligned(16)));
uint32_t t;
/* initialize key schedule; its first 16 bytes are the key */
key_schedule[0] = ((uint32_t *)key)[0];
key_schedule[1] = ((uint32_t *)key)[1];
key_schedule[2] = ((uint32_t *)key)[2];
key_schedule[3] = ((uint32_t *)key)[3];
t = key_schedule[3];
t = rotate32(t);
t = sbox(t, 1);
t = key_schedule[4] = key_schedule[0] ^ t;
t = key_schedule[5] = key_schedule[1] ^ t;
t = key_schedule[6] = key_schedule[2] ^ t;
t = key_schedule[7] = key_schedule[3] ^ t;
t = rotate32(t);
t = sbox(t, 2);
t = key_schedule[8] = key_schedule[4] ^ t;
t = key_schedule[9] = key_schedule[5] ^ t;
t = key_schedule[10] = key_schedule[6] ^ t;
t = key_schedule[11] = key_schedule[7] ^ t;
// Use -march=armv8-a+crypto+crc to get this one
#if defined(__aarch64__) && defined(__ARM_FEATURE_CRYPTO)
asm volatile(
"ld1 {v0.16b},[%0] \n"
"ld1 {v1.16b,v2.16b,v3.16b},[%1] \n"
"aese v0.16b,v1.16b \n" // round1: add_round_key,sub_bytes,shift_rows
"aesmc v0.16b,v0.16b \n" // round1: mix_columns
"aese v0.16b,v2.16b \n" // round2: add_round_key,sub_bytes,shift_rows
"eor v0.16b,v0.16b,v3.16b \n" // finish: add_round_key
"st1 {v0.16b},[%0] \n"
: /* only output is in *state */
: "r"(state), "r"(key_schedule)
: "v0", "v1", "v2", "v3", "cc", "memory");
// Use -maes to get this one
#elif defined(__x86_64__) && defined(__AES__)
asm volatile(
"movups (%0), %%xmm0 \n"
"movups (%1), %%xmm1 \n"
"pxor %%xmm1,%%xmm0 \n" // add_round_key(state, key_schedule)
"movups 16(%1),%%xmm2 \n"
"movups 32(%1),%%xmm1 \n"
"aesenc %%xmm2,%%xmm0 \n" // first round
"aesenclast %%xmm1,%%xmm0 \n" // final round
"movups %%xmm0, (%0) \n"
: /* only output is in *state */
: "r"(state), "r" (key_schedule)
: "xmm0", "xmm1", "xmm2", "cc", "memory");
#else
/* first round of the algorithm */
add_round_key(state, (void*)&key_schedule[0]);
sub_bytes(state);
shift_rows(state);
mix_columns(state);
add_round_key(state, (void*)&key_schedule[4]);
/* final round of the algorithm */
sub_bytes(state);
shift_rows(state);
add_round_key(state, (void*)&key_schedule[8]);
#endif
}
// this seems necessary only for gcc, otherwise hash is bogus
typedef __attribute__((may_alias)) uint8_t rf_u8;
typedef __attribute__((may_alias)) uint16_t rf_u16;
typedef __attribute__((may_alias)) uint32_t rf_u32;
typedef __attribute__((may_alias)) uint64_t rf_u64;
// 2048 entries for the rambox => 16kB
#define RAMBOX_SIZE 2048
#define RAMBOX_LOOPS 4
typedef union {
rf_u8 b[32];
rf_u16 w[16];
rf_u32 d[8];
rf_u64 q[4];
} hash256_t;
typedef struct __attribute__((aligned(16))) rf_ctx {
uint64_t rambox[RAMBOX_SIZE];
hash256_t hash;
uint32_t crc;
uint32_t word; // LE pending message
uint32_t len; // total message length
} rf256_ctx_t;
// these archs are fine with unaligned reads
#if defined(__x86_64__)||defined(__aarch64__)
#define RF_UNALIGNED_LE64
#define RF_UNALIGNED_LE32
#elif defined(__i386__)||defined(__ARM_ARCH_7A__)
#define RF_UNALIGNED_LE32
#endif
#define RF256_INIT_CRC 20180213
// the table is used as an 8 bit-aligned array of uint64_t for the first word,
// and as a 16 bit-aligned array of uint64_t for the second word. It is filled
// with the sha256 of "RainForestProCpuAntiAsic", iterated over and over until
// the table is filled. The highest offset being ((uint16_t *)table)[255] we
// need to add 6 extra bytes at the end to read an uint64_t. Maybe calculated
// on a UNIX system with this loop :
//
// ref="RainForestProCpuAntiAsic"
// for ((i=0;i<18;i++)); do
// set $(echo -n $ref|sha256sum)
// echo $1|sed 's/\(..\)/0x\1,/g'
// ref=$(printf $(echo $1|sed 's/\(..\)/\\x\1/g'))
// done
const uint8_t rf_table[256*2+6] = {
0x8e,0xc1,0xa8,0x04,0x38,0x78,0x7c,0x54,0x29,0x23,0x1b,0x78,0x9f,0xf9,0x27,0x54,
0x11,0x78,0x95,0xb6,0xaf,0x78,0x45,0x16,0x2b,0x9e,0x91,0xe8,0x97,0x25,0xf8,0x63,
0x82,0x56,0xcf,0x48,0x6f,0x82,0x14,0x0d,0x61,0xbe,0x47,0xd1,0x37,0xee,0x30,0xa9,
0x28,0x1e,0x4b,0xbf,0x07,0xcd,0x41,0xdf,0x23,0x21,0x12,0xb8,0x81,0x99,0x1d,0xe6,
0x68,0xcf,0xfa,0x2d,0x8e,0xb9,0x88,0xa7,0x15,0xce,0x9e,0x2f,0xeb,0x1b,0x0f,0x67,
0x20,0x68,0x6c,0xa9,0x5d,0xc1,0x7c,0x76,0xdf,0xbd,0x98,0x61,0xb4,0x14,0x65,0x40,
0x1e,0x72,0x51,0x74,0x93,0xd3,0xad,0xbe,0x46,0x0a,0x25,0xfb,0x6a,0x5e,0x1e,0x8a,
0x5a,0x03,0x3c,0xab,0x12,0xc2,0xd4,0x07,0x91,0xab,0xc9,0xdf,0x92,0x2c,0x85,0x6a,
0xa6,0x25,0x1e,0x66,0x50,0x26,0x4e,0xa8,0xbd,0xda,0x88,0x1b,0x95,0xd4,0x00,0xeb,
0x0d,0x1c,0x9b,0x3c,0x86,0xc7,0xb2,0xdf,0xb4,0x5a,0x36,0x15,0x8e,0x04,0xd2,0x54,
0x79,0xd2,0x3e,0x3d,0x99,0x50,0xa6,0x12,0x4c,0x32,0xc8,0x51,0x14,0x4d,0x4b,0x0e,
0xbb,0x17,0x80,0x8f,0xa4,0xc4,0x99,0x72,0xd7,0x14,0x4b,0xef,0xed,0x14,0xe9,0x17,
0xfa,0x9b,0x5d,0x37,0xd6,0x2f,0xef,0x02,0xd6,0x71,0x0a,0xbd,0xc5,0x40,0x11,0x90,
0x90,0x4e,0xb4,0x4c,0x72,0x51,0x7a,0xd8,0xba,0x30,0x4d,0x8c,0xe2,0x11,0xbb,0x6d,
0x4b,0xbc,0x6f,0x14,0x0c,0x9f,0xfa,0x5e,0x66,0x40,0x45,0xcb,0x7d,0x1b,0x3a,0xc5,
0x5e,0x9c,0x1e,0xcc,0xbd,0x16,0x3b,0xcf,0xfb,0x2a,0xd2,0x08,0x2a,0xf8,0x3d,0x46,
0x93,0x90,0xb3,0x66,0x81,0x34,0x7f,0x6d,0x9b,0x8c,0x99,0x03,0xc5,0x27,0xa3,0xd9,
0xce,0x90,0x88,0x0f,0x55,0xc3,0xa1,0x60,0x53,0xc8,0x0d,0x25,0xae,0x61,0xd9,0x72,
0x48,0x1d,0x6c,0x61,0xd2,0x87,0xdd,0x3d,0x23,0xf5,0xde,0x93,0x39,0x4c,0x43,0x9a,
0xf9,0x37,0xf2,0x61,0xd7,0xf8,0xea,0x65,0xf0,0xf1,0xde,0x3f,0x05,0x57,0x83,0x81,
0xde,0x02,0x62,0x49,0xd4,0x32,0x7e,0x4a,0xd4,0x9f,0x40,0x7e,0xb9,0x91,0xb1,0x35,
0xf7,0x62,0x3f,0x65,0x9e,0x4d,0x2b,0x10,0xde,0xd4,0x77,0x64,0x0f,0x84,0xad,0x92,
0xe7,0xa3,0x8a,0x10,0xc1,0x14,0xeb,0x57,0xc4,0xad,0x8e,0xc2,0xc7,0x32,0xa3,0x7e,
0x50,0x1f,0x7c,0xbb,0x2e,0x5f,0xf5,0x18,0x22,0xea,0xec,0x9d,0xa4,0x77,0xcd,0x85,
0x04,0x2f,0x20,0x61,0x72,0xa7,0x0c,0x92,0x06,0x4d,0x01,0x70,0x9b,0x35,0xa1,0x27,
0x32,0x6e,0xb9,0x78,0xe0,0xaa,0x5f,0x91,0xa6,0x51,0xe3,0x63,0xf8,0x97,0x2f,0x60,
0xd9,0xfb,0x15,0xe5,0x59,0xcf,0x31,0x3c,0x61,0xc7,0xb5,0x61,0x2a,0x6b,0xdd,0xd1,
0x09,0x70,0xc0,0xcf,0x94,0x7a,0xcc,0x31,0x94,0xb1,0xa2,0xf6,0x95,0xc0,0x38,0x3d,
0xef,0x19,0x30,0x70,0xdd,0x62,0x32,0x8f,0x7c,0x30,0xb9,0x18,0xf8,0xe7,0x8f,0x0a,
0xaa,0xb6,0x00,0x86,0xf2,0xe0,0x30,0x5f,0xa2,0xe8,0x00,0x8e,0x05,0xa0,0x22,0x18,
0x9f,0x83,0xd4,0x3a,0x85,0x10,0xb9,0x51,0x8d,0x07,0xf0,0xb3,0xcd,0x9b,0x55,0xa1,
0x14,0xce,0x0f,0xb2,0xcf,0xb8,0xce,0x2d,0xe6,0xe8,0x35,0x32,0x1f,0x22,0xb5,0xec,
0xd0,0xb9,0x72,0xa8,0xb4,0x97
//,0x6e,0x0a,0x47,0xcd,0x5a,0xf0,0xdc,0xeb,0xfd,0x46,
//0xe5,0x6e,0x83,0xe6,0x1a,0xcc,0x4a,0x8b,0xa5,0x28,0x9e,0x50,0x48,0xa9,0xa2,0x6b,
};
// this is made of the last iteration of the rf_table (18th transformation)
const uint8_t rf256_iv[32] = {
0x78,0xe9,0x90,0xd3,0xb3,0xc8,0x9b,0x7b,0x0a,0xc4,0x86,0x6e,0x4e,0x38,0xb3,0x6b,
0x33,0x68,0x7c,0xed,0x73,0x35,0x4b,0x0a,0x97,0x25,0x4c,0x77,0x7a,0xaa,0x61,0x1b
};
// crc32 lookup tables
const uint32_t rf_crc32_table[256] = {
/* 0x00 */ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
/* 0x04 */ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
/* 0x08 */ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
/* 0x0c */ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
/* 0x10 */ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
/* 0x14 */ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
/* 0x18 */ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
/* 0x1c */ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
/* 0x20 */ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
/* 0x24 */ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
/* 0x28 */ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
/* 0x2c */ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
/* 0x30 */ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
/* 0x34 */ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
/* 0x38 */ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
/* 0x3c */ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
/* 0x40 */ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
/* 0x44 */ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
/* 0x48 */ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
/* 0x4c */ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
/* 0x50 */ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
/* 0x54 */ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
/* 0x58 */ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
/* 0x5c */ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
/* 0x60 */ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
/* 0x64 */ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
/* 0x68 */ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
/* 0x6c */ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
/* 0x70 */ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
/* 0x74 */ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
/* 0x78 */ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
/* 0x7c */ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
/* 0x80 */ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
/* 0x84 */ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
/* 0x88 */ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
/* 0x8c */ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
/* 0x90 */ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
/* 0x94 */ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
/* 0x98 */ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
/* 0x9c */ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
/* 0xa0 */ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
/* 0xa4 */ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
/* 0xa8 */ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
/* 0xac */ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
/* 0xb0 */ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
/* 0xb4 */ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
/* 0xb8 */ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
/* 0xbc */ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
/* 0xc0 */ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
/* 0xc4 */ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
/* 0xc8 */ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
/* 0xcc */ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
/* 0xd0 */ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
/* 0xd4 */ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
/* 0xd8 */ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
/* 0xdc */ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
/* 0xe0 */ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
/* 0xe4 */ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
/* 0xe8 */ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
/* 0xec */ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
/* 0xf0 */ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
/* 0xf4 */ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
/* 0xf8 */ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
/* 0xfc */ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
// compute the crc32 of 32-bit message _msg_ from previous crc _crc_.
// build with -mcpu=cortex-a53+crc to enable native CRC instruction on ARM
static inline uint32_t rf_crc32_32(uint32_t crc, uint32_t msg) {
#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
asm("crc32w %w0,%w0,%w1\n":"+r"(crc):"r"(msg));
#else
crc=crc^msg;
crc=rf_crc32_table[crc&0xff]^(crc>>8);
crc=rf_crc32_table[crc&0xff]^(crc>>8);
crc=rf_crc32_table[crc&0xff]^(crc>>8);
crc=rf_crc32_table[crc&0xff]^(crc>>8);
#endif
return crc;
}
//static inline uint32_t rf_crc32_24(uint32_t crc, uint32_t msg) {
//#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
// asm("crc32b %w0,%w0,%w1\n":"+r"(crc):"r"(msg));
// asm("crc32h %w0,%w0,%w1\n":"+r"(crc):"r"(msg>>8));
//#else
// crc=crc^msg;
// crc=rf_crc32_table[crc&0xff]^(crc>>8);
// crc=rf_crc32_table[crc&0xff]^(crc>>8);
// crc=rf_crc32_table[crc&0xff]^(crc>>8);
//#endif
// return crc;
//}
//
//static inline uint32_t rf_crc32_16(uint32_t crc, uint32_t msg) {
//#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
// asm("crc32h %w0,%w0,%w1\n":"+r"(crc):"r"(msg));
//#else
// crc=crc^msg;
// crc=rf_crc32_table[crc&0xff]^(crc>>8);
// crc=rf_crc32_table[crc&0xff]^(crc>>8);
//#endif
// return crc;
//}
//
//static inline uint32_t rf_crc32_8(uint32_t crc, uint32_t msg) {
//#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
// asm("crc32b %w0,%w0,%w1\n":"+r"(crc):"r"(msg));
//#else
// crc=crc^msg;
// crc=rf_crc32_table[crc&0xff]^(crc>>8);
//#endif
// return crc;
//}
// add to _msg_ its own crc32. use -mcpu=cortex-a53+crc to enable native CRC
// instruction on ARM.
static inline uint64_t rf_add64_crc32(uint64_t msg) {
uint64_t crc=0;
#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
asm("crc32x %w0,%w0,%x1\n":"+r"(crc):"r"(msg));
#else
crc^=(uint32_t)msg;
crc=rf_crc32_table[crc&0xff]^(crc>>8);
crc=rf_crc32_table[crc&0xff]^(crc>>8);
crc=rf_crc32_table[crc&0xff]^(crc>>8);
crc=rf_crc32_table[crc&0xff]^(crc>>8);
crc^=msg>>32;
crc=rf_crc32_table[crc&0xff]^(crc>>8);
crc=rf_crc32_table[crc&0xff]^(crc>>8);
crc=rf_crc32_table[crc&0xff]^(crc>>8);
crc=rf_crc32_table[crc&0xff]^(crc>>8);
#endif
return msg+crc;
}
// mix the current state with the crc and return the new crc
static inline uint32_t rf_crc32x4(rf_u32 *state, uint32_t crc) {
crc=state[0]=rf_crc32_32(crc, state[0]);
crc=state[1]=rf_crc32_32(crc, state[1]);
crc=state[2]=rf_crc32_32(crc, state[2]);
crc=state[3]=rf_crc32_32(crc, state[3]);
return crc;
}
// read 64 bit from possibly unaligned memory address _p_ in little endian mode
static inline uint64_t rf_memr64(const uint8_t *p) {
#ifdef RF_UNALIGNED_LE64
return *(uint64_t *)p;
#else
uint64_t ret;
int byte;
for (ret=byte=0; byte<8; byte++)
ret+=(uint64_t)p[byte]<<(byte*8);
return ret;
#endif
}
// return rainforest lower word entry for index
static inline uint64_t rf_wltable(uint8_t index) {
return rf_memr64(&rf_table[index]);
}
// return rainforest upper word entry for _index_
static inline uint64_t rf_whtable(uint8_t index) {
return rf_memr64(&rf_table[index*2]);
}
// rotate left vector _v_ by _bits_ bits
static inline uint64_t rf_rotl64(uint64_t v, uint8_t bits) {
#if !defined(__ARM_ARCH_8A) && !defined(__AARCH64EL__) && !defined(x86_64)
bits&=63;
#endif
return (v<<bits)|(v>>(64-bits));
}
// rotate right vector _v_ by _bits_ bits
static inline uint64_t rf_rotr64(uint64_t v, uint8_t bits) {
#if !defined(__ARM_ARCH_8A) && !defined(__AARCH64EL__) && !defined(x86_64)
bits&=63;
#endif
return (v>>bits)|(v<<(64-bits));
}
// reverse all bytes in the word _v_
static inline uint64_t rf_bswap64(uint64_t v) {
#if defined(__x86_64__)
asm("bswap %0":"+r"(v));
#elif defined(__aarch64__)
asm("rev %0,%0\n":"+r"(v));
#else
v=((v&0xff00ff00ff00ff00ULL)>>8)|((v&0x00ff00ff00ff00ffULL)<<8);
v=((v&0xffff0000ffff0000ULL)>>16)|((v&0x0000ffff0000ffffULL)<<16);
v=(v>>32)|(v<<32);
#endif
return v;
}
// lookup _old_ in _rambox_, update it and perform a substitution if a matching
// value is found.
static inline uint32_t rf_rambox(uint64_t *rambox, uint64_t old) {
uint64_t *p;
int loops;
for (loops=0; loops<RAMBOX_LOOPS; loops++) {
old=rf_add64_crc32(old);
p=&rambox[old&(RAMBOX_SIZE-1)];
old+=rf_rotr64(*p, old/RAMBOX_SIZE);
// 0x80 below gives a write ratio of 50%
if ((old>>56)<0x80)
*p = old;
}
return old;
}
// write (_x_,_y_) at cell _cell_ for offset _ofs_
static inline void rf_w128(uint64_t *cell, ulong ofs, uint64_t x, uint64_t y) {
#if defined(__ARM_ARCH_8A) || defined(__AARCH64EL__)
// 128 bit at once is faster when exactly two parallelizable instructions are
// used between two calls to keep the pipe full.
asm volatile("stp %0, %1, [%2,#%3]\n\t"
: /* no output */
: "r"(x), "r"(y), "r" (cell), "I" (ofs*8));
#else
cell[ofs+0] = x;
cell[ofs+1] = y;
#endif
}
// initialize the ram box
static __attribute__((noinline)) void rf_raminit(uint64_t *rambox) {
uint64_t pat1 = 0x0123456789ABCDEFULL;
uint64_t pat2 = 0xFEDCBA9876543210ULL;
uint64_t pat3;
uint32_t pos;
// Note: no need to mask the higher bits on armv8 nor x86 :
//
// From ARMv8's ref manual :
// The register that is specified for a shift can be 32-bit or
// 64-bit. The amount to be shifted can be specified either as
// an immediate, that is up to register size minus one, or by
// a register where the value is taken only from the bottom five
// (modulo-32) or six (modulo-64) bits.
//
// Here we rotate pat2 by pat1's bits and put it into pat1, and in
// parallel we rotate pat1 by pat2's bits and put it into pat2. Thus
// the two data blocks are exchanged in addition to being rotated.
// What is stored each time is the previous and the rotated blocks,
// which only requires one rotate and a register rename.
for (pos = 0; pos < RAMBOX_SIZE; pos += 16) {
pat3 = pat1;
pat1 = rf_rotr64(pat2, pat3) + 0x111;
rf_w128(rambox + pos, 0, pat1, pat3);
pat3 = pat2;
pat2 = rf_rotr64(pat1, pat3) + 0x222;
rf_w128(rambox + pos, 2, pat2, pat3);
pat3 = pat1;
pat1 = rf_rotr64(pat2, pat3) + 0x333;
rf_w128(rambox + pos, 4, pat1, pat3);
pat3 = pat2;
pat2 = rf_rotr64(pat1, pat3) + 0x444;
rf_w128(rambox + pos, 6, pat2, pat3);
pat3 = pat1;
pat1 = rf_rotr64(pat2, pat3) + 0x555;
rf_w128(rambox + pos, 8, pat1, pat3);
pat3 = pat2;
pat2 = rf_rotr64(pat1, pat3) + 0x666;
rf_w128(rambox + pos, 10, pat2, pat3);
pat3 = pat1;
pat1 = rf_rotr64(pat2, pat3) + 0x777;
rf_w128(rambox + pos, 12, pat1, pat3);
pat3 = pat2;
pat2 = rf_rotr64(pat1, pat3) + 0x888;
rf_w128(rambox + pos, 14, pat2, pat3);
}
}
// exec the div/mod box. _v0_ and _v1_ must be aligned.
static inline void rf256_divbox(rf_u64 *v0, rf_u64 *v1) {
uint64_t pl, ql, ph, qh;
//---- low word ---- ---- high word ----
pl=~*v0; ph=~*v1;
ql=rf_bswap64(*v0); qh=rf_bswap64(*v1);
if (!pl||!ql) { pl=ql=0; }
else if (pl>ql) { uint64_t p=pl; pl=p/ql; ql=p%ql; }
else { uint64_t p=pl; pl=ql/p; ql=ql%p; }
if (!ph||!qh) { ph=qh=0; }
else if (ph>qh) { uint64_t p=ph; ph=p/qh; qh=p%qh; }
else { uint64_t p=ph; ph=qh/p; qh=qh%p; }
pl+=qh; ph+=ql;
*v0-=pl; *v1-=ph;
}
// exec the rotation/add box. _v0_ and _v1_ must be aligned.
static inline void rf256_rotbox(rf_u64 *v0, rf_u64 *v1, uint8_t b0, uint8_t b1) {
uint64_t l, h;
//---- low word ---- ---- high word ----
l=*v0; h=*v1;
l=rf_rotr64(l,b0); h=rf_rotl64(h,b1);
l+=rf_wltable(b0); h+=rf_whtable(b1);
b0=l; b1=h;
l=rf_rotl64(l,b1); h=rf_rotr64(h,b0);
b0=l; b1=h;
l=rf_rotr64(l,b1); h=rf_rotl64(h,b0);
*v0=l; *v1=h;
}
// mix the current state with the current crc
static inline uint32_t rf256_scramble(rf256_ctx_t *ctx) {
return ctx->crc=rf_crc32x4(ctx->hash.d, ctx->crc);
}
// mix the state with the crc and the pending text, and update the crc
static inline void rf256_inject(rf256_ctx_t *ctx) {
// BS: never <4 bytes with 80 input bytes
//ctx->crc=
// (ctx->bytes&3)==0?rf_crc32_32(rf256_scramble(ctx), ctx->word):
// (ctx->bytes&3)==3?rf_crc32_24(rf256_scramble(ctx), ctx->word):
// (ctx->bytes&3)==2?rf_crc32_16(rf256_scramble(ctx), ctx->word):
// rf_crc32_8(rf256_scramble(ctx), ctx->word);
ctx->crc=rf_crc32_32(rf256_scramble(ctx), ctx->word);
ctx->word=0;
}
// rotate the hash by 32 bits. Not using streaming instructions (SSE/NEON) is
// faster because the compiler can follow moves an use register renames.
static inline void rf256_rot32x256(hash256_t *hash) {
#if defined(__x86_64__) || defined(__aarch64__) || defined(__ARM_ARCH_7A__)
uint32_t t0, t1, t2;
t0=hash->d[0];
t1=hash->d[1];
t2=hash->d[2];
hash->d[1]=t0;
hash->d[2]=t1;
t0=hash->d[3];
t1=hash->d[4];
hash->d[3]=t2;
hash->d[4]=t0;
t2=hash->d[5];
t0=hash->d[6];
hash->d[5]=t1;
hash->d[6]=t2;
t1=hash->d[7];
hash->d[7]=t0;
hash->d[0]=t1;
#else
uint32_t tmp=hash->d[7];
memmove(&hash->d[1], &hash->d[0], 28);
hash->d[0]=tmp;
#endif
}
// encrypt the first 128 bits of the hash using the last 128 bits as the key
static inline void rf256_aesenc(rf256_ctx_t *ctx) {
aes2r_encrypt((uint8_t *)ctx->hash.b, (uint8_t *)ctx->hash.b+16);
}
// each new round consumes exactly 32 bits of text at once and perturbates
// 128 bits of output, 96 of which overlap with the previous round, and 32
// of which are new. With 5 rounds or more each output bit depends on every
// input bit.
static inline void rf256_one_round(rf256_ctx_t *ctx) {
uint64_t carry;
rf256_rot32x256(&ctx->hash);
carry=((uint64_t)ctx->len << 32) + ctx->crc;
rf256_scramble(ctx);
rf256_divbox(ctx->hash.q, ctx->hash.q+1);
rf256_scramble(ctx);
carry=rf_rambox(ctx->rambox, carry);
rf256_rotbox(ctx->hash.q, ctx->hash.q+1, carry, carry>>56);
rf256_scramble(ctx);
rf256_divbox(ctx->hash.q, ctx->hash.q+1);
rf256_scramble(ctx);
rf256_divbox(ctx->hash.q, ctx->hash.q+1);
rf256_scramble(ctx);
carry=rf_rambox(ctx->rambox, carry);
rf256_rotbox(ctx->hash.q, ctx->hash.q+1, carry>>8, carry>>48);
rf256_scramble(ctx);
rf256_divbox(ctx->hash.q, ctx->hash.q+1);
rf256_scramble(ctx);
rf256_divbox(ctx->hash.q, ctx->hash.q+1);
rf256_scramble(ctx);
carry=rf_rambox(ctx->rambox, carry);
rf256_rotbox(ctx->hash.q, ctx->hash.q+1, carry>>16, carry>>40);
rf256_scramble(ctx);
rf256_divbox(ctx->hash.q, ctx->hash.q+1);
rf256_scramble(ctx);
rf256_divbox(ctx->hash.q, ctx->hash.q+1);
rf256_scramble(ctx);
carry=rf_rambox(ctx->rambox,carry);
rf256_rotbox(ctx->hash.q, ctx->hash.q+1, carry>>24, carry>>32);
rf256_scramble(ctx);
rf256_divbox(ctx->hash.q, ctx->hash.q+1);
rf256_inject(ctx);
rf256_aesenc(ctx);
rf256_scramble(ctx);
}
// initialize the hash state
static void rf256_init(rf256_ctx_t *ctx) {
rf_raminit(ctx->rambox);
memcpy(ctx->hash.b, rf256_iv, sizeof(ctx->hash.b));
ctx->crc=RF256_INIT_CRC;
ctx->word=ctx->len=0;
}
// update the hash context _ctx_ with _len_ bytes from message _msg_
static void rf256_update(rf256_ctx_t *ctx, const void *msg, size_t len) {
while (len > 0) {
#ifdef RF_UNALIGNED_LE32
if (!(ctx->len&3) && len>=4) {
ctx->word=*(uint32_t *)msg;
ctx->len+=4;
rf256_one_round(ctx);
msg+=4;
len-=4;
continue;
}
#endif
ctx->word|=((uint32_t)*(uint8_t *)msg++)<<(8*(ctx->len++&3));
len--;
if (!(ctx->len&3))
rf256_one_round(ctx);
}
}
// finalize the hash and copy the result into _out_ if not null (256 bits)
static void rf256_final(void *out, rf256_ctx_t *ctx) {
// BS: never happens with 80 input bytes
//uint32_t pad;
//if (ctx->len&3)
// rf256_one_round(ctx);
// always work on at least 256 bits of input
//for (pad=0; pad+ctx->len < 32;pad+=4)
// rf256_one_round(ctx);
// always run 4 extra rounds to complete the last 128 bits
rf256_one_round(ctx);
rf256_one_round(ctx);
rf256_one_round(ctx);
rf256_one_round(ctx);
//if (out)
memcpy(out, ctx->hash.b, 32);
}
// hash _len_ bytes from _in_ into _out_
void rf256_hash(void *out, const void *in, size_t len) {
rf256_ctx_t ctx;
rf256_init(&ctx);
rf256_update(&ctx, in, len);
rf256_final(out, &ctx);
}

View file

@ -0,0 +1,19 @@
#ifndef RAINFOREST_H
#define RAINFOREST_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void rf256_hash(void *out, const void *in, size_t len);
static inline void rainforest_hash(const char* input, char* output, uint32_t len) {
rf256_hash(output, input, len);
}
#ifdef __cplusplus
}
#endif
#endif

32
stratum/algos/sha256q.c Normal file
View file

@ -0,0 +1,32 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "sha256.h"
#include <stdlib.h>
void sha256q_hash(const char* input, char* output, uint32_t len)
{
unsigned char hash[64];
SHA256_CTX ctx_sha256;
SHA256_Init(&ctx_sha256);
SHA256_Update(&ctx_sha256, input, len);
SHA256_Final(hash, &ctx_sha256);
SHA256_Init(&ctx_sha256);
SHA256_Update(&ctx_sha256, hash, 32);
SHA256_Final(hash, &ctx_sha256);
SHA256_Init(&ctx_sha256);
SHA256_Update(&ctx_sha256, hash, 32);
SHA256_Final(hash, &ctx_sha256);
SHA256_Init(&ctx_sha256);
SHA256_Update(&ctx_sha256, hash, 32);
SHA256_Final((unsigned char*)output, &ctx_sha256);
}

16
stratum/algos/sha256q.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef SHA256Q_H
#define SHA256Q_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void sha256q_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -183,7 +183,7 @@ void sm3_compress(uint32_t digest[8], const unsigned char block[64])
for(j = 16; j < 64; j++) { for(j = 16; j < 64; j++) {
T[j] = 0x7A879D8A; T[j] = 0x7A879D8A;
SS1 = ROTATELEFT((ROTATELEFT(A,12) + E + ROTATELEFT(T[j],j)), 7); SS1 = ROTATELEFT((ROTATELEFT(A,12) + E + ROTATELEFT(T[j],j&31)), 7);
SS2 = SS1 ^ ROTATELEFT(A,12); SS2 = SS1 ^ ROTATELEFT(A,12);
TT1 = FF1(A,B,C) + D + SS2 + W1[j]; TT1 = FF1(A,B,C) + D + SS2 + W1[j];
TT2 = GG1(E,F,G) + H + SS1 + W[j]; TT2 = GG1(E,F,G) + H + SS1 + W[j];

369
stratum/algos/sonoa.c Normal file
View file

@ -0,0 +1,369 @@
#include <stdlib.h>
#include <string.h>
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_groestl.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_keccak.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_shavite.h>
#include <sha3/sph_simd.h>
#include <sha3/sph_echo.h>
#include <sha3/sph_hamsi.h>
#include <sha3/sph_fugue.h>
#include <sha3/sph_shabal.h>
#include <sha3/sph_whirlpool.h>
#include <sha3/sph_sha2.h>
#include <sha3/sph_haval.h>
#include "common.h"
void sonoa_hash(const char* input, char* output, uint32_t len)
{
uint8_t _ALIGN(128) hash[64];
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_skein512_context ctx_skein;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
sph_shavite512_context ctx_shavite;
sph_simd512_context ctx_simd;
sph_echo512_context ctx_echo;
sph_hamsi512_context ctx_hamsi;
sph_fugue512_context ctx_fugue;
sph_shabal512_context ctx_shabal;
sph_whirlpool_context ctx_whirlpool;
sph_sha512_context ctx_sha512;
sph_haval256_5_context ctx_haval;
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, input, 80);
sph_blake512_close(&ctx_blake, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, hash, 64);
sph_groestl512_close(&ctx_groestl, hash);
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, hash, 64);
sph_keccak512_close(&ctx_keccak, hash);
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, hash, 64);
sph_cubehash512_close(&ctx_cubehash, hash);
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_groestl512(&ctx_groestl, hash, 64);
sph_groestl512_close(&ctx_groestl, hash);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_keccak512(&ctx_keccak, hash, 64);
sph_keccak512_close(&ctx_keccak, hash);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
sph_cubehash512(&ctx_cubehash, hash, 64);
sph_cubehash512_close(&ctx_cubehash, hash);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_hamsi512_init(&ctx_hamsi);
sph_hamsi512(&ctx_hamsi, hash, 64);
sph_hamsi512_close(&ctx_hamsi, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_groestl512(&ctx_groestl, hash, 64);
sph_groestl512_close(&ctx_groestl, hash);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_keccak512(&ctx_keccak, hash, 64);
sph_keccak512_close(&ctx_keccak, hash);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
sph_cubehash512(&ctx_cubehash, hash, 64);
sph_cubehash512_close(&ctx_cubehash, hash);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_hamsi512(&ctx_hamsi, hash, 64);
sph_hamsi512_close(&ctx_hamsi, hash);
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, hash, 64);
sph_fugue512_close(&ctx_fugue, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_groestl512(&ctx_groestl, hash, 64);
sph_groestl512_close(&ctx_groestl, hash);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_keccak512(&ctx_keccak, hash, 64);
sph_keccak512_close(&ctx_keccak, hash);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
sph_cubehash512(&ctx_cubehash, hash, 64);
sph_cubehash512_close(&ctx_cubehash, hash);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_hamsi512(&ctx_hamsi, hash, 64);
sph_hamsi512_close(&ctx_hamsi, hash);
sph_fugue512(&ctx_fugue, hash, 64);
sph_fugue512_close(&ctx_fugue, hash);
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, hash, 64);
sph_shabal512_close(&ctx_shabal, hash);
sph_hamsi512(&ctx_hamsi, hash, 64);
sph_hamsi512_close(&ctx_hamsi, hash);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_shabal512(&ctx_shabal, hash, 64);
sph_shabal512_close(&ctx_shabal, hash);
sph_groestl512(&ctx_groestl, hash, 64);
sph_groestl512_close(&ctx_groestl, hash);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_keccak512(&ctx_keccak, hash, 64);
sph_keccak512_close(&ctx_keccak, hash);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
sph_cubehash512(&ctx_cubehash, hash, 64);
sph_cubehash512_close(&ctx_cubehash, hash);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_hamsi512(&ctx_hamsi, hash, 64);
sph_hamsi512_close(&ctx_hamsi, hash);
sph_fugue512(&ctx_fugue, hash, 64);
sph_fugue512_close(&ctx_fugue, hash);
sph_shabal512(&ctx_shabal, hash, 64);
sph_shabal512_close(&ctx_shabal, hash);
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool(&ctx_whirlpool, hash, 64);
sph_whirlpool_close(&ctx_whirlpool, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_groestl512(&ctx_groestl, hash, 64);
sph_groestl512_close(&ctx_groestl, hash);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_keccak512(&ctx_keccak, hash, 64);
sph_keccak512_close(&ctx_keccak, hash);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
sph_cubehash512(&ctx_cubehash, hash, 64);
sph_cubehash512_close(&ctx_cubehash, hash);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_hamsi512(&ctx_hamsi, hash, 64);
sph_hamsi512_close(&ctx_hamsi, hash);
sph_fugue512(&ctx_fugue, hash, 64);
sph_fugue512_close(&ctx_fugue, hash);
sph_shabal512(&ctx_shabal, hash, 64);
sph_shabal512_close(&ctx_shabal, hash);
sph_whirlpool(&ctx_whirlpool, hash, 64);
sph_whirlpool_close(&ctx_whirlpool, hash);
sph_sha512_init(&ctx_sha512);
sph_sha512(&ctx_sha512,(const void*) hash, 64);
sph_sha512_close(&ctx_sha512,(void*) hash);
sph_whirlpool(&ctx_whirlpool, hash, 64);
sph_whirlpool_close(&ctx_whirlpool, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_groestl512(&ctx_groestl, hash, 64);
sph_groestl512_close(&ctx_groestl, hash);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_keccak512(&ctx_keccak, hash, 64);
sph_keccak512_close(&ctx_keccak, hash);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
sph_cubehash512(&ctx_cubehash, hash, 64);
sph_cubehash512_close(&ctx_cubehash, hash);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_hamsi512(&ctx_hamsi, hash, 64);
sph_hamsi512_close(&ctx_hamsi, hash);
sph_fugue512(&ctx_fugue, hash, 64);
sph_fugue512_close(&ctx_fugue, hash);
sph_shabal512(&ctx_shabal, hash, 64);
sph_shabal512_close(&ctx_shabal, hash);
sph_whirlpool(&ctx_whirlpool, hash, 64);
sph_whirlpool_close(&ctx_whirlpool, hash);
sph_sha512(&ctx_sha512,(const void*) hash, 64);
sph_sha512_close(&ctx_sha512,(void*) hash);
sph_haval256_5_init(&ctx_haval);
sph_haval256_5(&ctx_haval,(const void*) hash, 64);
sph_haval256_5_close(&ctx_haval, hash);
memcpy(output, hash, 32);
}

16
stratum/algos/sonoa.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef SONOA_H
#define SONOA_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void sonoa_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

87
stratum/algos/vitalium.c Normal file
View file

@ -0,0 +1,87 @@
#include "vitalium.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_fugue.h>
#include <sha3/sph_echo.h>
#include <sha3/sph_shavite.h>
#include <sha3/sph_luffa.h>
#include "gost.h"
#include "common.h"
void vitalium_hash(const char* input, char* output, uint32_t len)
{
sph_skein512_context ctx_skein;
sph_cubehash512_context ctx_cubehash;
sph_fugue512_context ctx_fugue;
sph_gost512_context ctx_gost;
sph_echo512_context ctx_echo;
sph_shavite512_context ctx_shavite;
sph_luffa512_context ctx_luffa;
//these uint512 in the c++ source of the client are backed by an array of uint32
uint32_t hashA[16], hashB[16];
sph_skein512_init(&ctx_skein);
sph_skein512 (&ctx_skein, input, len);
sph_skein512_close (&ctx_skein, hashA);
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512 (&ctx_cubehash, hashA, 64);
sph_cubehash512_close(&ctx_cubehash, hashB);
sph_fugue512_init(&ctx_fugue);
sph_fugue512 (&ctx_fugue, hashB, 64);
sph_fugue512_close(&ctx_fugue, hashA);
sph_gost512_init(&ctx_gost);
sph_gost512 (&ctx_gost, hashA, 64);
sph_gost512_close (&ctx_gost, hashB);
sph_echo512_init(&ctx_echo);
sph_echo512 (&ctx_echo, hashB, 64);
sph_echo512_close(&ctx_echo, hashA);
sph_shavite512_init(&ctx_shavite);
sph_shavite512 (&ctx_shavite, hashA, 64);
sph_shavite512_close(&ctx_shavite, hashB);
sph_luffa512_init (&ctx_luffa);
sph_luffa512 (&ctx_luffa, hashB, 64);
sph_luffa512_close (&ctx_luffa, hashA);
sph_gost512_init(&ctx_gost);
sph_gost512 (&ctx_gost, hashA, 64);
sph_gost512_close (&ctx_gost, hashB);
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512 (&ctx_cubehash, hashB, 64);
sph_cubehash512_close(&ctx_cubehash, hashA);
sph_fugue512_init(&ctx_fugue);
sph_fugue512 (&ctx_fugue, hashA, 64);
sph_fugue512_close(&ctx_fugue, hashB);
sph_gost512_init(&ctx_gost);
sph_gost512 (&ctx_gost, hashB, 64);
sph_gost512_close (&ctx_gost, hashA);
sph_echo512_init(&ctx_echo);
sph_echo512 (&ctx_echo, hashA, 64);
sph_echo512_close(&ctx_echo, hashB);
sph_shavite512_init(&ctx_shavite);
sph_shavite512 (&ctx_shavite, hashB, 64);
sph_shavite512_close(&ctx_shavite, hashA);
sph_luffa512_init (&ctx_luffa);
sph_luffa512 (&ctx_luffa, hashA, 64);
sph_luffa512_close (&ctx_luffa, hashB);
memcpy(output, hashB, 32);
}

16
stratum/algos/vitalium.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef VITALITY_H
#define VITALITY_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void vitalium_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

85
stratum/algos/x12.c Normal file
View file

@ -0,0 +1,85 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_shavite.h>
#include <sha3/sph_simd.h>
#include <sha3/sph_echo.h>
#include <sha3/sph_groestl.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_keccak.h>
#include <sha3/sph_hamsi.h>
void x12_hash(const char* input, char* output, uint32_t len)
{
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
sph_shavite512_context ctx_shavite;
sph_simd512_context ctx_simd;
sph_echo512_context ctx_echo;
sph_groestl512_context ctx_groestl;
sph_skein512_context ctx_skein;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_hamsi512_context ctx_hamsi;
uint32_t hash[16];
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, input, len);
sph_blake512_close(&ctx_blake, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, hash, 64);
sph_cubehash512_close(&ctx_cubehash, hash);
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, hash, 64);
sph_groestl512_close(&ctx_groestl, hash);
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, hash, 64);
sph_keccak512_close(&ctx_keccak, hash);
sph_hamsi512_init(&ctx_hamsi);
sph_hamsi512(&ctx_hamsi, hash, 64);
sph_hamsi512_close(&ctx_hamsi, hash);
memcpy(output, hash, 32);
}

16
stratum/algos/x12.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef X12_H
#define X12_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void x12_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

178
stratum/algos/x16r.c Normal file
View file

@ -0,0 +1,178 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_groestl.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_keccak.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_shavite.h>
#include <sha3/sph_simd.h>
#include <sha3/sph_echo.h>
#include <sha3/sph_hamsi.h>
#include <sha3/sph_fugue.h>
#include <sha3/sph_shabal.h>
#include <sha3/sph_whirlpool.h>
#include <sha3/sph_sha2.h>
#include "common.h"
enum Algo {
BLAKE = 0,
BMW,
GROESTL,
JH,
KECCAK,
SKEIN,
LUFFA,
CUBEHASH,
SHAVITE,
SIMD,
ECHO,
HAMSI,
FUGUE,
SHABAL,
WHIRLPOOL,
SHA512,
HASH_FUNC_COUNT
};
static void getAlgoString(const uint8_t* prevblock, char *output)
{
char *sptr = output;
for (int j = 0; j < HASH_FUNC_COUNT; j++) {
char b = (15 - j) >> 1; // 16 ascii hex chars, reversed
uint8_t algoDigit = (j & 1) ? prevblock[b] & 0xF : prevblock[b] >> 4;
if (algoDigit >= 10)
sprintf(sptr, "%c", 'A' + (algoDigit - 10));
else
sprintf(sptr, "%u", (uint32_t) algoDigit);
sptr++;
}
*sptr = '\0';
}
void x16r_hash(const char* input, char* output, uint32_t len)
{
uint32_t hash[64/4];
char hashOrder[HASH_FUNC_COUNT + 1] = { 0 };
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_skein512_context ctx_skein;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
sph_shavite512_context ctx_shavite;
sph_simd512_context ctx_simd;
sph_echo512_context ctx_echo;
sph_hamsi512_context ctx_hamsi;
sph_fugue512_context ctx_fugue;
sph_shabal512_context ctx_shabal;
sph_whirlpool_context ctx_whirlpool;
sph_sha512_context ctx_sha512;
void *in = (void*) input;
int size = len;
getAlgoString(&input[4], hashOrder);
for (int i = 0; i < 16; i++)
{
const char elem = hashOrder[i];
const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0';
switch (algo) {
case BLAKE:
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, in, size);
sph_blake512_close(&ctx_blake, hash);
break;
case BMW:
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, in, size);
sph_bmw512_close(&ctx_bmw, hash);
break;
case GROESTL:
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, in, size);
sph_groestl512_close(&ctx_groestl, hash);
break;
case SKEIN:
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, in, size);
sph_skein512_close(&ctx_skein, hash);
break;
case JH:
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, in, size);
sph_jh512_close(&ctx_jh, hash);
break;
case KECCAK:
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, in, size);
sph_keccak512_close(&ctx_keccak, hash);
break;
case LUFFA:
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, in, size);
sph_luffa512_close(&ctx_luffa, hash);
break;
case CUBEHASH:
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, in, size);
sph_cubehash512_close(&ctx_cubehash, hash);
break;
case SHAVITE:
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, in, size);
sph_shavite512_close(&ctx_shavite, hash);
break;
case SIMD:
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, in, size);
sph_simd512_close(&ctx_simd, hash);
break;
case ECHO:
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, in, size);
sph_echo512_close(&ctx_echo, hash);
break;
case HAMSI:
sph_hamsi512_init(&ctx_hamsi);
sph_hamsi512(&ctx_hamsi, in, size);
sph_hamsi512_close(&ctx_hamsi, hash);
break;
case FUGUE:
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, in, size);
sph_fugue512_close(&ctx_fugue, hash);
break;
case SHABAL:
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, in, size);
sph_shabal512_close(&ctx_shabal, hash);
break;
case WHIRLPOOL:
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool(&ctx_whirlpool, in, size);
sph_whirlpool_close(&ctx_whirlpool, hash);
break;
case SHA512:
sph_sha512_init(&ctx_sha512);
sph_sha512(&ctx_sha512,(const void*) in, size);
sph_sha512_close(&ctx_sha512,(void*) hash);
break;
}
in = (void*) hash;
size = 64;
}
memcpy(output, hash, 32);
}

16
stratum/algos/x16r.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef X16R_H
#define X16R_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void x16r_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

199
stratum/algos/x16rv2.c Normal file
View file

@ -0,0 +1,199 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_groestl.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_keccak.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_shavite.h>
#include <sha3/sph_simd.h>
#include <sha3/sph_echo.h>
#include <sha3/sph_hamsi.h>
#include <sha3/sph_fugue.h>
#include <sha3/sph_shabal.h>
#include <sha3/sph_whirlpool.h>
#include <sha3/sph_sha2.h>
#include <sha3/sph_tiger.h>
#include "common.h"
enum Algo {
BLAKE = 0,
BMW,
GROESTL,
JH,
KECCAK,
SKEIN,
LUFFA,
CUBEHASH,
SHAVITE,
SIMD,
ECHO,
HAMSI,
FUGUE,
SHABAL,
WHIRLPOOL,
SHA512,
HASH_FUNC_COUNT
};
static void getAlgoString(const uint8_t* prevblock, char *output)
{
char *sptr = output;
for (int j = 0; j < HASH_FUNC_COUNT; j++) {
char b = (15 - j) >> 1; // 16 ascii hex chars, reversed
uint8_t algoDigit = (j & 1) ? prevblock[b] & 0xF : prevblock[b] >> 4;
if (algoDigit >= 10)
sprintf(sptr, "%c", 'A' + (algoDigit - 10));
else
sprintf(sptr, "%u", (uint32_t) algoDigit);
sptr++;
}
*sptr = '\0';
}
inline void padtiger512(uint32_t* hash) {
for (int i = (24/4); i < (64/4); i++) hash[i] = 0;
}
void x16rv2_hash(const char* input, char* output, uint32_t len)
{
uint32_t hash[64/4];
char hashOrder[HASH_FUNC_COUNT + 1] = { 0 };
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_skein512_context ctx_skein;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
sph_shavite512_context ctx_shavite;
sph_simd512_context ctx_simd;
sph_echo512_context ctx_echo;
sph_hamsi512_context ctx_hamsi;
sph_fugue512_context ctx_fugue;
sph_shabal512_context ctx_shabal;
sph_whirlpool_context ctx_whirlpool;
sph_sha512_context ctx_sha512;
sph_tiger_context ctx_tiger;
void *in = (void*) input;
int size = len;
getAlgoString(&input[4], hashOrder);
for (int i = 0; i < 16; i++)
{
const char elem = hashOrder[i];
const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0';
switch (algo) {
case BLAKE:
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, in, size);
sph_blake512_close(&ctx_blake, hash);
break;
case BMW:
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, in, size);
sph_bmw512_close(&ctx_bmw, hash);
break;
case GROESTL:
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, in, size);
sph_groestl512_close(&ctx_groestl, hash);
break;
case SKEIN:
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, in, size);
sph_skein512_close(&ctx_skein, hash);
break;
case JH:
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, in, size);
sph_jh512_close(&ctx_jh, hash);
break;
case KECCAK:
sph_tiger_init(&ctx_tiger);
sph_tiger(&ctx_tiger, (const void*) in, size);
sph_tiger_close(&ctx_tiger, (void*) hash);
padtiger512(hash);
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, hash, 64);
sph_keccak512_close(&ctx_keccak, hash);
break;
case LUFFA:
sph_tiger_init(&ctx_tiger);
sph_tiger(&ctx_tiger, (const void*) in, size);
sph_tiger_close(&ctx_tiger, (void*) hash);
padtiger512(hash);
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
break;
case CUBEHASH:
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, in, size);
sph_cubehash512_close(&ctx_cubehash, hash);
break;
case SHAVITE:
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, in, size);
sph_shavite512_close(&ctx_shavite, hash);
break;
case SIMD:
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, in, size);
sph_simd512_close(&ctx_simd, hash);
break;
case ECHO:
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, in, size);
sph_echo512_close(&ctx_echo, hash);
break;
case HAMSI:
sph_hamsi512_init(&ctx_hamsi);
sph_hamsi512(&ctx_hamsi, in, size);
sph_hamsi512_close(&ctx_hamsi, hash);
break;
case FUGUE:
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, in, size);
sph_fugue512_close(&ctx_fugue, hash);
break;
case SHABAL:
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, in, size);
sph_shabal512_close(&ctx_shabal, hash);
break;
case WHIRLPOOL:
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool(&ctx_whirlpool, in, size);
sph_whirlpool_close(&ctx_whirlpool, hash);
break;
case SHA512:
sph_tiger_init(&ctx_tiger);
sph_tiger(&ctx_tiger, (const void*) in, size);
sph_tiger_close(&ctx_tiger, (void*) hash);
padtiger512(hash);
sph_sha512_init(&ctx_sha512);
sph_sha512(&ctx_sha512,(const void*) hash, 64);
sph_sha512_close(&ctx_sha512,(void*) hash);
break;
}
in = (void*) hash;
size = 64;
}
memcpy(output, hash, 32);
}

16
stratum/algos/x16rv2.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef X16RV2_H
#define X16RV2_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void x16rv2_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

180
stratum/algos/x16s.c Normal file
View file

@ -0,0 +1,180 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_groestl.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_keccak.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_shavite.h>
#include <sha3/sph_simd.h>
#include <sha3/sph_echo.h>
#include <sha3/sph_hamsi.h>
#include <sha3/sph_fugue.h>
#include <sha3/sph_shabal.h>
#include <sha3/sph_whirlpool.h>
#include <sha3/sph_sha2.h>
#include "common.h"
enum Algo {
BLAKE = 0,
BMW,
GROESTL,
JH,
KECCAK,
SKEIN,
LUFFA,
CUBEHASH,
SHAVITE,
SIMD,
ECHO,
HAMSI,
FUGUE,
SHABAL,
WHIRLPOOL,
SHA512,
HASH_FUNC_COUNT
};
static void getAlgoString(const uint8_t* prevblock, char *output)
{
strcpy(output, "0123456789ABCDEF");
for(int i = 0; i < 16; i++){
uint8_t b = (15 - i) >> 1; // 16 ascii hex chars, reversed
uint8_t algoDigit = (i & 1) ? prevblock[b] & 0xF : prevblock[b] >> 4;
int offset = algoDigit;
// insert the nth character at the front
char oldVal = output[offset];
for(int j=offset; j-->0;) {
output[j+1] = output[j];
}
output[0] = oldVal;
}
}
void x16s_hash(const char* input, char* output, uint32_t len)
{
uint32_t hash[64/4];
char hashOrder[HASH_FUNC_COUNT + 1] = { 0 };
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_skein512_context ctx_skein;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
sph_shavite512_context ctx_shavite;
sph_simd512_context ctx_simd;
sph_echo512_context ctx_echo;
sph_hamsi512_context ctx_hamsi;
sph_fugue512_context ctx_fugue;
sph_shabal512_context ctx_shabal;
sph_whirlpool_context ctx_whirlpool;
sph_sha512_context ctx_sha512;
void *in = (void*) input;
int size = len;
getAlgoString(&input[4], hashOrder);
for (int i = 0; i < 16; i++)
{
const char elem = hashOrder[i];
const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0';
switch (algo) {
case BLAKE:
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, in, size);
sph_blake512_close(&ctx_blake, hash);
break;
case BMW:
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, in, size);
sph_bmw512_close(&ctx_bmw, hash);
break;
case GROESTL:
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, in, size);
sph_groestl512_close(&ctx_groestl, hash);
break;
case SKEIN:
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, in, size);
sph_skein512_close(&ctx_skein, hash);
break;
case JH:
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, in, size);
sph_jh512_close(&ctx_jh, hash);
break;
case KECCAK:
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, in, size);
sph_keccak512_close(&ctx_keccak, hash);
break;
case LUFFA:
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, in, size);
sph_luffa512_close(&ctx_luffa, hash);
break;
case CUBEHASH:
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, in, size);
sph_cubehash512_close(&ctx_cubehash, hash);
break;
case SHAVITE:
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, in, size);
sph_shavite512_close(&ctx_shavite, hash);
break;
case SIMD:
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, in, size);
sph_simd512_close(&ctx_simd, hash);
break;
case ECHO:
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, in, size);
sph_echo512_close(&ctx_echo, hash);
break;
case HAMSI:
sph_hamsi512_init(&ctx_hamsi);
sph_hamsi512(&ctx_hamsi, in, size);
sph_hamsi512_close(&ctx_hamsi, hash);
break;
case FUGUE:
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, in, size);
sph_fugue512_close(&ctx_fugue, hash);
break;
case SHABAL:
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, in, size);
sph_shabal512_close(&ctx_shabal, hash);
break;
case WHIRLPOOL:
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool(&ctx_whirlpool, in, size);
sph_whirlpool_close(&ctx_whirlpool, hash);
break;
case SHA512:
sph_sha512_init(&ctx_sha512);
sph_sha512(&ctx_sha512,(const void*) in, size);
sph_sha512_close(&ctx_sha512,(void*) hash);
break;
}
in = (void*) hash;
size = 64;
}
memcpy(output, hash, 32);
}

16
stratum/algos/x16s.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef X16S_H
#define X16S_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void x16s_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

146
stratum/algos/x22i.c Normal file
View file

@ -0,0 +1,146 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_groestl.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_keccak.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_shavite.h>
#include <sha3/sph_simd.h>
#include <sha3/sph_echo.h>
#include <sha3/sph_hamsi.h>
#include <sha3/sph_fugue.h>
#include <sha3/sph_shabal.h>
#include <sha3/sph_whirlpool.h>
#include <sha3/sph_sha2.h>
#include <sha3/sph_haval.h>
#include <sha3/sph_tiger.h>
#include "SWIFFTX/SWIFFTX.h"
#include "gost.h"
#include "Lyra2.h"
#include "common.h"
void x22i_hash(const char* input, char* output, uint32_t len)
{
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_skein512_context ctx_skein;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
sph_shavite512_context ctx_shavite;
sph_simd512_context ctx_simd;
sph_echo512_context ctx_echo;
sph_hamsi512_context ctx_hamsi;
sph_fugue512_context ctx_fugue;
sph_shabal512_context ctx_shabal;
sph_whirlpool_context ctx_whirlpool;
sph_sha512_context ctx_sha512;
sph_haval256_5_context ctx_haval;
sph_tiger_context ctx_tiger;
sph_gost512_context ctx_gost;
sph_sha256_context ctx_sha;
unsigned char _ALIGN(128) hash[64 * 4] = {0};
unsigned char _ALIGN(128) hash2[64];
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, input, len);
sph_blake512_close (&ctx_blake, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, hash, 64);
sph_groestl512_close(&ctx_groestl, hash);
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, hash, 64);
sph_keccak512_close(&ctx_keccak, hash);
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close (&ctx_luffa, hash);
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, hash, 64);
sph_cubehash512_close(&ctx_cubehash, hash);
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_hamsi512_init(&ctx_hamsi);
sph_hamsi512(&ctx_hamsi, hash, 64);
sph_hamsi512_close(&ctx_hamsi, hash);
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, hash, 64);
sph_fugue512_close(&ctx_fugue, hash);
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, (const void*) hash, 64);
sph_shabal512_close(&ctx_shabal, &hash[64]);
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool (&ctx_whirlpool, (const void*) &hash[64], 64);
sph_whirlpool_close(&ctx_whirlpool, &hash[128]);
sph_sha512_init(&ctx_sha512);
sph_sha512(&ctx_sha512,(const void*) &hash[128], 64);
sph_sha512_close(&ctx_sha512,(void*) &hash[192]);
InitializeSWIFFTX();
ComputeSingleSWIFFTX((unsigned char*)hash, (unsigned char*)hash2, false);
memset(hash, 0, 64);
sph_haval256_5_init(&ctx_haval);
sph_haval256_5(&ctx_haval,(const void*) hash2, 64);
sph_haval256_5_close(&ctx_haval,hash);
memset(hash2, 0, 64);
sph_tiger_init(&ctx_tiger);
sph_tiger (&ctx_tiger, (const void*) hash, 64);
sph_tiger_close(&ctx_tiger, (void*) hash2);
memset(hash, 0, 64);
LYRA2((void*) hash, 32, (const void*) hash2, 32, (const void*) hash2, 32, 1, 4, 4);
sph_gost512_init(&ctx_gost);
sph_gost512 (&ctx_gost, (const void*) hash, 64);
sph_gost512_close(&ctx_gost, (void*) hash);
sph_sha256_init(&ctx_sha);
sph_sha256 (&ctx_sha, (const void*) hash, 64);
sph_sha256_close(&ctx_sha, (void*) hash);
memcpy(output, hash, 32);
}

16
stratum/algos/x22i.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef X22I_H
#define X22I_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void x22i_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -942,7 +942,15 @@ yescrypt_kdf(const yescrypt_shared_t * shared, yescrypt_local_t * local,
{ {
HMAC_SHA256_CTX_Y ctx; HMAC_SHA256_CTX_Y ctx;
HMAC_SHA256_Init_Y(&ctx, buf, buflen); HMAC_SHA256_Init_Y(&ctx, buf, buflen);
if (r == 32) { // yescryptR32
HMAC_SHA256_Update_Y(&ctx, "WaviBanana", 10);
} else
if (r == 16) { // yescryptR16
HMAC_SHA256_Update_Y(&ctx, "Client Key", 10);
}
else { // yescrypt
HMAC_SHA256_Update_Y(&ctx, salt, saltlen); HMAC_SHA256_Update_Y(&ctx, salt, saltlen);
}
HMAC_SHA256_Final_Y((uint8_t *)sha256, &ctx); HMAC_SHA256_Final_Y((uint8_t *)sha256, &ctx);
} }
/* Compute StoredKey */ /* Compute StoredKey */

View file

@ -327,14 +327,10 @@ static int yescrypt_bsty(const uint8_t * passwd, size_t passwdlen,
const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p, const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
uint8_t * buf, size_t buflen) uint8_t * buf, size_t buflen)
{ {
static __thread int initialized = 0; yescrypt_shared_t shared;
static __thread yescrypt_shared_t shared; yescrypt_local_t local;
static __thread yescrypt_local_t local;
int retval; int retval;
if (!initialized) {
/* "shared" could in fact be shared, but it's simpler to keep it private
* along with "local". It's dummy and tiny anyway. */
if (yescrypt_init_shared(&shared, NULL, 0, if (yescrypt_init_shared(&shared, NULL, 0,
0, 0, 0, YESCRYPT_SHARED_DEFAULTS, 0, NULL, 0)) 0, 0, 0, YESCRYPT_SHARED_DEFAULTS, 0, NULL, 0))
return -1; return -1;
@ -342,20 +338,14 @@ static int yescrypt_bsty(const uint8_t * passwd, size_t passwdlen,
yescrypt_free_shared(&shared); yescrypt_free_shared(&shared);
return -1; return -1;
} }
initialized = 1;
}
retval = yescrypt_kdf(&shared, &local, retval = yescrypt_kdf(&shared, &local,
passwd, passwdlen, salt, saltlen, N, r, p, 0, YESCRYPT_FLAGS, passwd, passwdlen, salt, saltlen, N, r, p, 0, YESCRYPT_FLAGS,
buf, buflen); buf, buflen);
#if 0
if (yescrypt_free_local(&local)) { yescrypt_free_local(&local);
yescrypt_free_shared(&shared); yescrypt_free_shared(&shared);
return -1;
}
if (yescrypt_free_shared(&shared))
return -1;
initialized = 0;
#endif
return retval; return retval;
} }
@ -364,3 +354,13 @@ void yescrypt_hash(const char *input, char *output, uint32_t len)
{ {
yescrypt_bsty((uint8_t*)input, len, (uint8_t*)input, len, 2048, 8, 1, (uint8_t*)output, 32); yescrypt_bsty((uint8_t*)input, len, (uint8_t*)input, len, 2048, 8, 1, (uint8_t*)output, 32);
} }
void yescryptR16_hash(const char *input, char *output, uint32_t len)
{
yescrypt_bsty((uint8_t*)input, len, (uint8_t*)input, len, 4096, 16, 1, (uint8_t*)output, 32);
}
void yescryptR32_hash(const char *input, char *output, uint32_t len)
{
yescrypt_bsty((uint8_t*)input, len, (uint8_t*)input, len, 4096, 32, 1, (uint8_t*)output, 32);
}

View file

@ -39,6 +39,8 @@ extern "C" {
#include <stdlib.h> /* for size_t */ #include <stdlib.h> /* for size_t */
void yescrypt_hash(const char* input, char* output, uint32_t len); void yescrypt_hash(const char* input, char* output, uint32_t len);
void yescryptR16_hash(const char* input, char* output, uint32_t len);
void yescryptR32_hash(const char* input, char* output, uint32_t len);
/** /**
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):

View file

@ -96,3 +96,19 @@ bool base58_decode(const char *input, char *output)
return true; return true;
} }
bool is_base58(char *input)
{
// All alphanumeric characters except "0", "O", "I" and "l"
size_t i=0, len = strlen(input);
char *c = input;
while (i < len) {
bool isdigit = (c[i] >= '1' && c[i] <= '9');
bool isalpha = (c[i] >= 'a' && c[i] <= 'z') || (c[i] >= 'A' && c[i] <= 'Z');
if (!isdigit && !isalpha) return false;
if (c[i] == 'I' || c[i] == 'O' || c[i] == 'l') return false;
i++;
}
return true;
}

View file

@ -1,8 +1,6 @@
#include "stratum.h" #include "stratum.h"
//#define CLIENT_DEBUGLOG_
bool client_suggest_difficulty(YAAMP_CLIENT *client, json_value *json_params) bool client_suggest_difficulty(YAAMP_CLIENT *client, json_value *json_params)
{ {
if(json_params->u.array.length>0) if(json_params->u.array.length>0)
@ -47,8 +45,8 @@ bool client_subscribe(YAAMP_CLIENT *client, json_value *json_params)
if(json_params->u.array.length>0) if(json_params->u.array.length>0)
{ {
if (json_params->u.array.values[0]->u.string.ptr)
strncpy(client->version, json_params->u.array.values[0]->u.string.ptr, 1023); strncpy(client->version, json_params->u.array.values[0]->u.string.ptr, 1023);
// if(!strcmp(client->version, "stratum-proxy/0.0.1")) return false;
if(strstr(client->version, "NiceHash") || strstr(client->version, "proxy") || strstr(client->version, "/3.")) if(strstr(client->version, "NiceHash") || strstr(client->version, "proxy") || strstr(client->version, "/3."))
client->reconnectable = false; client->reconnectable = false;
@ -88,9 +86,9 @@ bool client_subscribe(YAAMP_CLIENT *client, json_value *json_params)
memcpy(client->job_history, client1->job_history, sizeof(client->job_history)); memcpy(client->job_history, client1->job_history, sizeof(client->job_history));
client1->lock_count = 0; client1->lock_count = 0;
#ifdef CLIENT_DEBUGLOG_ if (g_debuglog_client) {
debuglog("reconnecting client locked to %x\n", client->jobid_next); debuglog("reconnecting client locked to %x\n", client->jobid_next);
#endif }
} }
else else
@ -106,9 +104,9 @@ bool client_subscribe(YAAMP_CLIENT *client, json_value *json_params)
memcpy(client->job_history, client1->job_history, sizeof(client->job_history)); memcpy(client->job_history, client1->job_history, sizeof(client->job_history));
client1->lock_count = 0; client1->lock_count = 0;
#ifdef CLIENT_DEBUGLOG_ if (g_debuglog_client) {
debuglog("reconnecting2 client\n"); debuglog("reconnecting2 client\n");
#endif }
} }
} }
} }
@ -116,9 +114,9 @@ bool client_subscribe(YAAMP_CLIENT *client, json_value *json_params)
strcpy(client->extranonce1_last, client->extranonce1); strcpy(client->extranonce1_last, client->extranonce1);
client->extranonce2size_last = client->extranonce2size; client->extranonce2size_last = client->extranonce2size;
#ifdef CLIENT_DEBUGLOG_ if (g_debuglog_client) {
debuglog("new client with nonce %s\n", client->extranonce1); debuglog("new client with nonce %s\n", client->extranonce1);
#endif }
client_send_result(client, "[[[\"mining.set_difficulty\",\"%.3g\"],[\"mining.notify\",\"%s\"]],\"%s\",%d]", client_send_result(client, "[[[\"mining.set_difficulty\",\"%.3g\"],[\"mining.notify\",\"%s\"]],\"%s\",%d]",
client->difficulty_actual, client->notify_id, client->extranonce1, client->extranonce2size); client->difficulty_actual, client->notify_id, client->extranonce1, client->extranonce2size);
@ -197,7 +195,14 @@ bool client_validate_user_address(YAAMP_CLIENT *client)
bool client_authorize(YAAMP_CLIENT *client, json_value *json_params) bool client_authorize(YAAMP_CLIENT *client, json_value *json_params)
{ {
if(json_params->u.array.length>1)
if(g_list_client.Find(client)) {
clientlog(client, "Already logged");
client_send_error(client, 21, "Already logged");
return false;
}
if(json_params->u.array.length>1 && json_params->u.array.values[1]->u.string.ptr)
strncpy(client->password, json_params->u.array.values[1]->u.string.ptr, 1023); strncpy(client->password, json_params->u.array.values[1]->u.string.ptr, 1023);
if (g_list_client.count >= g_stratum_max_cons) { if (g_list_client.count >= g_stratum_max_cons) {
@ -205,7 +210,7 @@ bool client_authorize(YAAMP_CLIENT *client, json_value *json_params)
return false; return false;
} }
if(json_params->u.array.length>0) if(json_params->u.array.length>0 && json_params->u.array.values[0]->u.string.ptr)
{ {
strncpy(client->username, json_params->u.array.values[0]->u.string.ptr, 1023); strncpy(client->username, json_params->u.array.values[0]->u.string.ptr, 1023);
@ -224,14 +229,19 @@ bool client_authorize(YAAMP_CLIENT *client, json_value *json_params)
} }
} }
if (!is_base58(client->username)) {
clientlog(client, "bad mining address %s", client->username);
return false;
}
bool reset = client_initialize_multialgo(client); bool reset = client_initialize_multialgo(client);
if(reset) return false; if(reset) return false;
client_initialize_difficulty(client); client_initialize_difficulty(client);
#ifdef CLIENT_DEBUGLOG_ if (g_debuglog_client) {
debuglog("new client %s, %s, %s\n", client->username, client->password, client->version); debuglog("new client %s, %s, %s\n", client->username, client->password, client->version);
#endif }
if(!client->userid || !client->workerid) if(!client->userid || !client->workerid)
{ {
@ -281,7 +291,7 @@ bool client_authorize(YAAMP_CLIENT *client, json_value *json_params)
bool client_update_block(YAAMP_CLIENT *client, json_value *json_params) bool client_update_block(YAAMP_CLIENT *client, json_value *json_params)
{ {
// password, id, block hash // password, id, block hash
if(json_params->u.array.length < 3) if(json_params->u.array.length < 3 || !json_params->u.array.values[0]->u.string.ptr)
{ {
clientlog(client, "update block, bad params"); clientlog(client, "update block, bad params");
return false; return false;
@ -293,14 +303,18 @@ bool client_update_block(YAAMP_CLIENT *client, json_value *json_params)
return false; return false;
} }
YAAMP_COIND *coind = (YAAMP_COIND *)object_find(&g_list_coind, json_params->u.array.values[1]->u.integer, true); int coinid = json_params->u.array.values[1]->u.integer;
if(!coinid) return false;
YAAMP_COIND *coind = (YAAMP_COIND *)object_find(&g_list_coind, coinid, true);
if(!coind) return false; if(!coind) return false;
const char* hash = json_params->u.array.values[2]->u.string.ptr; const char* hash = json_params->u.array.values[2]->u.string.ptr;
#ifdef CLIENT_DEBUGLOG_ if (g_debuglog_client) {
debuglog("notify: new %s block %s\n", coind->symbol, hash); debuglog("notify: new %s block %s\n", coind->symbol, hash);
#endif }
snprintf(coind->lastnotifyhash, 161, "%s", hash);
coind->newblock = true; coind->newblock = true;
coind->notreportingcounter = 0; coind->notreportingcounter = 0;
@ -541,6 +555,10 @@ void *client_thread(void *p)
client->id_int = json_get_int(json, "id"); client->id_int = json_get_int(json, "id");
client->id_str = json_get_string(json, "id"); client->id_str = json_get_string(json, "id");
if (client->id_str && strlen(client->id_str) > 32) {
clientlog(client, "bad id");
break;
}
const char *method = json_get_string(json, "method"); const char *method = json_get_string(json, "method");
@ -567,9 +585,9 @@ void *client_thread(void *p)
break; break;
} }
#ifdef CLIENT_DEBUGLOG_ if (g_debuglog_client) {
debuglog("client %s %d %s\n", method, client->id_int, client->id_str? client->id_str: "null"); debuglog("client %s %d %s\n", method, client->id_int, client->id_str? client->id_str: "null");
#endif }
bool b = false; bool b = false;
if(!strcmp(method, "mining.subscribe")) if(!strcmp(method, "mining.subscribe"))
@ -608,9 +626,7 @@ void *client_thread(void *p)
else if(!strcmp(method, "getwork")) else if(!strcmp(method, "getwork"))
{ {
clientlog(client, "using getwork"); // client using http:// url clientlog(client, "using getwork"); // client using http:// url
break;
} }
else else
{ {
b = client_send_error(client, 20, "Not supported"); b = client_send_error(client, 20, "Not supported");
@ -625,10 +641,10 @@ void *client_thread(void *p)
// source_close(client->source); // source_close(client->source);
#ifdef CLIENT_DEBUGLOG_ if (g_debuglog_client) {
debuglog("client terminate\n"); debuglog("client terminate\n");
#endif }
if(!client || client->deleted) { if(!client) {
pthread_exit(NULL); pthread_exit(NULL);
} }
@ -646,9 +662,12 @@ void *client_thread(void *p)
db_clear_worker(g_db, client); db_clear_worker(g_db, client);
CommonUnlock(&g_db_mutex); CommonUnlock(&g_db_mutex);
} }
}
object_delete(client); object_delete(client);
} else {
// only clients sockets in g_list_client are purged (if marked deleted)
socket_close(client->sock);
delete client;
}
pthread_exit(NULL); pthread_exit(NULL);
} }

View file

@ -3,10 +3,10 @@
double client_normalize_difficulty(double difficulty) double client_normalize_difficulty(double difficulty)
{ {
if(difficulty <= 0.001) difficulty = 0.001; if(difficulty < g_stratum_min_diff) difficulty = g_stratum_min_diff;
else if(difficulty < 1) difficulty = floor(difficulty*1000/2)/1000*2; else if(difficulty < 1) difficulty = floor(difficulty*1000/2)/1000*2;
else if(difficulty > 1) difficulty = floor(difficulty/2)*2; else if(difficulty > 1) difficulty = floor(difficulty/2)*2;
if(difficulty > g_stratum_max_diff) difficulty = g_stratum_max_diff;
return difficulty; return difficulty;
} }
@ -48,13 +48,12 @@ void client_change_difficulty(YAAMP_CLIENT *client, double difficulty)
void client_adjust_difficulty(YAAMP_CLIENT *client) void client_adjust_difficulty(YAAMP_CLIENT *client)
{ {
if(client->difficulty_remote) if(client->difficulty_remote) {
{
client_change_difficulty(client, client->difficulty_remote); client_change_difficulty(client, client->difficulty_remote);
return; return;
} }
if(client->shares_per_minute > 600) if(client->shares_per_minute > 100)
client_change_difficulty(client, client->difficulty_actual*4); client_change_difficulty(client, client->difficulty_actual*4);
else if(client->difficulty_fixed) else if(client->difficulty_fixed)
@ -79,6 +78,7 @@ int client_send_difficulty(YAAMP_CLIENT *client, double difficulty)
client_call(client, "mining.set_difficulty", "[%.0f]", difficulty); client_call(client, "mining.set_difficulty", "[%.0f]", difficulty);
else else
client_call(client, "mining.set_difficulty", "[%.3f]", difficulty); client_call(client, "mining.set_difficulty", "[%.3f]", difficulty);
return 0;
} }
void client_initialize_difficulty(YAAMP_CLIENT *client) void client_initialize_difficulty(YAAMP_CLIENT *client)

View file

@ -4,7 +4,6 @@
uint64_t lyra2z_height = 0; uint64_t lyra2z_height = 0;
//#define MERKLE_DEBUGLOG //#define MERKLE_DEBUGLOG
//#define HASH_DEBUGLOG_
//#define DONTSUBMIT //#define DONTSUBMIT
void build_submit_values(YAAMP_JOB_VALUES *submitvalues, YAAMP_JOB_TEMPLATE *templ, void build_submit_values(YAAMP_JOB_VALUES *submitvalues, YAAMP_JOB_TEMPLATE *templ,
@ -32,10 +31,14 @@ void build_submit_values(YAAMP_JOB_VALUES *submitvalues, YAAMP_JOB_TEMPLATE *tem
#ifdef MERKLE_DEBUGLOG #ifdef MERKLE_DEBUGLOG
printf("merkle root %s\n", merkleroot.c_str()); printf("merkle root %s\n", merkleroot.c_str());
#endif #endif
if (!strcmp(g_current_algo->name, "lbry")) { if (!strcmp(g_stratum_algo, "lbry")) {
sprintf(submitvalues->header, "%s%s%s%s%s%s%s", templ->version, templ->prevhash_be, submitvalues->merkleroot_be, sprintf(submitvalues->header, "%s%s%s%s%s%s%s", templ->version, templ->prevhash_be, submitvalues->merkleroot_be,
templ->claim_be, ntime, templ->nbits, nonce); templ->claim_be, ntime, templ->nbits, nonce);
ser_string_be(submitvalues->header, submitvalues->header_be, 32 + 20); ser_string_be(submitvalues->header, submitvalues->header_be, 112/4);
} else if (strlen(templ->extradata_be) == 128) { // LUX SC
sprintf(submitvalues->header, "%s%s%s%s%s%s%s", templ->version, templ->prevhash_be, submitvalues->merkleroot_be,
ntime, templ->nbits, nonce, templ->extradata_be);
ser_string_be(submitvalues->header, submitvalues->header_be, 36); // 80+64 / sizeof(u32)
} else { } else {
sprintf(submitvalues->header, "%s%s%s%s%s%s", templ->version, templ->prevhash_be, submitvalues->merkleroot_be, sprintf(submitvalues->header, "%s%s%s%s%s%s", templ->version, templ->prevhash_be, submitvalues->merkleroot_be,
ntime, templ->nbits, nonce); ntime, templ->nbits, nonce);
@ -215,12 +218,18 @@ static void client_do_submit(YAAMP_CLIENT *client, YAAMP_JOB *job, YAAMP_JOB_VAL
if(hash_int <= coin_target) if(hash_int <= coin_target)
{ {
char count_hex[8] = { 0 };
if (templ->txcount <= 252)
sprintf(count_hex, "%02x", templ->txcount & 0xFF);
else
sprintf(count_hex, "fd%02x%02x", templ->txcount & 0xFF, templ->txcount >> 8);
memset(block_hex, 0, block_size); memset(block_hex, 0, block_size);
sprintf(block_hex, "%s%02x%s", submitvalues->header_be, (unsigned char)templ->txcount, submitvalues->coinbase); sprintf(block_hex, "%s%s%s", submitvalues->header_be, count_hex, submitvalues->coinbase);
if (g_current_algo->name && !strcmp("jha", g_current_algo->name)) { if (g_current_algo->name && !strcmp("jha", g_current_algo->name)) {
// block header of 88 bytes // block header of 88 bytes
sprintf(block_hex, "%s8400000008000000%02x%s", submitvalues->header_be, (unsigned char)templ->txcount, submitvalues->coinbase); sprintf(block_hex, "%s8400000008000000%s%s", submitvalues->header_be, count_hex, submitvalues->coinbase);
} }
vector<string>::const_iterator i; vector<string>::const_iterator i;
@ -272,27 +281,29 @@ static void client_do_submit(YAAMP_CLIENT *client, YAAMP_JOB *job, YAAMP_JOB_VAL
target_to_diff(coin_target), target_to_diff(hash_int), target_to_diff(coin_target), target_to_diff(hash_int),
hash1, submitvalues->hash_be, templ->has_segwit_txs); hash1, submitvalues->hash_be, templ->has_segwit_txs);
if(coind->noblocknotify) { if(!strcmp("DCR", coind->rpcencoding)) {
// DCR go wallet doesnt handle blocknotify= config (yet) // delay between dcrd and dcrwallet
// required to store the user id and the user diff
sleep(1); sleep(1);
}
if(!strcmp(coind->lastnotifyhash,submitvalues->hash_be)) {
block_confirm(coind->id, submitvalues->hash_be); block_confirm(coind->id, submitvalues->hash_be);
} }
#ifdef HASH_DEBUGLOG_ if (g_debuglog_hash) {
debuglog("--------------------------------------------------------------\n"); debuglog("--------------------------------------------------------------\n");
debuglog("hash1 %s\n", hash1); debuglog("hash1 %s\n", hash1);
debuglog("hash2 %s\n", submitvalues->hash_be); debuglog("hash2 %s\n", submitvalues->hash_be);
#endif }
} }
else { else {
debuglog("*** REJECTED :( %s block %d %d txs\n", coind->name, templ->height, templ->txcount); debuglog("*** REJECTED :( %s block %d %d txs\n", coind->name, templ->height, templ->txcount);
rejectlog("REJECTED %s block %d\n", coind->symbol, templ->height); rejectlog("REJECTED %s block %d\n", coind->symbol, templ->height);
#ifdef HASH_DEBUGLOG_ if (g_debuglog_hash) {
//debuglog("block %s\n", block_hex); //debuglog("block %s\n", block_hex);
debuglog("--------------------------------------------------------------\n"); debuglog("--------------------------------------------------------------\n");
#endif }
} }
} }
@ -318,9 +329,9 @@ void client_submit_error(YAAMP_CLIENT *client, YAAMP_JOB *job, int id, const cha
share_add(client, job, false, extranonce2, ntime, nonce, 0, id); share_add(client, job, false, extranonce2, ntime, nonce, 0, id);
client->submit_bad++; client->submit_bad++;
#ifdef HASH_DEBUGLOG_ if (g_debuglog_hash) {
dump_submit_debug(message, client, job, extranonce2, ntime, nonce); dump_submit_debug(message, client, job, extranonce2, ntime, nonce);
#endif }
} }
object_unlock(job); object_unlock(job);
@ -332,33 +343,37 @@ static bool ntime_valid_range(const char ntimehex[])
uint32_t ntime = 0; uint32_t ntime = 0;
if (strlen(ntimehex) != 8) return false; if (strlen(ntimehex) != 8) return false;
sscanf(ntimehex, "%8x", &ntime); sscanf(ntimehex, "%8x", &ntime);
if (ntime < 0x57000000 || ntime > 0x60000000) // 14 Jan 2021 if (ntime < 0x5b000000 || ntime > 0x60000000) // 14 Jan 2021
ntime = bswap32(ntime); // just in case... return false;
time(&rawtime); time(&rawtime);
return ((rawtime - ntime) < (23 * 60 * 60)); return (abs(rawtime - ntime) < (30 * 60));
}
static bool valid_string_params(json_value *json_params)
{
for(int p=0; p < json_params->u.array.length; p++) {
if (!json_is_string(json_params->u.array.values[p]))
return false;
}
return true;
} }
bool client_submit(YAAMP_CLIENT *client, json_value *json_params) bool client_submit(YAAMP_CLIENT *client, json_value *json_params)
{ {
// submit(worker_name, jobid, extranonce2, ntime, nonce): // submit(worker_name, jobid, extranonce2, ntime, nonce):
if(json_params->u.array.length<5) if(json_params->u.array.length<5 || !valid_string_params(json_params)) {
{
debuglog("%s - %s bad message\n", client->username, client->sock->ip); debuglog("%s - %s bad message\n", client->username, client->sock->ip);
client->submit_bad++; client->submit_bad++;
return false; return false;
} }
char extranonce2[32]; char extranonce2[32] = { 0 };
char ntime[32]; char extra[160] = { 0 };
char nonce[32]; char nonce[80] = { 0 };
char vote[8]; char ntime[32] = { 0 };
char vote[8] = { 0 };
memset(extranonce2, 0, 32); if (strlen(json_params->u.array.values[1]->u.string.ptr) > 32) {
memset(ntime, 0, 32);
memset(nonce, 0, 32);
memset(vote, 0, 8);
if (!json_params->u.array.values[1]->u.string.ptr || strlen(json_params->u.array.values[1]->u.string.ptr) > 32) {
clientlog(client, "bad json, wrong jobid len"); clientlog(client, "bad json, wrong jobid len");
client->submit_bad++; client->submit_bad++;
return false; return false;
@ -368,17 +383,27 @@ bool client_submit(YAAMP_CLIENT *client, json_value *json_params)
strncpy(extranonce2, json_params->u.array.values[2]->u.string.ptr, 31); strncpy(extranonce2, json_params->u.array.values[2]->u.string.ptr, 31);
strncpy(ntime, json_params->u.array.values[3]->u.string.ptr, 31); strncpy(ntime, json_params->u.array.values[3]->u.string.ptr, 31);
strncpy(nonce, json_params->u.array.values[4]->u.string.ptr, 31); strncpy(nonce, json_params->u.array.values[4]->u.string.ptr, 31);
if (json_params->u.array.length == 6)
strncpy(vote, json_params->u.array.values[5]->u.string.ptr, 7);
#ifdef HASH_DEBUGLOG_
debuglog("submit %s (uid %d) %d, %s, %s, %s\n", client->sock->ip, client->userid, jobid, extranonce2, ntime, nonce);
#endif
string_lower(extranonce2); string_lower(extranonce2);
string_lower(ntime); string_lower(ntime);
string_lower(nonce); string_lower(nonce);
if (json_params->u.array.length == 6) {
if (strstr(g_stratum_algo, "phi")) {
// lux optional field, smart contral root hashes (not mandatory on shares submit)
strncpy(extra, json_params->u.array.values[5]->u.string.ptr, 128);
string_lower(extra);
} else {
// heavycoin vote
strncpy(vote, json_params->u.array.values[5]->u.string.ptr, 7);
string_lower(vote); string_lower(vote);
}
}
if (g_debuglog_hash) {
debuglog("submit %s (uid %d) %d, %s, t=%s, n=%s, extra=%s\n", client->sock->ip, client->userid,
jobid, extranonce2, ntime, nonce, extra);
}
YAAMP_JOB *job = (YAAMP_JOB *)object_find(&g_list_job, jobid, true); YAAMP_JOB *job = (YAAMP_JOB *)object_find(&g_list_job, jobid, true);
if(!job) if(!job)
@ -399,15 +424,14 @@ bool client_submit(YAAMP_CLIENT *client, json_value *json_params)
YAAMP_JOB_TEMPLATE *templ = job->templ; YAAMP_JOB_TEMPLATE *templ = job->templ;
if(strlen(nonce) != YAAMP_NONCE_SIZE*2) if(strlen(nonce) != YAAMP_NONCE_SIZE*2 || !ishexa(nonce, YAAMP_NONCE_SIZE*2)) {
{
client_submit_error(client, job, 20, "Invalid nonce size", extranonce2, ntime, nonce); client_submit_error(client, job, 20, "Invalid nonce size", extranonce2, ntime, nonce);
return true; return true;
} }
if(strcmp(ntime, templ->ntime)) if(strcmp(ntime, templ->ntime))
{ {
if (!ntime_valid_range(ntime)) { if (!ishexa(ntime, 8) || !ntime_valid_range(ntime)) {
client_submit_error(client, job, 23, "Invalid time rolling", extranonce2, ntime, nonce); client_submit_error(client, job, 23, "Invalid time rolling", extranonce2, ntime, nonce);
return true; return true;
} }
@ -444,18 +468,20 @@ bool client_submit(YAAMP_CLIENT *client, json_value *json_params)
if (extranull) { if (extranull) {
debuglog("extranonce %s is empty!, should be %s - %s\n", extranonce2, extra1_id, client->sock->ip); debuglog("extranonce %s is empty!, should be %s - %s\n", extranonce2, extra1_id, client->sock->ip);
client_submit_error(client, job, 27, "Invalid extranonce2 suffix", extranonce2, ntime, nonce); client_submit_error(client, job, 27, "Invalid extranonce2 suffix", extranonce2, ntime, nonce);
client->submit_bad++;
return true; return true;
} }
if (extradiff) { if (extradiff) {
// some ccminer pre-release doesn't fill correctly the extranonce // some ccminer pre-release doesn't fill correctly the extranonce
client_submit_error(client, job, 27, "Invalid extranonce2 suffix", extranonce2, ntime, nonce); client_submit_error(client, job, 27, "Invalid extranonce2 suffix", extranonce2, ntime, nonce);
client->submit_bad++;
socket_send(client->sock, "{\"id\":null,\"method\":\"mining.set_extranonce\",\"params\":[\"%s\",%d]}\n", socket_send(client->sock, "{\"id\":null,\"method\":\"mining.set_extranonce\",\"params\":[\"%s\",%d]}\n",
client->extranonce1, client->extranonce2size); client->extranonce1, client->extranonce2size);
return true; return true;
} }
} }
else if(!ishexa(extranonce2, client->extranonce2size*2)) {
client_submit_error(client, job, 27, "Invalid nonce2", extranonce2, ntime, nonce);
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -474,11 +500,11 @@ bool client_submit(YAAMP_CLIENT *client, json_value *json_params)
// minimum hash diff begins with 0000, for all... // minimum hash diff begins with 0000, for all...
uint8_t pfx = submitvalues.hash_bin[30] | submitvalues.hash_bin[31]; uint8_t pfx = submitvalues.hash_bin[30] | submitvalues.hash_bin[31];
if(pfx) { if(pfx) {
#ifdef HASH_DEBUGLOG_ if (g_debuglog_hash) {
debuglog("Possible %s error, hash starts with %02x%02x%02x%02x\n", g_current_algo->name, debuglog("Possible %s error, hash starts with %02x%02x%02x%02x\n", g_current_algo->name,
(int) submitvalues.hash_bin[31], (int) submitvalues.hash_bin[30], (int) submitvalues.hash_bin[31], (int) submitvalues.hash_bin[30],
(int) submitvalues.hash_bin[29], (int) submitvalues.hash_bin[28]); (int) submitvalues.hash_bin[29], (int) submitvalues.hash_bin[28]);
#endif }
client_submit_error(client, job, 25, "Invalid share", extranonce2, ntime, nonce); client_submit_error(client, job, 25, "Invalid share", extranonce2, ntime, nonce);
return true; return true;
} }
@ -488,11 +514,11 @@ bool client_submit(YAAMP_CLIENT *client, json_value *json_params)
uint64_t coin_target = decode_compact(templ->nbits); uint64_t coin_target = decode_compact(templ->nbits);
if (templ->nbits && !coin_target) coin_target = 0xFFFF000000000000ULL; if (templ->nbits && !coin_target) coin_target = 0xFFFF000000000000ULL;
#ifdef HASH_DEBUGLOG_ if (g_debuglog_hash) {
debuglog("%016llx actual\n", hash_int); debuglog("%016llx actual\n", hash_int);
debuglog("%016llx target\n", user_target); debuglog("%016llx target\n", user_target);
debuglog("%016llx coin\n", coin_target); debuglog("%016llx coin\n", coin_target);
#endif }
if(hash_int > user_target && hash_int > coin_target) if(hash_int > user_target && hash_int > coin_target)
{ {
client_submit_error(client, job, 26, "Low difficulty share", extranonce2, ntime, nonce); client_submit_error(client, job, 26, "Low difficulty share", extranonce2, ntime, nonce);
@ -518,12 +544,12 @@ bool client_submit(YAAMP_CLIENT *client, json_value *json_params)
// share_diff = share_diff / g_current_algo->diff_multiplier; // share_diff = share_diff / g_current_algo->diff_multiplier;
// } // }
#ifndef HASH_DEBUGLOG_ if (g_debuglog_hash) {
// only log a few... // only log a few...
if (share_diff > (client->difficulty_actual * 16)) if (share_diff > (client->difficulty_actual * 16))
debuglog("submit %s (uid %d) %d, %s, %s, %s, %.3f/%.3f\n", client->sock->ip, client->userid, debuglog("submit %s (uid %d) %d, %s, %s, %s, %.3f/%.3f\n", client->sock->ip, client->userid,
jobid, extranonce2, ntime, nonce, share_diff, client->difficulty_actual); jobid, extranonce2, ntime, nonce, share_diff, client->difficulty_actual);
#endif }
share_add(client, job, true, extranonce2, ntime, nonce, share_diff, 0); share_add(client, job, true, extranonce2, ntime, nonce, share_diff, 0);
object_unlock(job); object_unlock(job);

View file

@ -14,12 +14,30 @@ static void encode_tx_value(char *encoded, json_int_t value)
TX_VALUE(value, 32), TX_VALUE(value, 40), TX_VALUE(value, 48), TX_VALUE(value, 56)); TX_VALUE(value, 32), TX_VALUE(value, 40), TX_VALUE(value, 48), TX_VALUE(value, 56));
} }
static void p2sh_pack_tx(YAAMP_COIND *coind, char *data, json_int_t amount, char *payee)
{
char evalue[32];
char coinb2_part[256];
char coinb2_len[4];
sprintf(coinb2_part, "a9%02x%s87", (unsigned int)(strlen(payee) >> 1) & 0xFF, payee);
sprintf(coinb2_len, "%02x", (unsigned int)(strlen(coinb2_part) >> 1) & 0xFF);
encode_tx_value(evalue, amount);
strcat(data, evalue);
strcat(data, coinb2_len);
strcat(data, coinb2_part);
}
static void job_pack_tx(YAAMP_COIND *coind, char *data, json_int_t amount, char *key) static void job_pack_tx(YAAMP_COIND *coind, char *data, json_int_t amount, char *key)
{ {
int ol = strlen(data); int ol = strlen(data);
char evalue[32]; char evalue[32];
encode_tx_value(evalue, amount);
if(coind->p2sh_address && !key) {
p2sh_pack_tx(coind, data, amount, coind->script_pubkey);
return;
}
encode_tx_value(evalue, amount);
sprintf(data+strlen(data), "%s", evalue); sprintf(data+strlen(data), "%s", evalue);
if(coind->pos && !key) if(coind->pos && !key)
@ -104,6 +122,69 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value *
if (strlen(coind->charity_address) == 0) if (strlen(coind->charity_address) == 0)
sprintf(coind->charity_address, "EdFwYw4Mo2Zq6CFM2yNJgXvE2DTJxgdBRX"); sprintf(coind->charity_address, "EdFwYw4Mo2Zq6CFM2yNJgXvE2DTJxgdBRX");
} }
else if(strcmp(coind->symbol, "DYN") == 0)
{
char script_dests[2048] = { 0 };
char script_payee[128] = { 0 };
char payees[3];
int npayees = (templ->has_segwit_txs) ? 2 : 1;
bool dynode_enabled;
dynode_enabled = json_get_bool(json_result, "dynode_payments_enforced");
bool superblocks_enabled = json_get_bool(json_result, "superblocks_enabled");
json_value* superblock = json_get_array(json_result, "superblock");
json_value* dynode;
dynode = json_get_object(json_result, "dynode");
if(!dynode && json_get_bool(json_result, "dynode_payments")) {
coind->oldmasternodes = true;
debuglog("%s is using old dynodes rpc keys\n", coind->symbol);
return;
}
if(superblocks_enabled && superblock) {
for(int i = 0; i < superblock->u.array.length; i++) {
const char *payee = json_get_string(superblock->u.array.values[i], "payee");
json_int_t amount = json_get_int(superblock->u.array.values[i], "amount");
if (payee && amount) {
npayees++;
available -= amount;
base58_decode(payee, script_payee);
job_pack_tx(coind, script_dests, amount, script_payee);
//debuglog("%s superblock found %s %u\n", coind->symbol, payee, amount);
}
}
}
if (dynode_enabled && dynode) {
bool started;
started = json_get_bool(json_result, "dynode_payments_started");
const char *payee = json_get_string(dynode, "payee");
json_int_t amount = json_get_int(dynode, "amount");
if (!payee)
debuglog("coinbase_create failed to get Dynode payee\n");
if (!amount)
debuglog("coinbase_create failed to get Dynode amount\n");
if (!started)
debuglog("coinbase_create failed to get Dynode started\n");
if (payee && amount && started) {
npayees++;
available -= amount;
base58_decode(payee, script_payee);
job_pack_tx(coind, script_dests, amount, script_payee);
//debuglog("%s dynode found %s %u\n", coind->symbol, payee, amount);
}
}
sprintf(payees, "%02x", npayees);
strcat(templ->coinb2, payees);
if (templ->has_segwit_txs) strcat(templ->coinb2, commitment);
strcat(templ->coinb2, script_dests);
job_pack_tx(coind, templ->coinb2, available, NULL);
strcat(templ->coinb2, "00000000"); // locktime
coind->reward = (double)available/100000000*coind->reward_mul;
//debuglog("%s %d dests %s\n", coind->symbol, npayees, script_dests);
return;
}
else if(strcmp(coind->symbol, "LTCR") == 0) { else if(strcmp(coind->symbol, "LTCR") == 0) {
if (coind->charity_percent <= 0) if (coind->charity_percent <= 0)
coind->charity_percent = 10; coind->charity_percent = 10;
@ -145,9 +226,155 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value *
if (strlen(coind->charity_address) == 0 && !strcmp(coind->symbol, "DCR")) if (strlen(coind->charity_address) == 0 && !strcmp(coind->symbol, "DCR"))
sprintf(coind->charity_address, "Dcur2mcGjmENx4DhNqDctW5wJCVyT3Qeqkx"); sprintf(coind->charity_address, "Dcur2mcGjmENx4DhNqDctW5wJCVyT3Qeqkx");
} }
else if(strcmp(coind->symbol, "STAK") == 0) {
char script_payee[512] = { 0 };
char payees[4];
int npayees = (templ->has_segwit_txs) ? 2 : 1;
bool masternode_payments = json_get_bool(json_result, "masternode_payments");
bool masternodes_enabled = json_get_bool(json_result, "enforce_masternode_payments");
if (masternodes_enabled && masternode_payments) {
const char *payee = json_get_string(json_result, "payee");
json_int_t amount = json_get_int(json_result, "payee_amount");
if (payee && amount)
++npayees;
}
//treasury 5% @ 10 STAK per block
json_int_t charity_amount = 50000000;
//testnet
//sprintf(coind->charity_address, "93ASJtDuVYVdKXemH9BrtSMscznvsp9stD");
switch (templ->height % 4) {
case 0: sprintf(coind->charity_address, "3K3bPrW5h7DYEMp2RcXawTCXajcm4ZU9Zh");
break;
case 1: sprintf(coind->charity_address, "33Ssxmn3ehVMgyxgegXhpLGSBpubPjLZQ6");
break;
case 2: sprintf(coind->charity_address, "3HFPNAjesiBY5sSVUmuBFnMEGut69R49ca");
break;
case 3: sprintf(coind->charity_address, "37jLjjfUXQU4bdqVzvpUXyzAqPQSmxyByi");
break;
}
++npayees;
available -= charity_amount;
base58_decode(coind->charity_address, script_payee);
sprintf(payees, "%02x", npayees);
strcat(templ->coinb2, payees);
if (templ->has_segwit_txs) strcat(templ->coinb2, commitment);
char echarity_amount[32];
encode_tx_value(echarity_amount, charity_amount);
strcat(templ->coinb2, echarity_amount);
char coinb2_part[1024] = { 0 };
char coinb2_len[3] = { 0 };
sprintf(coinb2_part, "a9%02x%s87", (unsigned int)(strlen(script_payee) >> 1) & 0xFF, script_payee);
sprintf(coinb2_len, "%02x", (unsigned int)(strlen(coinb2_part) >> 1) & 0xFF);
strcat(templ->coinb2, coinb2_len);
strcat(templ->coinb2, coinb2_part);
if (masternodes_enabled && masternode_payments) {
//duplicated: revisit ++todo
const char *payee = json_get_string(json_result, "payee");
json_int_t amount = json_get_int(json_result, "payee_amount");
if (payee && amount) {
available -= amount;
base58_decode(payee, script_payee);
job_pack_tx(coind, templ->coinb2, amount, script_payee);
}
}
job_pack_tx(coind, templ->coinb2, available, NULL);
strcat(templ->coinb2, "00000000"); // locktime
coind->reward = (double)available / 100000000 * coind->reward_mul;
return;
}
else if(strcmp(coind->symbol, "TUX") == 0) {
char script_payee[1024];
char charity_payee[256] = { 0 };
const char *payee = json_get_string(json_result, "donation_payee");
if(payee != NULL){
sprintf(coind->charity_address, "%s", payee);
} else {
sprintf(coind->charity_address, "%s", "");
}
if(strlen(coind->charity_address) > 0){
char script_payee[1024];
char charity_payee[256] = { 0 };
sprintf(charity_payee, "%s", coind->charity_address);
if (strlen(charity_payee) == 0)
stratumlog("ERROR %s has no charity_address set!\n", coind->name);
base58_decode(charity_payee, script_payee);
json_int_t charity_amount = json_get_int(json_result, "donation_amount");
coind->charity_amount = charity_amount;
if (templ->has_segwit_txs) {
strcat(templ->coinb2, "03"); // 3 outputs (nulldata + fees + miner)
strcat(templ->coinb2, commitment);
} else {
strcat(templ->coinb2, "02");
}
job_pack_tx(coind, templ->coinb2, available, NULL);
char echarity_amount[32];
encode_tx_value(echarity_amount, charity_amount);
strcat(templ->coinb2, echarity_amount);
char coinb2_part[1024] = { 0 };
char coinb2_len[3] = { 0 };
sprintf(coinb2_part, "a9%02x%s87", (unsigned int)(strlen(script_payee) >> 1) & 0xFF, script_payee);
sprintf(coinb2_len, "%02x", (unsigned int)(strlen(coinb2_part) >> 1) & 0xFF);
strcat(templ->coinb2, coinb2_len);
strcat(templ->coinb2, coinb2_part);
debuglog("pack tx %s\n", coinb2_part);
strcat(templ->coinb2, "00000000"); // locktime
coind->reward = (double)available/100000000*coind->reward_mul;
//debuglog("INFO %s block available %f, charity %f miner %f\n", coind->symbol,
// (double) available/1e8, (double) charity_amount/1e8, coind->reward);
return;
}
}
bool founder_enabled = json_get_bool(json_result, "founder_payments_started");
json_value* founder = json_get_object(json_result, "founder");
if (!coind->hasmasternodes && founder_enabled && founder) {
char founder_payee[256] = { 0 };
char founder_script[1024] = { 0};
const char *payee = json_get_string(founder, "payee");
bool founder_use_p2sh = (strcmp(coind->symbol, "PGN") == 0);
json_int_t amount = json_get_int(founder, "amount");
if(payee && amount) {
if (payee) snprintf(founder_payee, 255, "%s", payee);
if (strlen(founder_payee) == 0)
stratumlog("ERROR %s has no charity_address set!\n", coind->name);
base58_decode(founder_payee, founder_script);
available -= amount;
if (templ->has_segwit_txs) {
strcat(templ->coinb2, "03"); // 3 outputs (nulldata + fees + miner)
strcat(templ->coinb2, commitment);
} else {
strcat(templ->coinb2, "02");
}
job_pack_tx(coind, templ->coinb2, available, NULL);
if(founder_use_p2sh) {
p2sh_pack_tx(coind, templ->coinb2, amount, founder_script);
} else {
job_pack_tx(coind, templ->coinb2, amount, founder_script);
}
strcat(templ->coinb2, "00000000"); // locktime
coind->reward = (double)available/100000000*coind->reward_mul;
debuglog("%s founder address %s, amount %lld\n", coind->symbol,founder_payee, amount);
debuglog("%s founder script %s\n", coind->symbol,founder_script);
debuglog("%s scripts %s\n", coind->symbol, templ->coinb2);
return;
}
}
// 2 txs are required on these coins, one for foundation (dev fees) // 2 txs are required on these coins, one for foundation (dev fees)
if(coind->charity_percent) if(coind->charity_percent && !coind->hasmasternodes)
{ {
char script_payee[1024]; char script_payee[1024];
char charity_payee[256] = { 0 }; char charity_payee[256] = { 0 };
@ -159,7 +386,10 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value *
base58_decode(charity_payee, script_payee); base58_decode(charity_payee, script_payee);
json_int_t charity_amount = (available * coind->charity_percent) / 100; json_int_t charity_amount = json_get_int(json_result, "payee_amount");
if (charity_amount <= 0)
charity_amount = (available * coind->charity_percent) / 100;
available -= charity_amount; available -= charity_amount;
coind->charity_amount = charity_amount; coind->charity_amount = charity_amount;
@ -174,6 +404,8 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value *
strcat(templ->coinb2, "00000000"); // locktime strcat(templ->coinb2, "00000000"); // locktime
coind->reward = (double)available/100000000*coind->reward_mul; coind->reward = (double)available/100000000*coind->reward_mul;
//debuglog("INFO %s block available %f, charity %f miner %f\n", coind->symbol,
// (double) available/1e8, (double) charity_amount/1e8, coind->reward);
return; return;
} }
@ -213,24 +445,42 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value *
} }
} }
if(strcmp(coind->symbol, "SIB") == 0 || // most recent masternodes rpc (DASH, SIB, MUE, DSR, GBX...)
strcmp(coind->symbol, "MUE") == 0 || // MUEcore-x11 if(coind->hasmasternodes && !coind->oldmasternodes)
strcmp(coind->symbol, "VIVO") == 0 || // VIVO coin
strcmp(coind->symbol, "INN") == 0 || // Innova coin
strcmp(coind->symbol, "DSR") == 0 || // Desire coin
strcmp(coind->symbol, "ONEX") == 0 || // ONEX Cash
strcmp(coind->symbol, "GBX") == 0 || // GoByte
strcmp(coind->symbol, "KZC") == 0 || // KZ Cash
strcmp(coind->symbol, "DASH") == 0 || strcmp(coind->symbol, "DASH-TESTNET") == 0) // Dash 12.1
{ {
char script_dests[2048] = { 0 }; char script_dests[2048] = { 0 };
char script_payee[128] = { 0 }; char script_payee[128] = { 0 };
char payees[4]; // addresses count char payees[4]; // addresses count
int npayees = 1; int npayees = (templ->has_segwit_txs) ? 2 : 1;
bool masternode_enabled = json_get_bool(json_result, "masternode_payments_enforced"); bool masternode_enabled = json_get_bool(json_result, "masternode_payments_enforced");
bool superblocks_enabled = json_get_bool(json_result, "superblocks_enabled"); bool superblocks_enabled = json_get_bool(json_result, "superblocks_enabled");
json_value* superblock = json_get_array(json_result, "superblock"); json_value* superblock = json_get_array(json_result, "superblock");
json_value* masternode = json_get_object(json_result, "masternode"); json_value* masternode = json_get_object(json_result, "masternode");
if(!masternode && json_get_bool(json_result, "masternode_payments")) {
coind->oldmasternodes = true;
debuglog("%s is using old masternodes rpc keys\n", coind->symbol);
return;
}
if(coind->charity_percent) {
char charity_payee[256] = { 0 };
const char *payee = json_get_string(json_result, "payee");
if (payee) snprintf(charity_payee, 255, "%s", payee);
else sprintf(charity_payee, "%s", coind->charity_address);
if (strlen(charity_payee) == 0)
stratumlog("ERROR %s has no charity_address set!\n", coind->name);
json_int_t charity_amount = (available * coind->charity_percent) / 100;
npayees++;
available -= charity_amount;
coind->charity_amount = charity_amount;
base58_decode(charity_payee, script_payee);
job_pack_tx(coind, script_dests, charity_amount, script_payee);
}
// smart contracts balance refund, same format as DASH superblocks
json_value* screfund = json_get_array(json_result, "screfund");
if(screfund && screfund->u.array.length) {
superblocks_enabled = true;
superblock = screfund;
}
if(superblocks_enabled && superblock) { if(superblocks_enabled && superblock) {
for(int i = 0; i < superblock->u.array.length; i++) { for(int i = 0; i < superblock->u.array.length; i++) {
const char *payee = json_get_string(superblock->u.array.values[i], "payee"); const char *payee = json_get_string(superblock->u.array.values[i], "payee");
@ -239,27 +489,38 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value *
npayees++; npayees++;
available -= amount; available -= amount;
base58_decode(payee, script_payee); base58_decode(payee, script_payee);
bool superblock_use_p2sh = (strcmp(coind->symbol, "MAC") == 0);
if(superblock_use_p2sh)
p2sh_pack_tx(coind, script_dests, amount, script_payee);
else
job_pack_tx(coind, script_dests, amount, script_payee); job_pack_tx(coind, script_dests, amount, script_payee);
//debuglog("%s superblock %s %u\n", coind->symbol, payee, amount); //debuglog("%s superblock %s %u\n", coind->symbol, payee, amount);
} }
} }
} }
if (masternode_enabled && masternode) { if (masternode_enabled && masternode) {
bool started = json_get_bool(json_result, "masternode_payments_started");
const char *payee = json_get_string(masternode, "payee"); const char *payee = json_get_string(masternode, "payee");
json_int_t amount = json_get_int(masternode, "amount"); json_int_t amount = json_get_int(masternode, "amount");
if (payee && amount) { if (payee && amount && started) {
npayees++; npayees++;
available -= amount; available -= amount;
base58_decode(payee, script_payee); base58_decode(payee, script_payee);
bool masternode_use_p2sh = (strcmp(coind->symbol, "MAC") == 0);
if(masternode_use_p2sh)
p2sh_pack_tx(coind, script_dests, amount, script_payee);
else
job_pack_tx(coind, script_dests, amount, script_payee); job_pack_tx(coind, script_dests, amount, script_payee);
} }
} }
sprintf(payees, "%02x", npayees); sprintf(payees, "%02x", npayees);
strcat(templ->coinb2, payees); strcat(templ->coinb2, payees);
if (templ->has_segwit_txs) strcat(templ->coinb2, commitment);
strcat(templ->coinb2, script_dests); strcat(templ->coinb2, script_dests);
job_pack_tx(coind, templ->coinb2, available, NULL); job_pack_tx(coind, templ->coinb2, available, NULL);
strcat(templ->coinb2, "00000000"); // locktime strcat(templ->coinb2, "00000000"); // locktime
coind->reward = (double)available/100000000*coind->reward_mul; coind->reward = (double)available/100000000*coind->reward_mul;
//debuglog("%s total %u available %u\n", coind->symbol, templ->value, available);
//debuglog("%s %d dests %s\n", coind->symbol, npayees, script_dests); //debuglog("%s %d dests %s\n", coind->symbol, npayees, script_dests);
return; return;
} }
@ -351,7 +612,7 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value *
} }
else if(coind->hasmasternodes) /* OLD DASH style */ else if(coind->hasmasternodes && coind->oldmasternodes) /* OLD DASH style */
{ {
char charity_payee[256] = { 0 }; char charity_payee[256] = { 0 };
const char *payee = json_get_string(json_result, "payee"); const char *payee = json_get_string(json_result, "payee");

View file

@ -98,7 +98,7 @@ bool coind_validate_user_address(YAAMP_COIND *coind, char* const address)
} }
bool isvalid = json_get_bool(json_result, "isvalid"); bool isvalid = json_get_bool(json_result, "isvalid");
if(!isvalid) stratumlog("%s user address %s is not valid.\n", coind->name, address); if(!isvalid) stratumlog("%s: %s user address %s is not valid.\n", g_stratum_algo, coind->symbol, address);
json_value_free(json); json_value_free(json);
@ -114,7 +114,12 @@ bool coind_validate_address(YAAMP_COIND *coind)
char params[YAAMP_SMALLBUFSIZE]; char params[YAAMP_SMALLBUFSIZE];
sprintf(params, "[\"%s\"]", coind->wallet); sprintf(params, "[\"%s\"]", coind->wallet);
json_value *json = rpc_call(&coind->rpc, "validateaddress", params); json_value *json;
bool getaddressinfo = ((strcmp(coind->symbol,"DGB") == 0) || (strcmp(coind->symbol2, "DGB") == 0));
if(getaddressinfo)
json = rpc_call(&coind->rpc, "getaddressinfo", params);
else
json = rpc_call(&coind->rpc, "validateaddress", params);
if(!json) return false; if(!json) return false;
json_value *json_result = json_get_object(json, "result"); json_value *json_result = json_get_object(json, "result");
@ -124,11 +129,12 @@ bool coind_validate_address(YAAMP_COIND *coind)
return false; return false;
} }
bool isvalid = json_get_bool(json_result, "isvalid"); bool isvalid = getaddressinfo || json_get_bool(json_result, "isvalid");
if(!isvalid) stratumlog("%s wallet %s is not valid.\n", coind->name, coind->wallet); if(!isvalid) stratumlog("%s wallet %s is not valid.\n", coind->name, coind->wallet);
bool ismine = json_get_bool(json_result, "ismine"); bool ismine = json_get_bool(json_result, "ismine");
if(!ismine) stratumlog("%s wallet %s is not mine.\n", coind->name, coind->wallet); if(!ismine) stratumlog("%s wallet %s is not mine.\n", coind->name, coind->wallet);
else isvalid = ismine;
const char *p = json_get_string(json_result, "pubkey"); const char *p = json_get_string(json_result, "pubkey");
strcpy(coind->pubkey, p ? p : ""); strcpy(coind->pubkey, p ? p : "");
@ -139,6 +145,8 @@ bool coind_validate_address(YAAMP_COIND *coind)
if (!base58_decode(coind->wallet, coind->script_pubkey)) if (!base58_decode(coind->wallet, coind->script_pubkey))
stratumlog("Warning: unable to decode %s %s script pubkey\n", coind->symbol, coind->wallet); stratumlog("Warning: unable to decode %s %s script pubkey\n", coind->symbol, coind->wallet);
coind->p2sh_address = json_get_bool(json_result, "isscript");
// if base58 decode fails // if base58 decode fails
if (!strlen(coind->script_pubkey)) { if (!strlen(coind->script_pubkey)) {
const char *pk = json_get_string(json_result, "scriptPubKey"); const char *pk = json_get_string(json_result, "scriptPubKey");
@ -165,7 +173,6 @@ void coind_init(YAAMP_COIND *coind)
strcpy(account, coind->account); strcpy(account, coind->account);
if(!strcmp(coind->rpcencoding, "DCR")) { if(!strcmp(coind->rpcencoding, "DCR")) {
coind->usegetwork = true; coind->usegetwork = true;
//coind->noblocknotify = true;
//sprintf(account, "default"); //sprintf(account, "default");
} }
@ -247,8 +254,6 @@ void coind_terminate(YAAMP_COIND *coind)
// CommonLock(&coind->mutex); // CommonLock(&coind->mutex);
// while(!coind->deleted) // while(!coind->deleted)
// { // {
// debuglog("calling coind_getinfo %s\n", coind->symbol);
// job_create_last(coind, true); // job_create_last(coind, true);
// pthread_cond_wait(&coind->cond, &coind->mutex); // pthread_cond_wait(&coind->cond, &coind->mutex);
// } // }

View file

@ -35,6 +35,7 @@ public:
char pubkey[1024]; char pubkey[1024];
char script_pubkey[1024]; char script_pubkey[1024];
bool p2sh_address;
bool pos; bool pos;
bool hassubmitblock; bool hassubmitblock;
@ -47,6 +48,7 @@ public:
bool enable; bool enable;
bool auto_ready; bool auto_ready;
bool newblock; bool newblock;
char lastnotifyhash[192];
int height; int height;
double difficulty; double difficulty;
@ -65,7 +67,7 @@ public:
bool usegetwork; bool usegetwork;
bool usememorypool; bool usememorypool;
bool hasmasternodes; bool hasmasternodes;
bool noblocknotify; bool oldmasternodes;
bool multialgos; // pow_hash field (or mined_hash) bool multialgos; // pow_hash field (or mined_hash)
bool usesegwit; bool usesegwit;

Some files were not shown because too many files have changed in this diff Show more