2
0
Fork 0
mirror of https://git.sr.ht/~sircmpwn/mkproof synced 2024-06-08 16:36:07 +02:00

code format and make format

This commit is contained in:
JP Aumasson 2015-10-20 22:46:17 +02:00
parent e4a29780ff
commit 818608837d
22 changed files with 2374 additions and 2426 deletions

View File

@ -45,7 +45,7 @@ endif
LIB_SH := lib$(LIB_NAME).$(LIB_EXT)
LIB_ST := lib$(LIB_NAME).a
.PHONY: clean test
.PHONY: clean dist format
all: clean $(BIN) $(LIB_SH) $(LIB_ST)
bin: $(BIN)
@ -69,3 +69,6 @@ clean:
dist:
cd ..; \
tar cfvJ $(DIST)/$(DIST)-`date "+%Y%m%d%H%M00"`.txz $(DIST)/*
format:
clang-format -i src/*.c src/*.h src/blake2/*.c src/blake2/*.h

View File

@ -5,11 +5,12 @@
*
* 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/>.
* 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 <stdbool.h>
#include <string.h>
@ -18,8 +19,8 @@
#include "argon2.h"
#include "core.h"
/*************************Argon2 input parameter restrictions**************************************************/
/*************************Argon2 input parameter
* restrictions**************************************************/
/* Minimum and maximum number of lanes (degree of parallelism) */
const uint32_t ARGON2_MIN_LANES = 1;
@ -38,7 +39,8 @@ const uint32_t ARGON2_MIN_OUTLEN = 4;
const uint32_t ARGON2_MAX_OUTLEN = 0xFFFFFFFF;
/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */
const uint32_t ARGON2_MIN_MEMORY = 2 * __ARGON_SYNC_POINTS; // 2 blocks per slice
const uint32_t ARGON2_MIN_MEMORY =
2 * __ARGON_SYNC_POINTS; // 2 blocks per slice
const uint32_t ARGON2_MAX_MEMORY = 0xFFFFFFFF; // 2^32-1 blocks
/* Minimum and maximum number of passes */
@ -61,127 +63,159 @@ const uint32_t ARGON2_MAX_SALT_LENGTH = 0xFFFFFFFF;
const uint32_t ARGON2_MIN_SECRET = 0;
const uint32_t ARGON2_MAX_SECRET = 0xFFFFFFFF;
/************************* Error messages
* *********************************************************************************/
/************************* Error messages *********************************************************************************/
const char *Argon2_ErrorMessage[] = {
/*{ARGON2_OK, */ "OK",
/*},
const char *Argon2_ErrorMessage[] =
{
/*{ARGON2_OK, */"OK",/*},
{ARGON2_OUTPUT_PTR_NULL, */ "Output pointer is NULL",
/*},
{ARGON2_OUTPUT_PTR_NULL, */"Output pointer is NULL",/*},
{ARGON2_OUTPUT_TOO_SHORT, */ "Output is too short",
/*},
{ARGON2_OUTPUT_TOO_LONG, */ "Output is too long",
/*},
{ARGON2_OUTPUT_TOO_SHORT, */"Output is too short",/*},
{ARGON2_OUTPUT_TOO_LONG, */"Output is too long",/*},
{ARGON2_PWD_TOO_SHORT, */ "Password is too short",
/*},
{ARGON2_PWD_TOO_LONG, */ "Password is too long",
/*},
{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_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_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_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_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_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_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_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_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_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_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_OUT_PTR_MISMATCH, */ "Output pointer mismatch" /*}*/
};
int hashpwd( void *out, size_t outlen, const void *in, size_t inlen, const void *salt,
size_t saltlen, unsigned int t_cost, unsigned int m_cost )
{
Argon2_Context context = {( uint8_t * ) out, ( uint32_t ) outlen,
( uint8_t * ) in, ( uint32_t ) inlen,
( uint8_t * ) salt, ( uint32_t ) saltlen,
NULL, /*Pointer to the secret*/
0, /*Secret length*/
NULL, /*Pointer to the associated data*/
0, /*Associated data length*/
( uint32_t ) t_cost, ( uint32_t ) m_cost,
1, /*Number of lanes*/
1, /*Number of threads*/
NULL, NULL, /*Pointers to external memory (de)allocators*/
true, /*Clear the password after use*/
false, /*Not use the secret so not clear it*/
true, /*Clear the memory after use*/
false /*Not printing the memory content to the file*/
};
int hashpwd(void *out, size_t outlen, const void *in, size_t inlen,
const void *salt, size_t saltlen, unsigned int t_cost,
unsigned int m_cost) {
Argon2_Context context = {
(uint8_t *)out,
(uint32_t)outlen,
(uint8_t *)in,
(uint32_t)inlen,
(uint8_t *)salt,
(uint32_t)saltlen,
NULL, /*Pointer to the secret*/
0, /*Secret length*/
NULL, /*Pointer to the associated data*/
0, /*Associated data length*/
(uint32_t)t_cost,
(uint32_t)m_cost,
1, /*Number of lanes*/
1, /*Number of threads*/
NULL,
NULL, /*Pointers to external memory (de)allocators*/
true, /*Clear the password after use*/
false, /*Not use the secret so not clear it*/
true, /*Clear the memory after use*/
false /*Not printing the memory content to the file*/
};
return argon2_core( &context, Argon2_i );
return argon2_core(&context, Argon2_i);
}
int hashpwd2( void *out, size_t outlen, const void *in, size_t inlen, const void *salt,
size_t saltlen, unsigned int t_cost, unsigned int m_cost )
{
Argon2_Context context = {( uint8_t * ) out, ( uint32_t ) outlen,
( uint8_t * ) in, ( uint32_t ) inlen,
( uint8_t * ) salt, ( uint32_t ) saltlen,
NULL, 0, NULL, 0,
( uint32_t ) t_cost, ( uint32_t ) m_cost,
1, 1, NULL, NULL,
true, true, true, false
};
int hashpwd2(void *out, size_t outlen, const void *in, size_t inlen,
const void *salt, size_t saltlen, unsigned int t_cost,
unsigned int m_cost) {
Argon2_Context context = {(uint8_t *)out,
(uint32_t)outlen,
(uint8_t *)in,
(uint32_t)inlen,
(uint8_t *)salt,
(uint32_t)saltlen,
NULL,
0,
NULL,
0,
(uint32_t)t_cost,
(uint32_t)m_cost,
1,
1,
NULL,
NULL,
true,
true,
true,
false};
return argon2_core( &context, Argon2_d );
return argon2_core(&context, Argon2_d);
}
int argon2d(Argon2_Context *context) { return argon2_core(context, Argon2_d); }
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) {
if (0 == context->outlen || NULL == hash) {
return ARGON2_OUT_PTR_MISMATCH;
}
int result = argon2_core(context, Argon2_d);
if (ARGON2_OK != result) {
return result;
}
return 0 == memcmp(hash, context->out, context->outlen);
}
int argon2i( Argon2_Context *context )
{
return argon2_core( context, Argon2_i );
}
int verify_d( Argon2_Context *context, const char *hash )
{
if ( 0 == context->outlen || NULL == hash )
{
return ARGON2_OUT_PTR_MISMATCH;
}
int result = argon2_core( context, Argon2_d );
if ( ARGON2_OK != result )
{
return result;
}
return 0 == memcmp( hash, context->out, context->outlen );
}
const char *error_message( int error_code )
{
if ( error_code < ARGON2_ERROR_CODES_LENGTH )
{
return Argon2_ErrorMessage[( Argon2_ErrorCodes ) error_code];
}
return "Unknown error code.";
const char *error_message(int error_code) {
if (error_code < ARGON2_ERROR_CODES_LENGTH) {
return Argon2_ErrorMessage[(Argon2_ErrorCodes)error_code];
}
return "Unknown error code.";
}

View File

@ -5,8 +5,10 @@
*
* 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/>.
* 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/>.
*/
#pragma once
@ -17,17 +19,17 @@
#include <stddef.h>
#include <stdbool.h>
/************************* Constants to enable Known Answer Tests (KAT) **************************************************/
/************************* Constants to enable Known Answer Tests (KAT)
* **************************************************/
/* Enable ARGON2_KAT */
//#define ARGON2_KAT
//#define ARGON2_KAT_INTERNAL
/* The KAT file name */
const char *ARGON2_KAT_FILENAME;
/*************************Argon2 input parameter restrictions**************************************************/
/*************************Argon2 input parameter
* restrictions**************************************************/
/* Minimum and maximum number of lanes (degree of parallelism) */
const uint32_t ARGON2_MIN_LANES;
@ -41,92 +43,95 @@ const uint32_t ARGON2_MAX_THREADS;
const uint32_t ARGON2_SYNC_POINTS;
/* Minimum and maximum digest size in bytes */
const uint32_t ARGON2_MIN_OUTLEN ;
const uint32_t ARGON2_MAX_OUTLEN ;
const uint32_t ARGON2_MIN_OUTLEN;
const uint32_t ARGON2_MAX_OUTLEN;
/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */
const uint32_t ARGON2_MIN_MEMORY ; // 2 blocks per slice
const uint32_t ARGON2_MIN_MEMORY; // 2 blocks per slice
const uint32_t ARGON2_MAX_MEMORY; // 2^32-1 blocks
/* Minimum and maximum number of passes */
const uint32_t ARGON2_MIN_TIME ;
const uint32_t ARGON2_MIN_TIME;
const uint32_t ARGON2_MAX_TIME;
/* Minimum and maximum password length in bytes */
const uint32_t ARGON2_MIN_PWD_LENGTH ;
const uint32_t ARGON2_MAX_PWD_LENGTH ;
const uint32_t ARGON2_MIN_PWD_LENGTH;
const uint32_t ARGON2_MAX_PWD_LENGTH;
/* Minimum and maximum associated data length in bytes */
const uint32_t ARGON2_MIN_AD_LENGTH ;
const uint32_t ARGON2_MAX_AD_LENGTH ;
const uint32_t ARGON2_MIN_AD_LENGTH;
const uint32_t ARGON2_MAX_AD_LENGTH;
/* Minimum and maximum salt length in bytes */
const uint32_t ARGON2_MIN_SALT_LENGTH ;
const uint32_t ARGON2_MIN_SALT_LENGTH;
const uint32_t ARGON2_MAX_SALT_LENGTH;
/* Minimum and maximum key length in bytes */
const uint32_t ARGON2_MIN_SECRET ;
const uint32_t ARGON2_MAX_SECRET ;
const uint32_t ARGON2_MIN_SECRET;
const uint32_t ARGON2_MAX_SECRET;
/************************* Error codes *********************************************************************************/
typedef enum _Argon2_ErrorCodes
{
ARGON2_OK = 0,
/************************* Error codes
* *********************************************************************************/
typedef enum _Argon2_ErrorCodes {
ARGON2_OK = 0,
ARGON2_OUTPUT_PTR_NULL = 1,
ARGON2_OUTPUT_PTR_NULL = 1,
ARGON2_OUTPUT_TOO_SHORT = 2,
ARGON2_OUTPUT_TOO_LONG = 3,
ARGON2_OUTPUT_TOO_SHORT = 2,
ARGON2_OUTPUT_TOO_LONG = 3,
ARGON2_PWD_TOO_SHORT = 4,
ARGON2_PWD_TOO_LONG = 5,
ARGON2_PWD_TOO_SHORT = 4,
ARGON2_PWD_TOO_LONG = 5,
ARGON2_SALT_TOO_SHORT = 6,
ARGON2_SALT_TOO_LONG = 7,
ARGON2_SALT_TOO_SHORT = 6,
ARGON2_SALT_TOO_LONG = 7,
ARGON2_AD_TOO_SHORT = 8,
ARGON2_AD_TOO_LONG = 9,
ARGON2_AD_TOO_SHORT = 8,
ARGON2_AD_TOO_LONG = 9,
ARGON2_SECRET_TOO_SHORT = 10,
ARGON2_SECRET_TOO_LONG = 11,
ARGON2_SECRET_TOO_SHORT = 10,
ARGON2_SECRET_TOO_LONG = 11,
ARGON2_TIME_TOO_SMALL = 12,
ARGON2_TIME_TOO_LARGE = 13,
ARGON2_TIME_TOO_SMALL = 12,
ARGON2_TIME_TOO_LARGE = 13,
ARGON2_MEMORY_TOO_LITTLE = 14,
ARGON2_MEMORY_TOO_MUCH = 15,
ARGON2_MEMORY_TOO_LITTLE = 14,
ARGON2_MEMORY_TOO_MUCH = 15,
ARGON2_LANES_TOO_FEW = 16,
ARGON2_LANES_TOO_MANY = 17,
ARGON2_LANES_TOO_FEW = 16,
ARGON2_LANES_TOO_MANY = 17,
ARGON2_PWD_PTR_MISMATCH = 18, //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_AD_PTR_MISMATCH = 21, //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_SECRET_PTR_MISMATCH = 20, // 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_ALLOCATE_MEMORY_CBK_NULL = 24,
ARGON2_FREE_MEMORY_CBK_NULL = 23,
ARGON2_ALLOCATE_MEMORY_CBK_NULL = 24,
ARGON2_INCORRECT_PARAMETER = 25,
ARGON2_INCORRECT_TYPE = 26,
ARGON2_INCORRECT_PARAMETER = 25,
ARGON2_INCORRECT_TYPE = 26,
ARGON2_OUT_PTR_MISMATCH = 27,
ARGON2_OUT_PTR_MISMATCH = 27,
ARGON2_THREADS_TOO_FEW = 28,
ARGON2_THREADS_TOO_MANY = 29,
ARGON2_THREADS_TOO_FEW = 28,
ARGON2_THREADS_TOO_MANY = 29,
ARGON2_ERROR_CODES_LENGTH /* Do NOT remove; Do NOT add error codes after this error code */
ARGON2_ERROR_CODES_LENGTH /* Do NOT remove; Do NOT add error codes after this
error code */
} Argon2_ErrorCodes;
/********************************************* Memory allocator types --- for
* external allocation
* *************************************************************/
typedef int (*AllocateMemoryCallback)(uint8_t **memory,
size_t bytes_to_allocate);
typedef void (*FreeMemoryCallback)(uint8_t *memory, size_t bytes_to_allocate);
/********************************************* Memory allocator types --- for external allocation *************************************************************/
typedef int ( *AllocateMemoryCallback )( uint8_t **memory, size_t bytes_to_allocate );
typedef void( *FreeMemoryCallback )( uint8_t *memory, size_t bytes_to_allocate );
/********************************************* Argon2 external data structures*************************************************************/
/********************************************* Argon2 external data
* structures*************************************************************/
/*
*****Context: structure to hold Argon2 inputs:
@ -138,51 +143,53 @@ typedef void( *FreeMemoryCallback )( uint8_t *memory, size_t bytes_to_allocate )
* number of passes, amount of used memory (in KBytes, can be rounded up a bit)
* number of parallel threads that will be run.
* All the parameters above affect the output hash value.
* Additionally, two function pointers can be provided to allocate and deallocate the memory (if NULL, memory will be allocated internally).
* 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
* Additionally, two function pointers can be provided to allocate and
deallocate the memory (if NULL, memory will be allocated internally).
* 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
****************************
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.
You need to spend 1 GB of RAM and you run 5 passes of Argon2d with 4 parallel lanes.
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.
You need to spend 1 GB of RAM and you run 5 passes of Argon2d with 4 parallel
lanes.
You want to erase the password, but you're OK with last pass not being 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
{
uint8_t *out; //output array
uint32_t outlen; //digest length
typedef struct _Argon2_Context {
uint8_t *out; // output array
uint32_t outlen; // digest length
uint8_t *pwd; //password array
uint32_t pwdlen; //password length
uint8_t *pwd; // password array
uint32_t pwdlen; // password length
uint8_t *salt; //salt array
uint32_t saltlen; //salt length
uint8_t *salt; // salt array
uint32_t saltlen; // salt length
uint8_t *secret; //key array
uint32_t secretlen; //key length
uint8_t *secret; // key array
uint32_t secretlen; // key length
uint8_t *ad; //associated data array
uint32_t adlen; //associated data 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
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
AllocateMemoryCallback allocate_cbk; //pointer to memory allocator
FreeMemoryCallback free_cbk; //pointer to memory deallocator
AllocateMemoryCallback allocate_cbk; // pointer to memory allocator
FreeMemoryCallback free_cbk; // pointer to memory deallocator
bool clear_password; //whether to clear the password array
bool clear_secret; //whether to clear the secret array
bool clear_memory; //whether to clear the memory after the run
bool clear_password; // whether to clear the password array
bool clear_secret; // whether to clear the secret array
bool clear_memory; // whether to clear the memory after the run
bool print; //whether to print starting variables, memory blocks, and the tag to the file -- Test vectors only!
bool print; // whether to print starting variables, memory blocks, and the tag
// to the file -- Test vectors only!
} Argon2_Context;
/**
* Function to hash the inputs in the memory-hard fashion (uses Argon2i)
* @param out Pointer to the memory where the hash digest will be written
@ -196,64 +203,72 @@ typedef struct _Argon2_Context
* @pre @a saltlen must be at least @saltlen bytes long
* @return Zero if successful, 1 otherwise.
*/
int hashpwd( void *out, size_t outlen, const void *in, size_t inlen, const void *salt, size_t saltlen,
unsigned int t_cost, unsigned int m_cost );
int hashpwd(void *out, size_t outlen, const void *in, size_t inlen,
const void *salt, size_t saltlen, unsigned int t_cost,
unsigned int m_cost);
/* same for argon2d */
int hashpwd2( void *out, size_t outlen, const void *in, size_t inlen, const void *salt, size_t saltlen,
unsigned int t_cost, unsigned int m_cost );
int hashpwd2(void *out, size_t outlen, const void *in, size_t inlen,
const void *salt, size_t saltlen, unsigned int t_cost,
unsigned int m_cost);
/*
* **************Argon2d: Version of Argon2 that picks memory blocks depending on the password and salt. Only for side-channel-free environment!!***************
* **************Argon2d: Version of Argon2 that picks memory blocks depending
* on the password and salt. Only for side-channel-free
* environment!!***************
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
int argon2d( Argon2_Context *context );
int argon2d(Argon2_Context *context);
/*
* * **************Argon2i: Version of Argon2 that picks memory blocks independent on the password and salt. Good for side-channels,
* * **************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 );
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 );
int argon2di(Argon2_Context *context);
/*
* * **************Argon2ds: Argon2d hardened against GPU attacks, 20% slower***************
* * **************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 );
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***************
* * **************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 );
int argon2id(Argon2_Context *context);
/*
* Verify if a given password is correct for Argon2d hashing
* @param context Pointer to current Argon2 context
* @param hash The password hash to verify. The length of the hash is specified by the context outlen member
* @param hash The password hash to verify. The length of the hash is
* specified by the context outlen member
* @return Zero if successful, a non zero error code otherwise
*/
int verify_d( Argon2_Context *context, const char *hash );
int verify_d(Argon2_Context *context, const char *hash);
/*
* Get the associated error message for given error code
* @return The error message associated with the given error code
*/
const char *error_message( int error_code );
const char *error_message(int error_code);
#endif

View File

@ -7,8 +7,10 @@
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
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/>.
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/>.
*/
#pragma once
#ifndef __BLAKE2_CONFIG_H__
@ -35,7 +37,6 @@
#define HAVE_XOP
#endif
#ifdef HAVE_AVX2
#ifndef HAVE_AVX
#define HAVE_AVX
@ -69,4 +70,3 @@
#endif
#endif

View File

@ -7,8 +7,10 @@
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
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/>.
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/>.
*/
#pragma once
#ifndef __BLAKE2_IMPL_H__
@ -19,128 +21,133 @@
/* Argon2 Team - Begin Code */
#include "brg-endian.h"
#if defined(PLATFORM_BYTE_ORDER) && (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) && !defined(NATIVE_LITTLE_ENDIAN)
#if defined(PLATFORM_BYTE_ORDER) && \
(PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) && \
!defined(NATIVE_LITTLE_ENDIAN)
#define NATIVE_LITTLE_ENDIAN
#endif
/* Argon2 Team - End Code */
static __inline uint32_t load32( const void *src )
{
static __inline uint32_t load32(const void *src) {
#if defined(NATIVE_LITTLE_ENDIAN)
uint32_t w;
memcpy( &w, src, sizeof w );
return w;
uint32_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
uint32_t w = *p++;
w |= ( uint32_t )( *p++ ) << 8;
w |= ( uint32_t )( *p++ ) << 16;
w |= ( uint32_t )( *p++ ) << 24;
return w;
const uint8_t *p = (const uint8_t *)src;
uint32_t w = *p++;
w |= (uint32_t)(*p++) << 8;
w |= (uint32_t)(*p++) << 16;
w |= (uint32_t)(*p++) << 24;
return w;
#endif
}
static __inline uint64_t load64( const void *src )
{
static __inline uint64_t load64(const void *src) {
#if defined(NATIVE_LITTLE_ENDIAN)
uint64_t w;
memcpy( &w, src, sizeof w );
return w;
uint64_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
uint64_t w = *p++;
w |= ( uint64_t )( *p++ ) << 8;
w |= ( uint64_t )( *p++ ) << 16;
w |= ( uint64_t )( *p++ ) << 24;
w |= ( uint64_t )( *p++ ) << 32;
w |= ( uint64_t )( *p++ ) << 40;
w |= ( uint64_t )( *p++ ) << 48;
w |= ( uint64_t )( *p++ ) << 56;
return w;
const uint8_t *p = (const uint8_t *)src;
uint64_t w = *p++;
w |= (uint64_t)(*p++) << 8;
w |= (uint64_t)(*p++) << 16;
w |= (uint64_t)(*p++) << 24;
w |= (uint64_t)(*p++) << 32;
w |= (uint64_t)(*p++) << 40;
w |= (uint64_t)(*p++) << 48;
w |= (uint64_t)(*p++) << 56;
return w;
#endif
}
static __inline void store32( void *dst, uint32_t w )
{
static __inline void store32(void *dst, uint32_t w) {
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy( dst, &w, sizeof w );
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w;
uint8_t *p = (uint8_t *)dst;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
#endif
}
static __inline void store64( void *dst, uint64_t w )
{
static __inline void store64(void *dst, uint64_t w) {
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy( dst, &w, sizeof w );
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w;
uint8_t *p = (uint8_t *)dst;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
#endif
}
static __inline uint64_t load48( const void *src )
{
const uint8_t *p = ( const uint8_t * )src;
uint64_t w = *p++;
w |= ( uint64_t )( *p++ ) << 8;
w |= ( uint64_t )( *p++ ) << 16;
w |= ( uint64_t )( *p++ ) << 24;
w |= ( uint64_t )( *p++ ) << 32;
w |= ( uint64_t )( *p++ ) << 40;
return w;
static __inline uint64_t load48(const void *src) {
const uint8_t *p = (const uint8_t *)src;
uint64_t w = *p++;
w |= (uint64_t)(*p++) << 8;
w |= (uint64_t)(*p++) << 16;
w |= (uint64_t)(*p++) << 24;
w |= (uint64_t)(*p++) << 32;
w |= (uint64_t)(*p++) << 40;
return w;
}
static __inline void store48( void *dst, uint64_t w )
{
uint8_t *p = ( uint8_t * )dst;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w;
static __inline void store48(void *dst, uint64_t w) {
uint8_t *p = (uint8_t *)dst;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
}
static __inline uint32_t rotl32( const uint32_t w, const unsigned c )
{
return ( w << c ) | ( w >> ( 32 - c ) );
static __inline uint32_t rotl32(const uint32_t w, const unsigned c) {
return (w << c) | (w >> (32 - c));
}
static __inline uint64_t rotl64( const uint64_t w, const unsigned c )
{
return ( w << c ) | ( w >> ( 64 - c ) );
static __inline uint64_t rotl64(const uint64_t w, const unsigned c) {
return (w << c) | (w >> (64 - c));
}
static __inline uint32_t rotr32( const uint32_t w, const unsigned c )
{
return ( w >> c ) | ( w << ( 32 - c ) );
static __inline uint32_t rotr32(const uint32_t w, const unsigned c) {
return (w >> c) | (w << (32 - c));
}
static __inline uint64_t rotr64( const uint64_t w, const unsigned c )
{
return ( w >> c ) | ( w << ( 64 - c ) );
static __inline uint64_t rotr64(const uint64_t w, const unsigned c) {
return (w >> c) | (w << (64 - c));
}
/* prevents compiler optimizing out memset() */
static __inline void secure_zero_memory( void *v, size_t n )
{
volatile uint8_t *p = ( volatile uint8_t * )v;
static __inline void secure_zero_memory(void *v, size_t n) {
volatile uint8_t *p = (volatile uint8_t *)v;
while( n-- ) *p++ = 0;
while (n--)
*p++ = 0;
}
#endif

View File

@ -1,85 +1,91 @@
#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))))
#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))))
#define G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
row1l = _mm_add_epi64(row1l, row2l); \
row1h = _mm_add_epi64(row1h, row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -32); \
row4h = _mm_roti_epi64(row4h, -32); \
\
row3l = _mm_add_epi64(row3l, row4l); \
row3h = _mm_add_epi64(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -24); \
row2h = _mm_roti_epi64(row2h, -24); \
#define G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
row1l = _mm_add_epi64(row1l, row2l); \
row1h = _mm_add_epi64(row1h, row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -32); \
row4h = _mm_roti_epi64(row4h, -32); \
\
row3l = _mm_add_epi64(row3l, row4l); \
row3h = _mm_add_epi64(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -24); \
row2h = _mm_roti_epi64(row2h, -24);
#define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
row1l = _mm_add_epi64(row1l, row2l); \
row1h = _mm_add_epi64(row1h, row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -16); \
row4h = _mm_roti_epi64(row4h, -16); \
\
row3l = _mm_add_epi64(row3l, row4l); \
row3h = _mm_add_epi64(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -63); \
row2h = _mm_roti_epi64(row2h, -63); \
#define G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
row1l = _mm_add_epi64(row1l, row2l); \
row1h = _mm_add_epi64(row1h, row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -16); \
row4h = _mm_roti_epi64(row4h, -16); \
\
row3l = _mm_add_epi64(row3l, row4l); \
row3h = _mm_add_epi64(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -63); \
row2h = _mm_roti_epi64(row2h, -63);
#define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
t0 = _mm_alignr_epi8(row2h, row2l, 8); \
t1 = _mm_alignr_epi8(row2l, row2h, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4h, row4l, 8); \
t1 = _mm_alignr_epi8(row4l, row4h, 8); \
row4l = t1; \
row4h = t0;
#define DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
t0 = _mm_alignr_epi8(row2h, row2l, 8); \
t1 = _mm_alignr_epi8(row2l, row2h, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4h, row4l, 8); \
t1 = _mm_alignr_epi8(row4l, row4h, 8); \
row4l = t1; \
row4h = t0;
#define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
t0 = _mm_alignr_epi8(row2l, row2h, 8); \
t1 = _mm_alignr_epi8(row2h, row2l, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4l, row4h, 8); \
t1 = _mm_alignr_epi8(row4h, row4l, 8); \
row4l = t1; \
row4h = t0;
#define UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
t0 = _mm_alignr_epi8(row2l, row2h, 8); \
t1 = _mm_alignr_epi8(row2h, row2l, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4l, row4h, 8); \
t1 = _mm_alignr_epi8(row4h, row4l, 8); \
row4l = t1; \
row4h = t0;
#define BLAKE2_ROUND(row1l,row1h,row2l,row2h,row3l,row3h,row4l,row4h) \
G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
\
DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
\
G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
\
UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h);
#define BLAKE2_ROUND(row1l, row1h, row2l, row2h, row3l, row3h, row4l, row4h) \
G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
\
DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
\
G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
\
UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h);

View File

@ -7,8 +7,10 @@
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
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/>.
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/>.
*/
#pragma once
#ifndef __BLAKE2_H__
@ -21,7 +23,7 @@
#if defined(_MSC_VER)
#define ALIGN(x) __declspec(align(x))
#else
#define ALIGN(x) __attribute__ ((__aligned__(x)))
#define ALIGN(x) __attribute__((__aligned__(x)))
#endif
/* Argon2 Team - End Code */
@ -29,59 +31,56 @@
extern "C" {
#endif
enum blake2b_constant
{
BLAKE2B_BLOCKBYTES = 128,
BLAKE2B_OUTBYTES = 64,
BLAKE2B_KEYBYTES = 64,
BLAKE2B_SALTBYTES = 16,
BLAKE2B_PERSONALBYTES = 16
enum blake2b_constant {
BLAKE2B_BLOCKBYTES = 128,
BLAKE2B_OUTBYTES = 64,
BLAKE2B_KEYBYTES = 64,
BLAKE2B_SALTBYTES = 16,
BLAKE2B_PERSONALBYTES = 16
};
#pragma pack(push, 1)
typedef struct __blake2b_param
{
uint8_t digest_length; // 1
uint8_t key_length; // 2
uint8_t fanout; // 3
uint8_t depth; // 4
uint32_t leaf_length; // 8
uint64_t node_offset; // 16
uint8_t node_depth; // 17
uint8_t inner_length; // 18
uint8_t reserved[14]; // 32
uint8_t salt[BLAKE2B_SALTBYTES]; // 48
uint8_t personal[BLAKE2B_PERSONALBYTES]; // 64
typedef struct __blake2b_param {
uint8_t digest_length; // 1
uint8_t key_length; // 2
uint8_t fanout; // 3
uint8_t depth; // 4
uint32_t leaf_length; // 8
uint64_t node_offset; // 16
uint8_t node_depth; // 17
uint8_t inner_length; // 18
uint8_t reserved[14]; // 32
uint8_t salt[BLAKE2B_SALTBYTES]; // 48
uint8_t personal[BLAKE2B_PERSONALBYTES]; // 64
} blake2b_param;
ALIGN( 64 ) typedef struct __blake2b_state
{
uint64_t h[8];
uint64_t t[2];
uint64_t f[2];
uint8_t buf[2 * BLAKE2B_BLOCKBYTES];
size_t buflen;
uint8_t last_node;
ALIGN(64) typedef struct __blake2b_state {
uint64_t h[8];
uint64_t t[2];
uint64_t f[2];
uint8_t buf[2 * BLAKE2B_BLOCKBYTES];
size_t buflen;
uint8_t last_node;
} blake2b_state;
#pragma pack(pop)
int blake2b_init( blake2b_state *S, const uint8_t outlen );
int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen );
int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen );
int blake2b_init(blake2b_state *S, const uint8_t outlen);
int blake2b_init_key(blake2b_state *S, const uint8_t outlen, const void *key,
const uint8_t keylen);
int blake2b_init_param(blake2b_state *S, const blake2b_param *P);
int blake2b_update(blake2b_state *S, const uint8_t *in, uint64_t inlen);
int blake2b_final(blake2b_state *S, uint8_t *out, uint8_t outlen);
int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
int blake2b(uint8_t *out, const void *in, const void *key, const uint8_t outlen,
const uint64_t inlen, uint8_t keylen);
/* Argon2 Team - Begin Code */
int blake2b_long( uint8_t *out, const void *in, const uint32_t outlen, const uint64_t inlen );
int blake2b_long(uint8_t *out, const void *in, const uint32_t outlen,
const uint64_t inlen);
/* Argon2 Team - End Code */
#if defined(__cplusplus)
}
#endif
#endif

View File

@ -7,8 +7,10 @@
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
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/>.
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>
@ -18,324 +20,310 @@
#include "blake2.h"
#include "blake2-impl.h"
static const uint64_t blake2b_IV[8] =
{
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
};
static const uint64_t blake2b_IV[8] = {
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL};
static const uint8_t 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 const uint8_t 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 __inline int blake2b_set_lastnode( blake2b_state *S )
{
S->f[1] = ~0ULL;
return 0;
static __inline int blake2b_set_lastnode(blake2b_state *S) {
S->f[1] = ~0ULL;
return 0;
}
/* Some helper functions, not necessarily useful */
static __inline int blake2b_set_lastblock( blake2b_state *S )
{
if( S->last_node ) blake2b_set_lastnode( S );
static __inline int blake2b_set_lastblock(blake2b_state *S) {
if (S->last_node)
blake2b_set_lastnode(S);
S->f[0] = ~0ULL;
return 0;
S->f[0] = ~0ULL;
return 0;
}
static __inline int blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
{
S->t[0] += inc;
S->t[1] += ( S->t[0] < inc );
return 0;
static __inline int blake2b_increment_counter(blake2b_state *S,
const uint64_t inc) {
S->t[0] += inc;
S->t[1] += (S->t[0] < inc);
return 0;
}
static __inline int blake2b_init0(blake2b_state *S) {
memset(S, 0, sizeof(blake2b_state));
static __inline int blake2b_init0( blake2b_state *S )
{
memset( S, 0, sizeof( blake2b_state ) );
for (int i = 0; i < 8; ++i)
S->h[i] = blake2b_IV[i];
for( int i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
return 0;
return 0;
}
/* init xors IV with input parameter block */
int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
{
blake2b_init0( S );
const uint8_t *p = ( const uint8_t * )( P );
int blake2b_init_param(blake2b_state *S, const blake2b_param *P) {
blake2b_init0(S);
const uint8_t *p = (const uint8_t *)(P);
/* IV XOR ParamBlock */
for( size_t i = 0; i < 8; ++i )
S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
/* IV XOR ParamBlock */
for (size_t i = 0; i < 8; ++i)
S->h[i] ^= load64(p + sizeof(S->h[i]) * i);
return 0;
return 0;
}
int blake2b_init(blake2b_state *S, const uint8_t outlen) {
blake2b_param P[1];
if ((!outlen) || (outlen > BLAKE2B_OUTBYTES))
return -1;
int blake2b_init( blake2b_state *S, const uint8_t outlen )
{
blake2b_param P[1];
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
P->digest_length = outlen;
P->key_length = 0;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
store64( &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 );
P->digest_length = outlen;
P->key_length = 0;
P->fanout = 1;
P->depth = 1;
store32(&P->leaf_length, 0);
store64(&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, const uint8_t outlen, const void *key,
const uint8_t keylen) {
blake2b_param P[1];
int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )
{
blake2b_param P[1];
if ((!outlen) || (outlen > BLAKE2B_OUTBYTES))
return -1;
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
if (!key || !keylen || keylen > BLAKE2B_KEYBYTES)
return -1;
if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
P->digest_length = outlen;
P->key_length = keylen;
P->fanout = 1;
P->depth = 1;
store32(&P->leaf_length, 0);
store64(&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));
P->digest_length = outlen;
P->key_length = keylen;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
store64( &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)
return -1;
if( blake2b_init_param( S, P ) < 0 ) return -1;
{
uint8_t block[BLAKE2B_BLOCKBYTES];
memset( block, 0, BLAKE2B_BLOCKBYTES );
memcpy( block, key, keylen );
blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
}
return 0;
{
uint8_t block[BLAKE2B_BLOCKBYTES];
memset(block, 0, BLAKE2B_BLOCKBYTES);
memcpy(block, key, keylen);
blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
secure_zero_memory(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */
}
return 0;
}
static int blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
{
uint64_t m[16];
uint64_t v[16];
int i;
static int blake2b_compress(blake2b_state *S,
const uint8_t block[BLAKE2B_BLOCKBYTES]) {
uint64_t m[16];
uint64_t v[16];
int i;
for( i = 0; i < 16; ++i )
m[i] = load64( block + i * sizeof( m[i] ) );
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];
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] = S->t[0] ^ blake2b_IV[4];
v[13] = S->t[1] ^ blake2b_IV[5];
v[14] = S->f[0] ^ blake2b_IV[6];
v[15] = S->f[1] ^ blake2b_IV[7];
#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(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(0)
ROUND( 0 );
ROUND( 1 );
ROUND( 2 );
ROUND( 3 );
ROUND( 4 );
ROUND( 5 );
ROUND( 6 );
ROUND( 7 );
ROUND( 8 );
ROUND( 9 );
ROUND( 10 );
ROUND( 11 );
v[8] = blake2b_IV[0];
v[9] = blake2b_IV[1];
v[10] = blake2b_IV[2];
v[11] = blake2b_IV[3];
v[12] = S->t[0] ^ blake2b_IV[4];
v[13] = S->t[1] ^ blake2b_IV[5];
v[14] = S->f[0] ^ blake2b_IV[6];
v[15] = S->f[1] ^ blake2b_IV[7];
#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 (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 (0)
ROUND(0);
ROUND(1);
ROUND(2);
ROUND(3);
ROUND(4);
ROUND(5);
ROUND(6);
ROUND(7);
ROUND(8);
ROUND(9);
ROUND(10);
ROUND(11);
for( i = 0; i < 8; ++i )
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
for (i = 0; i < 8; ++i)
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
#undef G
#undef ROUND
return 0;
return 0;
}
/* inlen now in bytes */
int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen )
{
while( inlen > 0 )
int blake2b_update(blake2b_state *S, const uint8_t *in, uint64_t inlen) {
while (inlen > 0) {
size_t left = S->buflen;
size_t fill = 2 * BLAKE2B_BLOCKBYTES - left;
if (inlen > fill) {
memcpy(S->buf + left, in, fill); // Fill buffer
S->buflen += fill;
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress(S, S->buf); // Compress
memcpy(S->buf, S->buf + BLAKE2B_BLOCKBYTES,
BLAKE2B_BLOCKBYTES); // Shift buffer left
S->buflen -= BLAKE2B_BLOCKBYTES;
in += fill;
inlen -= fill;
} else // inlen <= fill
{
size_t left = S->buflen;
size_t fill = 2 * BLAKE2B_BLOCKBYTES - left;
if( inlen > fill )
{
memcpy( S->buf + left, in, fill ); // Fill buffer
S->buflen += fill;
blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
blake2b_compress( S, S->buf ); // Compress
memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); // Shift buffer left
S->buflen -= BLAKE2B_BLOCKBYTES;
in += fill;
inlen -= fill;
}
else // inlen <= fill
{
memcpy( S->buf + left, in, inlen );
S->buflen += inlen; // Be lazy, do not compress
in += inlen;
inlen -= inlen;
}
memcpy(S->buf + left, in, inlen);
S->buflen += inlen; // Be lazy, do not compress
in += inlen;
inlen -= inlen;
}
}
return 0;
return 0;
}
/* Is this correct? */
int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen )
{
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
int blake2b_final(blake2b_state *S, uint8_t *out, uint8_t outlen) {
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
if( outlen > BLAKE2B_OUTBYTES )
return -1;
if (outlen > BLAKE2B_OUTBYTES)
return -1;
if( S->buflen > BLAKE2B_BLOCKBYTES )
{
blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
blake2b_compress( S, S->buf );
S->buflen -= BLAKE2B_BLOCKBYTES;
memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, S->buflen );
}
if (S->buflen > BLAKE2B_BLOCKBYTES) {
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress(S, S->buf);
S->buflen -= BLAKE2B_BLOCKBYTES;
memcpy(S->buf, S->buf + BLAKE2B_BLOCKBYTES, S->buflen);
}
blake2b_increment_counter( S, S->buflen );
blake2b_set_lastblock( S );
memset( S->buf + S->buflen, 0, 2 * BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
blake2b_compress( S, S->buf );
blake2b_increment_counter(S, S->buflen);
blake2b_set_lastblock(S);
memset(S->buf + S->buflen, 0,
2 * BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
blake2b_compress(S, S->buf);
for( int i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
for (int i = 0; i < 8; ++i) /* Output full hash to temp buffer */
store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
memcpy( out, buffer, outlen );
return 0;
memcpy(out, buffer, outlen);
return 0;
}
/* inlen, at least, should be uint64_t. Others can be size_t. */
int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
{
blake2b_state S[1];
int blake2b(uint8_t *out, const void *in, const void *key, const uint8_t outlen,
const uint64_t inlen, uint8_t keylen) {
blake2b_state S[1];
/* Verify parameters */
if ( NULL == in && inlen > 0 ) return -1;
/* Verify parameters */
if (NULL == in && inlen > 0)
return -1;
if ( NULL == out ) return -1;
if (NULL == out)
return -1;
if( NULL == key && keylen > 0 ) return -1;
if (NULL == key && keylen > 0)
return -1;
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
if (!outlen || outlen > BLAKE2B_OUTBYTES)
return -1;
if( keylen > BLAKE2B_KEYBYTES ) return -1;
if (keylen > BLAKE2B_KEYBYTES)
return -1;
if( keylen > 0 )
{
if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
}
else
{
if( blake2b_init( S, outlen ) < 0 ) return -1;
}
if (keylen > 0) {
if (blake2b_init_key(S, outlen, key, keylen) < 0)
return -1;
} else {
if (blake2b_init(S, outlen) < 0)
return -1;
}
blake2b_update( S, ( const uint8_t * )in, inlen );
blake2b_final( S, out, outlen );
return 0;
blake2b_update(S, (const uint8_t *)in, inlen);
blake2b_final(S, out, outlen);
return 0;
}
/* Argon2 Team - Begin Code */
int blake2b_long( uint8_t *out, const void *in, const uint32_t outlen, const uint64_t inlen )
{
blake2b_state blake_state;
memset( &blake_state, 0, sizeof blake_state );
int blake2b_long(uint8_t *out, const void *in, const uint32_t outlen,
const uint64_t inlen) {
blake2b_state blake_state;
memset(&blake_state, 0, sizeof blake_state);
if ( outlen <= BLAKE2B_OUTBYTES )
{
blake2b_init( &blake_state, outlen );
blake2b_update( &blake_state, ( const uint8_t * )&outlen, sizeof( uint32_t ) );
blake2b_update( &blake_state, ( const uint8_t * )in, inlen );
blake2b_final( &blake_state, out, outlen );
}
else
{
uint8_t out_buffer[BLAKE2B_OUTBYTES];
uint8_t in_buffer[BLAKE2B_OUTBYTES];
blake2b_init( &blake_state, BLAKE2B_OUTBYTES );
blake2b_update( &blake_state, ( const uint8_t * )&outlen, sizeof( uint32_t ) );
blake2b_update( &blake_state, ( const uint8_t * )in, inlen );
blake2b_final( &blake_state, out_buffer, BLAKE2B_OUTBYTES );
memcpy( out, out_buffer, BLAKE2B_OUTBYTES / 2 );
out += BLAKE2B_OUTBYTES / 2;
uint32_t toproduce = outlen - BLAKE2B_OUTBYTES / 2;
while ( toproduce > BLAKE2B_OUTBYTES )
{
memcpy( in_buffer, out_buffer, BLAKE2B_OUTBYTES );
blake2b( out_buffer, in_buffer, NULL, BLAKE2B_OUTBYTES, BLAKE2B_OUTBYTES, 0 );
memcpy( out, out_buffer, BLAKE2B_OUTBYTES / 2 );
out += BLAKE2B_OUTBYTES / 2;
toproduce -= BLAKE2B_OUTBYTES / 2;
}
memcpy( in_buffer, out_buffer, BLAKE2B_OUTBYTES );
blake2b( out_buffer, in_buffer, NULL, toproduce, BLAKE2B_OUTBYTES, 0 );
memcpy( out, out_buffer, toproduce );
if (outlen <= BLAKE2B_OUTBYTES) {
blake2b_init(&blake_state, outlen);
blake2b_update(&blake_state, (const uint8_t *)&outlen, sizeof(uint32_t));
blake2b_update(&blake_state, (const uint8_t *)in, inlen);
blake2b_final(&blake_state, out, outlen);
} else {
uint8_t out_buffer[BLAKE2B_OUTBYTES];
uint8_t in_buffer[BLAKE2B_OUTBYTES];
blake2b_init(&blake_state, BLAKE2B_OUTBYTES);
blake2b_update(&blake_state, (const uint8_t *)&outlen, sizeof(uint32_t));
blake2b_update(&blake_state, (const uint8_t *)in, inlen);
blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES);
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
out += BLAKE2B_OUTBYTES / 2;
uint32_t toproduce = outlen - BLAKE2B_OUTBYTES / 2;
while (toproduce > BLAKE2B_OUTBYTES) {
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
blake2b(out_buffer, in_buffer, NULL, BLAKE2B_OUTBYTES, BLAKE2B_OUTBYTES,
0);
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
out += BLAKE2B_OUTBYTES / 2;
toproduce -= BLAKE2B_OUTBYTES / 2;
}
return 0;
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
blake2b(out_buffer, in_buffer, NULL, toproduce, BLAKE2B_OUTBYTES, 0);
memcpy(out, out_buffer, toproduce);
}
return 0;
}
/* Argon2 Team - End Code */

View File

@ -7,135 +7,141 @@
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
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/>.
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/>.
*/
#pragma once
#ifndef __BLAKE2B_ROUND_H__
#define __BLAKE2B_ROUND_H__
/* Argon2 Team - Begin Code */
#define LOAD(p) _mm_load_si128( (const __m128i *)(p) )
#define STORE(p,r) _mm_store_si128((__m128i *)(p), r)
#define LOAD(p) _mm_load_si128((const __m128i *)(p))
#define STORE(p, r) _mm_store_si128((__m128i *)(p), r)
/* Argon2 Team - End Code */
#define LOADU(p) _mm_loadu_si128( (const __m128i *)(p) )
#define STOREU(p,r) _mm_storeu_si128((__m128i *)(p), r)
#define LOADU(p) _mm_loadu_si128((const __m128i *)(p))
#define STOREU(p, r) _mm_storeu_si128((__m128i *)(p), r)
#define TOF(reg) _mm_castsi128_ps((reg))
#define TOI(reg) _mm_castps_si128((reg))
#define LIKELY(x) __builtin_expect((x),1)
#define LIKELY(x) __builtin_expect((x), 1)
/* Microarchitecture-specific macros */
#ifndef HAVE_XOP
#ifdef HAVE_SSSE3
#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))))
#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
#define _mm_roti_epi64(r, c) _mm_xor_si128(_mm_srli_epi64( (r), -(c) ),_mm_slli_epi64( (r), 64-(-c) ))
#define _mm_roti_epi64(r, c) \
_mm_xor_si128(_mm_srli_epi64((r), -(c)), _mm_slli_epi64((r), 64 - (-c)))
#endif
#else
/* ... */
#endif
#define G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1) \
row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -32); \
row4h = _mm_roti_epi64(row4h, -32); \
\
row3l = _mm_add_epi64(row3l, row4l); \
row3h = _mm_add_epi64(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -24); \
row2h = _mm_roti_epi64(row2h, -24);
#define G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \
row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -32); \
row4h = _mm_roti_epi64(row4h, -32); \
\
row3l = _mm_add_epi64(row3l, row4l); \
row3h = _mm_add_epi64(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -24); \
row2h = _mm_roti_epi64(row2h, -24); \
#define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \
row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -16); \
row4h = _mm_roti_epi64(row4h, -16); \
\
row3l = _mm_add_epi64(row3l, row4l); \
row3h = _mm_add_epi64(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -63); \
row2h = _mm_roti_epi64(row2h, -63); \
#define G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1) \
row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -16); \
row4h = _mm_roti_epi64(row4h, -16); \
\
row3l = _mm_add_epi64(row3l, row4l); \
row3h = _mm_add_epi64(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -63); \
row2h = _mm_roti_epi64(row2h, -63);
#if defined(HAVE_SSSE3)
#define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
t0 = _mm_alignr_epi8(row2h, row2l, 8); \
t1 = _mm_alignr_epi8(row2l, row2h, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4h, row4l, 8); \
t1 = _mm_alignr_epi8(row4l, row4h, 8); \
row4l = t1; \
#define DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
t0 = _mm_alignr_epi8(row2h, row2l, 8); \
t1 = _mm_alignr_epi8(row2l, row2h, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4h, row4l, 8); \
t1 = _mm_alignr_epi8(row4l, row4h, 8); \
row4l = t1; \
row4h = t0;
#define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
t0 = _mm_alignr_epi8(row2l, row2h, 8); \
t1 = _mm_alignr_epi8(row2h, row2l, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4l, row4h, 8); \
t1 = _mm_alignr_epi8(row4h, row4l, 8); \
row4l = t1; \
#define UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
t0 = _mm_alignr_epi8(row2l, row2h, 8); \
t1 = _mm_alignr_epi8(row2h, row2l, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4l, row4h, 8); \
t1 = _mm_alignr_epi8(row4h, row4l, 8); \
row4l = t1; \
row4h = t0;
#else
#define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
t0 = row4l;\
t1 = row2l;\
row4l = row3l;\
row3l = row3h;\
row3h = row4l;\
row4l = _mm_unpackhi_epi64(row4h, _mm_unpacklo_epi64(t0, t0)); \
row4h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row4h, row4h)); \
row2l = _mm_unpackhi_epi64(row2l, _mm_unpacklo_epi64(row2h, row2h)); \
#define DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
t0 = row4l; \
t1 = row2l; \
row4l = row3l; \
row3l = row3h; \
row3h = row4l; \
row4l = _mm_unpackhi_epi64(row4h, _mm_unpacklo_epi64(t0, t0)); \
row4h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row4h, row4h)); \
row2l = _mm_unpackhi_epi64(row2l, _mm_unpacklo_epi64(row2h, row2h)); \
row2h = _mm_unpackhi_epi64(row2h, _mm_unpacklo_epi64(t1, t1))
#define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
t0 = row3l;\
row3l = row3h;\
row3h = t0;\
t0 = row2l;\
t1 = row4l;\
row2l = _mm_unpackhi_epi64(row2h, _mm_unpacklo_epi64(row2l, row2l)); \
row2h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row2h, row2h)); \
row4l = _mm_unpackhi_epi64(row4l, _mm_unpacklo_epi64(row4h, row4h)); \
#define UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
t0 = row2l; \
t1 = row4l; \
row2l = _mm_unpackhi_epi64(row2h, _mm_unpacklo_epi64(row2l, row2l)); \
row2h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row2h, row2h)); \
row4l = _mm_unpackhi_epi64(row4l, _mm_unpacklo_epi64(row4h, row4h)); \
row4h = _mm_unpackhi_epi64(row4h, _mm_unpacklo_epi64(t1, t1))
#endif
@ -146,27 +152,27 @@
#include "blake2b-load-sse2.h"
#endif
#define ROUND(r) \
LOAD_MSG_ ##r ##_1(b0, b1); \
G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
LOAD_MSG_ ##r ##_2(b0, b1); \
G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
LOAD_MSG_ ##r ##_3(b0, b1); \
G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
LOAD_MSG_ ##r ##_4(b0, b1); \
G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h);
#define ROUND(r) \
LOAD_MSG_##r##_1(b0, b1); \
G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1); \
LOAD_MSG_##r##_2(b0, b1); \
G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1); \
DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
LOAD_MSG_##r##_3(b0, b1); \
G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1); \
LOAD_MSG_##r##_4(b0, b1); \
G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1); \
UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h);
#endif
#define BLAKE2_ROUND(row1l,row1h,row2l,row2h,row3l,row3h,row4l,row4h) \
G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
\
DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
\
G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
\
UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h);
#define BLAKE2_ROUND(row1l, row1h, row2l, row2h, row3l, row3h, row4l, row4h) \
G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
\
DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
\
G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
\
UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h);

View File

@ -1,92 +1,96 @@
#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))))
#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))))
static 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));
static 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(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
row1l = fBlaMka(row1l, row2l); \
row1h = fBlaMka(row1h, row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -32); \
row4h = _mm_roti_epi64(row4h, -32); \
\
row3l = fBlaMka(row3l, row4l); \
row3h = fBlaMka(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -24); \
row2h = _mm_roti_epi64(row2h, -24); \
#define G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
row1l = fBlaMka(row1l, row2l); \
row1h = fBlaMka(row1h, row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -32); \
row4h = _mm_roti_epi64(row4h, -32); \
\
row3l = fBlaMka(row3l, row4l); \
row3h = fBlaMka(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -24); \
row2h = _mm_roti_epi64(row2h, -24);
#define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
row1l = fBlaMka(row1l, row2l); \
row1h = fBlaMka(row1h, row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -16); \
row4h = _mm_roti_epi64(row4h, -16); \
\
row3l = fBlaMka(row3l, row4l); \
row3h = fBlaMka(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -63); \
row2h = _mm_roti_epi64(row2h, -63); \
#define G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
row1l = fBlaMka(row1l, row2l); \
row1h = fBlaMka(row1h, row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -16); \
row4h = _mm_roti_epi64(row4h, -16); \
\
row3l = fBlaMka(row3l, row4l); \
row3h = fBlaMka(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -63); \
row2h = _mm_roti_epi64(row2h, -63);
#define DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
t0 = _mm_alignr_epi8(row2h, row2l, 8); \
t1 = _mm_alignr_epi8(row2l, row2h, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4h, row4l, 8); \
t1 = _mm_alignr_epi8(row4l, row4h, 8); \
row4l = t1; \
row4h = t0;
#define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
t0 = _mm_alignr_epi8(row2h, row2l, 8); \
t1 = _mm_alignr_epi8(row2l, row2h, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4h, row4l, 8); \
t1 = _mm_alignr_epi8(row4l, row4h, 8); \
row4l = t1; \
row4h = t0;
#define UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
t0 = _mm_alignr_epi8(row2l, row2h, 8); \
t1 = _mm_alignr_epi8(row2h, row2l, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4l, row4h, 8); \
t1 = _mm_alignr_epi8(row4h, row4l, 8); \
row4l = t1; \
row4h = t0;
#define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
t0 = _mm_alignr_epi8(row2l, row2h, 8); \
t1 = _mm_alignr_epi8(row2h, row2l, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4l, row4h, 8); \
t1 = _mm_alignr_epi8(row4h, row4l, 8); \
row4l = t1; \
row4h = t0;
#define BLAKE2_ROUND(row1l,row1h,row2l,row2h,row3l,row3h,row4l,row4h) \
G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
\
DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
\
G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
\
UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h);
#define BLAKE2_ROUND(row1l, row1h, row2l, row2h, row3l, row3h, row4l, row4h) \
G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
\
DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
\
G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
\
UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h);

View File

@ -3,42 +3,39 @@
#ifndef __BLAKE_ROUND_MKA_H__
#define __BLAKE_ROUND_MKA_H__
#define G(a, b, c, d) \
a = fBlaMka(a, b); \
d = rotr64(d ^ a, 32); \
c = fBlaMka(c, d); \
b = rotr64(b ^ c, 24); \
a = fBlaMka(a, b); \
d = rotr64(d ^ a, 16); \
c = fBlaMka(c, d); \
b = rotr64(b ^ c, 63);
#define G(a,b,c,d) \
a = fBlaMka(a, b) ; \
d = rotr64(d ^ a, 32); \
c = fBlaMka(c, d); \
b = rotr64(b ^ c, 24); \
a = fBlaMka(a, b) ; \
d = rotr64(d ^ a, 16); \
c = fBlaMka(c, d); \
b = rotr64(b ^ c, 63);
#define BLAKE2_ROUND_NOMSG(v0,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v15) \
G(v0, v4, v8, v12); \
G(v1, v5, v9, v13); \
G(v2, v6, v10, v14); \
G(v3, v7, v11, v15); \
G(v0, v5, v10, v15); \
G(v1, v6, v11, v12); \
G(v2, v7, v8, v13); \
G(v3, v4, v9, v14);
#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \
v12, v13, v14, v15) \
G(v0, v4, v8, v12); \
G(v1, v5, v9, v13); \
G(v2, v6, v10, v14); \
G(v3, v7, v11, v15); \
G(v0, v5, v10, v15); \
G(v1, v6, v11, v12); \
G(v2, v7, v8, v13); \
G(v3, v4, v9, v14);
/*designed by the Lyra PHC team */
static __inline uint64_t fBlaMka( uint64_t x, uint64_t y )
{
uint32_t lessX = ( uint32_t )x;
uint32_t lessY = ( uint32_t )y;
static __inline uint64_t fBlaMka(uint64_t x, uint64_t y) {
uint32_t lessX = (uint32_t)x;
uint32_t lessY = (uint32_t)y;
uint64_t lessZ = ( uint64_t )lessX;
lessZ = lessZ * lessY;
lessZ = lessZ << 1;
uint64_t lessZ = (uint64_t)lessX;
lessZ = lessZ * lessY;
lessZ = lessZ << 1;
uint64_t z = lessZ + x + y;
uint64_t z = lessZ + x + y;
return z;
return z;
}
#endif

View File

@ -29,25 +29,25 @@
#ifndef _BRG_ENDIAN_H
#define _BRG_ENDIAN_H
#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
#if 0
/* Include files where endian defines and byteswap functions may reside */
#if defined( __sun )
# include <sys/isa_defs.h>
#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ )
# include <sys/endian.h>
#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \
defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )
# include <machine/endian.h>
#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
# if !defined( __MINGW32__ ) && !defined( _AIX )
# include <endian.h>
# if !defined( __BEOS__ )
# include <byteswap.h>
# endif
# endif
#if defined(__sun)
#include <sys/isa_defs.h>
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
#include <sys/endian.h>
#elif defined(BSD) && (BSD >= 199103) || defined(__APPLE__) || \
defined(__CYGWIN32__) || defined(__DJGPP__) || defined(__osf__)
#include <machine/endian.h>
#elif defined(__linux__) || defined(__GNUC__) || defined(__GNU_LIBRARY__)
#if !defined(__MINGW32__) && !defined(_AIX)
#include <endian.h>
#if !defined(__BEOS__)
#include <byteswap.h>
#endif
#endif
#endif
#endif
@ -55,89 +55,88 @@
/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */
/* seem to encompass most endian symbol definitions */
#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )
# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#if defined(BIG_ENDIAN) && defined(LITTLE_ENDIAN)
#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
#define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN
#define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#elif defined(BIG_ENDIAN)
#define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(LITTLE_ENDIAN)
#define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )
# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( _BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( _LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#if defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
#if defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN
#define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN
#define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#elif defined(_BIG_ENDIAN)
#define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(_LITTLE_ENDIAN)
#define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )
# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN)
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN
#define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
#define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#elif defined(__BIG_ENDIAN)
#define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(__LITTLE_ENDIAN)
#define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )
# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#if defined(__BIG_ENDIAN__) && defined(__LITTLE_ENDIAN__)
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __BIG_ENDIAN__
#define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
#define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#elif defined(__BIG_ENDIAN__)
#define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(__LITTLE_ENDIAN__)
#define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
/* if the platform byte order could not be determined, then try to */
/* set this define using common machine defines */
#if !defined(PLATFORM_BYTE_ORDER)
#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
defined( vax ) || defined( vms ) || defined( VMS ) || \
defined( __VMS ) || defined( _M_X64 )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#if defined(__alpha__) || defined(__alpha) || defined(i386) || \
defined(__i386__) || defined(_M_I86) || defined(_M_IX86) || \
defined(__OS2__) || defined(sun386) || defined(__TURBOC__) || \
defined(vax) || defined(vms) || defined(VMS) || defined(__VMS) || \
defined(_M_X64)
#define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \
defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(AMIGA) || defined(applec) || defined(__AS400__) || \
defined(_CRAY) || defined(__hppa) || defined(__hp9000) || \
defined(ibm370) || defined(mc68000) || defined(m68k) || \
defined(__MRC__) || defined(__MVS__) || defined(__MWERKS__) || \
defined(sparc) || defined(__sparc) || defined(SYMANTEC_C) || \
defined(__VOS__) || defined(__TIGCC__) || defined(__TANDEM) || \
defined(THINK_C) || defined(__VMCMS__) || defined(_AIX)
#define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(__arm__)
# ifdef __BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# else
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif 1 /* **** EDIT HERE IF NECESSARY **** */
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#ifdef __BIG_ENDIAN
#define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#else
# error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order
#define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#elif 1 /* **** EDIT HERE IF NECESSARY **** */
#define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
#define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#else
#error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order
#endif
#endif
#endif

View File

@ -5,11 +5,12 @@
*
* 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/>.
* 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"
@ -18,8 +19,7 @@
#if defined __STDC_LIB_EXT1__
#define __STDC_WANT_LIB_EXT1__ 1
#endif
#define VC_GE_2005( version ) ( version >= 1400 )
#define VC_GE_2005(version) (version >= 1400)
#include <inttypes.h>
#ifndef _MSC_VER
@ -33,7 +33,6 @@
#include "core.h"
#include "kat.h"
#include "blake2/blake2.h"
#include "blake2/blake2-impl.h"
@ -42,9 +41,8 @@
#define NOT_OPTIMIZED __attribute__((optnone))
#endif
#elif defined(__GNUC__)
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
#define GCC_VERSION \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION >= 40400
#define NOT_OPTIMIZED __attribute__((optimize("O0")))
#endif
@ -54,48 +52,37 @@
#endif
/***************Instance and Position constructors**********/
void init_block_value( block *b, uint8_t in )
{
memset( b->v,in,sizeof( b->v ) );
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 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];
}
}
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];
}
}
/***************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))
{
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
*memory = ( block * )malloc( memory_size );
if ( !*memory )
{
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
return ARGON2_OK;
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)) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
else return ARGON2_MEMORY_ALLOCATION_ERROR;
*memory = (block *)malloc(memory_size);
if (!*memory) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
return ARGON2_OK;
} else
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
/* Function that securely cleans the memory
@ -103,587 +90,522 @@ int allocate_memory( block **memory, uint32_t m_cost )
* @param s Memory size in bytes
*/
static __inline void NOT_OPTIMIZED secure_wipe_memory( void *v, size_t n )
{
#if defined (_MSC_VER ) && VC_GE_2005( _MSC_VER )
SecureZeroMemory( v, n );
static __inline 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 );
#elif defined( __OpenBSD__ )
explicit_bzero( memory, size );
memset_s(v, n);
#elif defined(__OpenBSD__)
explicit_bzero(memory, size);
#else
static void *( *const volatile memset_sec )( void *, int, size_t ) = &memset;
memset_sec( v, 0, n );
static void *(*const volatile memset_sec)(void *, int, size_t) = &memset;
memset_sec(v, 0, n);
#endif
}
/*************************Argon2 internal constants**************************************************/
/*************************Argon2 internal
* constants**************************************************/
/* Version of the algorithm */
const uint32_t ARGON2_VERSION_NUMBER = 0x10;
/* Memory block size in bytes */
#define ARGON2_BLOCK_SIZE 1024
#define ARGON2_WORDS_IN_BLOCK (ARGON2_BLOCK_SIZE/8)
#define ARGON2_BLOCK_SIZE 1024
#define ARGON2_WORDS_IN_BLOCK (ARGON2_BLOCK_SIZE / 8)
const uint32_t ARGON2_QWORDS_IN_BLOCK = 64; /*Dependent values!*/
/* Number of pseudo-random values generated by one call to Blake in Argon2i to generate reference block positions*/
/* Number of pseudo-random values generated by one call to Blake in Argon2i to
* generate reference block positions*/
const uint32_t ARGON2_ADDRESSES_IN_BLOCK = 128;
/*********Memory functions*/
void clear_memory( Argon2_instance_t *instance, bool clear )
{
if ( instance->memory != NULL && clear )
{
secure_wipe_memory( instance->memory, sizeof ( block ) * instance->memory_blocks );
}
void clear_memory(Argon2_instance_t *instance, bool clear) {
if (instance->memory != NULL && clear) {
secure_wipe_memory(instance->memory,
sizeof(block) * instance->memory_blocks);
}
}
void free_memory( block *memory )
{
if ( memory != NULL )
{
free( memory );
}
void free_memory(block *memory) {
if (memory != NULL) {
free(memory);
}
}
void finalize( const Argon2_Context *context, Argon2_instance_t *instance )
{
if ( context != NULL && instance != NULL )
{
block blockhash;
copy_block( &blockhash, instance->memory+ instance->lane_length - 1 );
// XOR the last blocks
for ( uint32_t 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
blake2b_long( context->out, ( uint8_t * ) blockhash.v, context->outlen, ARGON2_BLOCK_SIZE );
secure_wipe_memory( blockhash.v, ARGON2_BLOCK_SIZE ); //clear the blockhash
if( context->print ) //Shall we print the output tag?
{
print_tag( context->out, context->outlen );
}
// Clear memory
clear_memory( instance, context->clear_memory );
// Deallocate the memory
if ( NULL != context->free_cbk )
{
context->free_cbk( ( uint8_t * ) instance->memory, instance->memory_blocks * sizeof ( block ) );
}
else
{
free_memory( instance->memory );
}
void finalize(const Argon2_Context *context, Argon2_instance_t *instance) {
if (context != NULL && instance != NULL) {
block blockhash;
copy_block(&blockhash, instance->memory + instance->lane_length - 1);
// XOR the last blocks
for (uint32_t 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
blake2b_long(context->out, (uint8_t *)blockhash.v, context->outlen,
ARGON2_BLOCK_SIZE);
secure_wipe_memory(blockhash.v, ARGON2_BLOCK_SIZE); // clear the blockhash
if (context->print) // Shall we print the output tag?
{
print_tag(context->out, context->outlen);
}
// Clear memory
clear_memory(instance, context->clear_memory);
// Deallocate the memory
if (NULL != context->free_cbk) {
context->free_cbk((uint8_t *)instance->memory,
instance->memory_blocks * sizeof(block));
} else {
free_memory(instance->memory);
}
}
}
uint32_t index_alpha( const Argon2_instance_t *instance, const Argon2_position_t *position, uint32_t pseudo_rand, bool 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;
uint32_t index_alpha(const Argon2_instance_t *instance,
const Argon2_position_t *position, uint32_t pseudo_rand,
bool 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;
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 );
}
}
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 );
}
} 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 */
uint64_t 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.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce
* relative position */
uint64_t 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 */
uint32_t start_position = 0;
/* 1.2.5 Computing starting position */
uint32_t start_position = 0;
if ( 0 != position->pass )
{
start_position = ( position->slice == ARGON2_SYNC_POINTS - 1 ) ? 0 : ( position->slice + 1 ) * instance->segment_length;
}
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 */
uint32_t absolute_position = ( start_position + relative_position ) % instance->lane_length; // absolute position
return absolute_position;
/* 1.2.6. Computing absolute position */
uint32_t absolute_position = (start_position + relative_position) %
instance->lane_length; // absolute position
return absolute_position;
}
void fill_memory_blocks( Argon2_instance_t *instance )
{
if ( instance == NULL )
{
return;
}
void fill_memory_blocks(Argon2_instance_t *instance) {
if (instance == NULL) {
return;
}
for ( uint32_t r = 0; r < instance->passes; ++r )
{
for ( uint8_t s = 0; s < ARGON2_SYNC_POINTS; ++s )
{
for (uint32_t r = 0; r < instance->passes; ++r) {
for (uint8_t s = 0; s < ARGON2_SYNC_POINTS; ++s) {
#ifndef _MSC_VER
//1. Allocating space for threads
pthread_t *thread = malloc( sizeof( pthread_t )*( instance->lanes ) );
Argon2_thread_data *thr_data = malloc( sizeof( Argon2_thread_data )*( instance->lanes ) );
pthread_attr_t attr;
int rc;
void *status;
pthread_attr_init( &attr );
pthread_attr_setdetachstate( &attr,PTHREAD_CREATE_JOINABLE );
// 1. Allocating space for threads
pthread_t *thread = malloc(sizeof(pthread_t) * (instance->lanes));
Argon2_thread_data *thr_data =
malloc(sizeof(Argon2_thread_data) * (instance->lanes));
pthread_attr_t attr;
int rc;
void *status;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
//2. Calling threads
for ( uint32_t l = 0; l < instance->lanes; ++l )
{
//2.1 Join a thread if limit is exceeded
if( l>=instance->threads )
{
rc = pthread_join( thread[l-instance->threads],&status );
// 2. Calling threads
for (uint32_t l = 0; l < instance->lanes; ++l) {
// 2.1 Join a thread if limit is exceeded
if (l >= instance->threads) {
rc = pthread_join(thread[l - instance->threads], &status);
if ( rc )
{
printf( "ERROR; return code from pthread_join() is %d\n", rc );
exit( -1 );
}
}
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
}
//2.2 Create thread
Argon2_position_t position = {r,l,s,0};
thr_data[l].instance_ptr = instance;//preparing the thread input
memcpy( &( thr_data[l].pos ), &position, sizeof( Argon2_position_t ) );
rc = pthread_create( &thread[l],&attr,fill_segment_thr,( void * )&thr_data[l] );
// 2.2 Create thread
Argon2_position_t position = {r, l, s, 0};
thr_data[l].instance_ptr = instance; // preparing the thread input
memcpy(&(thr_data[l].pos), &position, sizeof(Argon2_position_t));
rc = pthread_create(&thread[l], &attr, fill_segment_thr,
(void *)&thr_data[l]);
//FillSegment(instance, position); //Non-thread equivalent of the lines above
}
// FillSegment(instance, position); //Non-thread equivalent of the
// lines above
}
//3. Joining remaining threads
for ( uint32_t l = instance->lanes - instance->threads; l < instance->lanes; ++l )
{
rc = pthread_join( thread[l],&status );
// 3. Joining remaining threads
for (uint32_t l = instance->lanes - instance->threads;
l < instance->lanes; ++l) {
rc = pthread_join(thread[l], &status);
if ( rc )
{
printf( "ERROR; return code from pthread_join() is %d\n", rc );
exit( -1 );
}
}
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
}
free( thread );
pthread_attr_destroy( &attr );
free( thr_data );
#else //No threads for Windows
for (uint32_t l = 0; l < instance->lanes; ++l)
{
Argon2_position_t position = { r, l, s, 0 };
fill_segment(instance, position);
}
free(thread);
pthread_attr_destroy(&attr);
free(thr_data);
#else // No threads for Windows
for (uint32_t l = 0; l < instance->lanes; ++l) {
Argon2_position_t position = {r, l, s, 0};
fill_segment(instance, position);
}
#endif
}
if( instance->print_internals )
{
internal_kat( instance, r ); // Print all memory blocks
}
}
if (instance->print_internals) {
internal_kat(instance, r); // Print all memory blocks
}
}
}
int validate_inputs( const Argon2_Context *context )
{
if ( NULL == context )
{
return ARGON2_INCORRECT_PARAMETER;
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 length */
if (NULL == context->pwd) {
if (0 != context->pwdlen) {
return ARGON2_PWD_PTR_MISMATCH;
}
} else {
if (ARGON2_MIN_PWD_LENGTH != 0 && ARGON2_MIN_PWD_LENGTH > context->pwdlen) {
return ARGON2_PWD_TOO_SHORT;
}
if ( NULL == context->out )
{
return ARGON2_OUTPUT_PTR_NULL;
if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) {
return ARGON2_PWD_TOO_LONG;
}
}
/* Validate salt length */
if (NULL == context->salt) {
if (0 != context->saltlen) {
return ARGON2_SALT_PTR_MISMATCH;
}
} else {
if (ARGON2_MIN_SALT_LENGTH > context->saltlen) {
return ARGON2_SALT_TOO_SHORT;
}
/* Validate output length */
if ( ARGON2_MIN_OUTLEN > context->outlen )
{
return ARGON2_OUTPUT_TOO_SHORT;
if (ARGON2_MAX_SALT_LENGTH < context->saltlen) {
return ARGON2_SALT_TOO_LONG;
}
}
/* Validate secret length */
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_OUTLEN < context->outlen )
{
return ARGON2_OUTPUT_TOO_LONG;
if (ARGON2_MAX_SECRET < context->secretlen) {
return ARGON2_SECRET_TOO_LONG;
}
}
/* Validate associated data */
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;
}
/* Validate password length */
if ( NULL == context->pwd )
{
if ( 0 != context->pwdlen )
{
return ARGON2_PWD_PTR_MISMATCH;
}
if (ARGON2_MAX_AD_LENGTH < context->adlen) {
return ARGON2_AD_TOO_LONG;
}
else
{
if ( ARGON2_MIN_PWD_LENGTH != 0 && ARGON2_MIN_PWD_LENGTH > context->pwdlen )
{
return ARGON2_PWD_TOO_SHORT;
}
}
if ( ARGON2_MAX_PWD_LENGTH < context->pwdlen )
{
return ARGON2_PWD_TOO_LONG;
}
}
/* Validate memory cost */
if (ARGON2_MIN_MEMORY > context->m_cost) {
return ARGON2_MEMORY_TOO_LITTLE;
}
/* Validate salt length */
if ( NULL == context->salt )
{
if ( 0 != context->saltlen )
{
return ARGON2_SALT_PTR_MISMATCH;
}
}
else
{
if ( ARGON2_MIN_SALT_LENGTH > context->saltlen )
{
return ARGON2_SALT_TOO_SHORT;
}
if (ARGON2_MAX_MEMORY < context->m_cost) {
return ARGON2_MEMORY_TOO_MUCH;
}
if ( ARGON2_MAX_SALT_LENGTH < context->saltlen )
{
return ARGON2_SALT_TOO_LONG;
}
}
/* Validate time cost */
if (ARGON2_MIN_TIME > context->t_cost) {
return ARGON2_TIME_TOO_SMALL;
}
/* Validate secret length */
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_TIME < context->t_cost) {
return ARGON2_TIME_TOO_LARGE;
}
if ( ARGON2_MAX_SECRET < context->secretlen )
{
return ARGON2_SECRET_TOO_LONG;
}
}
/* Validate lanes */
if (ARGON2_MIN_LANES > context->lanes) {
return ARGON2_LANES_TOO_FEW;
}
/* Validate associated data */
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_LANES < context->lanes) {
return ARGON2_LANES_TOO_MANY;
}
if ( ARGON2_MAX_AD_LENGTH < context->adlen )
{
return ARGON2_AD_TOO_LONG;
}
}
/* Validate threads */
if (ARGON2_MIN_THREADS > context->threads) {
return ARGON2_THREADS_TOO_FEW;
}
/* Validate memory cost */
if ( ARGON2_MIN_MEMORY > context->m_cost )
{
return ARGON2_MEMORY_TOO_LITTLE;
}
if (ARGON2_MAX_THREADS < context->threads) {
return ARGON2_THREADS_TOO_MANY;
}
if ( ARGON2_MAX_MEMORY < context->m_cost )
{
return ARGON2_MEMORY_TOO_MUCH;
}
if (NULL != context->allocate_cbk && NULL == context->free_cbk) {
return ARGON2_FREE_MEMORY_CBK_NULL;
}
/* Validate time cost */
if ( ARGON2_MIN_TIME > context->t_cost )
{
return ARGON2_TIME_TOO_SMALL;
}
if (NULL == context->allocate_cbk && NULL != context->free_cbk) {
return ARGON2_ALLOCATE_MEMORY_CBK_NULL;
}
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;
return ARGON2_OK;
}
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)
for ( uint32_t l = 0; l < instance->lanes; ++l )
{
store32( blockhash+ARGON2_PREHASH_DIGEST_LENGTH,0 );
store32( blockhash+ARGON2_PREHASH_DIGEST_LENGTH + 4,l );
blake2b_long( ( uint8_t * ) ( instance->memory[l * instance->lane_length].v ), blockhash, ARGON2_BLOCK_SIZE, ARGON2_PREHASH_SEED_LENGTH );
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)
for (uint32_t l = 0; l < instance->lanes; ++l) {
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
blake2b_long((uint8_t *)(instance->memory[l * instance->lane_length].v),
blockhash, ARGON2_BLOCK_SIZE, ARGON2_PREHASH_SEED_LENGTH);
store32( blockhash+ARGON2_PREHASH_DIGEST_LENGTH,1 );
blake2b_long( ( uint8_t * ) ( instance->memory[l * instance->lane_length + 1].v ), blockhash, ARGON2_BLOCK_SIZE, ARGON2_PREHASH_SEED_LENGTH );
}
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
blake2b_long((uint8_t *)(instance->memory[l * instance->lane_length + 1].v),
blockhash, ARGON2_BLOCK_SIZE, ARGON2_PREHASH_SEED_LENGTH);
}
}
void initial_hash( uint8_t *blockhash, Argon2_Context *context, Argon2_type type )
{
blake2b_state BlakeHash;
uint8_t value[sizeof ( uint32_t )];
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;
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->clear_password) {
secure_wipe_memory(context->pwd, context->pwdlen);
context->pwdlen = 0;
}
}
blake2b_init( &BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH );
store32(&value, context->saltlen);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32( &value, context->lanes );
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->outlen );
blake2b_update( &BlakeHash, ( const uint8_t * ) &value, sizeof ( value ) );
store32(&value, context->secretlen);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32( &value, context->m_cost );
blake2b_update( &BlakeHash, ( const uint8_t * ) &value, sizeof ( value ) );
if (context->secret != NULL) {
blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
context->secretlen);
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->clear_password )
{
secure_wipe_memory( context->pwd, context->pwdlen );
context->pwdlen = 0;
}
if (context->clear_secret) {
secure_wipe_memory(context->secret, context->secretlen);
context->secretlen = 0;
}
}
store32( &value, context->saltlen );
blake2b_update( &BlakeHash, ( const uint8_t * ) &value, sizeof ( value ) );
store32(&value, context->adlen);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
if ( context->salt != NULL )
{
blake2b_update( &BlakeHash, ( const uint8_t * ) context->salt, context->saltlen );
}
if (context->ad != NULL) {
blake2b_update(&BlakeHash, (const uint8_t *)context->ad, context->adlen);
}
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->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 );
blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
}
int initialize( Argon2_instance_t *instance, Argon2_Context *context )
{
if ( instance == NULL || context == NULL )
return ARGON2_INCORRECT_PARAMETER;
int initialize(Argon2_instance_t *instance, Argon2_Context *context) {
if (instance == NULL || context == NULL)
return ARGON2_INCORRECT_PARAMETER;
// 1. Memory allocation
int result = ARGON2_OK;
// 1. Memory allocation
int result = ARGON2_OK;
if ( NULL != context->allocate_cbk )
{
result = context->allocate_cbk( ( uint8_t ** )&( instance->memory ), instance->memory_blocks * ARGON2_BLOCK_SIZE );
}
else
{
result = allocate_memory( &( instance->memory ), instance->memory_blocks );
}
if (NULL != context->allocate_cbk) {
result = context->allocate_cbk((uint8_t **)&(instance->memory),
instance->memory_blocks * ARGON2_BLOCK_SIZE);
} else {
result = allocate_memory(&(instance->memory), instance->memory_blocks);
}
if ( ARGON2_OK != result )
{
return result;
}
if (ARGON2_OK != result) {
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
secure_wipe_memory( blockhash + ARGON2_PREHASH_DIGEST_LENGTH, ARGON2_PREHASH_SEED_LENGTH - ARGON2_PREHASH_DIGEST_LENGTH );
// 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
secure_wipe_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
ARGON2_PREHASH_SEED_LENGTH - ARGON2_PREHASH_DIGEST_LENGTH);
if( context->print )
{
initial_kat( blockhash, context, instance->type );
}
if (context->print) {
initial_kat(blockhash, context, instance->type);
}
// 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 );
// 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;
return ARGON2_OK;
}
int argon2_core( Argon2_Context *context, Argon2_type type )
{
/* 1. Validate all inputs */
int result = validate_inputs( context );
int argon2_core(Argon2_Context *context, Argon2_type type) {
/* 1. Validate all inputs */
int result = validate_inputs(context);
if ( ARGON2_OK != result )
{
return result;
}
if (ARGON2_OK != result) {
return result;
}
if ( Argon2_d != type && Argon2_i != type )
{
return ARGON2_INCORRECT_TYPE;
}
if (Argon2_d != type && Argon2_i != type) {
return ARGON2_INCORRECT_TYPE;
}
/* 2. Align memory size */
// Minimum memory_blocks = 8L blocks, where L is the number of lanes
uint32_t memory_blocks = context->m_cost;
/* 2. Align memory size */
// Minimum memory_blocks = 8L blocks, where L is the number of lanes
uint32_t memory_blocks = context->m_cost;
if ( memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes )
{
memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
}
if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) {
memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
}
uint32_t segment_length = memory_blocks / ( context->lanes * ARGON2_SYNC_POINTS );
bool print_internals = context->print;
// Ensure that all segments have equal length
memory_blocks = segment_length * ( context->lanes * ARGON2_SYNC_POINTS );
Argon2_instance_t instance = { NULL, context->t_cost, memory_blocks, segment_length,
segment_length * ARGON2_SYNC_POINTS, context->lanes, context->threads, type, print_internals
};
uint32_t segment_length =
memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
bool print_internals = context->print;
// Ensure that all segments have equal length
memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
Argon2_instance_t instance = {NULL,
context->t_cost,
memory_blocks,
segment_length,
segment_length * ARGON2_SYNC_POINTS,
context->lanes,
context->threads,
type,
print_internals};
/* 3. Initialization: Hashing inputs, allocating memory, filling first blocks */
result = initialize( &instance, context );
/* 3. Initialization: Hashing inputs, allocating memory, filling first blocks
*/
result = initialize(&instance, context);
if ( ARGON2_OK != result )
{
return result;
}
if (ARGON2_OK != result) {
return result;
}
/* 4. Filling memory */
fill_memory_blocks( &instance );
/* 4. Filling memory */
fill_memory_blocks(&instance);
/* 5. Finalization */
finalize( context, &instance );
/* 5. Finalization */
finalize(context, &instance);
return ARGON2_OK;
return ARGON2_OK;
}
#ifndef _MSC_VER /* No threads for Windows*/
void *fill_segment_thr( void *thread_data )
{
Argon2_thread_data *my_data = ( Argon2_thread_data * )thread_data;
fill_segment( my_data->instance_ptr, my_data->pos );
pthread_exit( thread_data );
#ifndef _MSC_VER /* No threads for Windows*/
void *fill_segment_thr(void *thread_data) {
Argon2_thread_data *my_data = (Argon2_thread_data *)thread_data;
fill_segment(my_data->instance_ptr, my_data->pos);
pthread_exit(thread_data);
}
#endif

View File

@ -5,104 +5,104 @@
*
* 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/>.
* 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/>.
*/
#pragma once
#ifndef __ARGON2_CORE_H__
#define __ARGON2_CORE_H__
/*************************Argon2 internal constants**************************************************/
/*************************Argon2 internal
* constants**************************************************/
/* Version of the algorithm */
extern const uint32_t ARGON2_VERSION_NUMBER;
/* Memory block size in bytes */
#define ARGON2_BLOCK_SIZE 1024
#define ARGON2_WORDS_IN_BLOCK (ARGON2_BLOCK_SIZE/8)
extern const uint32_t ARGON2_QWORDS_IN_BLOCK ; /*Dependent values!*/
#define ARGON2_BLOCK_SIZE 1024
#define ARGON2_WORDS_IN_BLOCK (ARGON2_BLOCK_SIZE / 8)
extern const uint32_t ARGON2_QWORDS_IN_BLOCK; /*Dependent values!*/
/* Number of pseudo-random values generated by one call to Blake in Argon2i to generate reference block positions*/
/* Number of pseudo-random values generated by one call to Blake in Argon2i to
* generate reference block positions*/
extern const uint32_t ARGON2_ADDRESSES_IN_BLOCK;
/* Pre-hashing digest length and its extension*/
#define ARGON2_PREHASH_DIGEST_LENGTH 64
#define ARGON2_PREHASH_SEED_LENGTH 72 /*Dependent values!*/
#define ARGON2_PREHASH_DIGEST_LENGTH 64
#define ARGON2_PREHASH_SEED_LENGTH 72 /*Dependent values!*/
/* Argon2 primitive type */
typedef enum _Argon2_type
{
Argon2_d=0,
Argon2_i=1,
typedef enum _Argon2_type {
Argon2_d = 0,
Argon2_i = 1,
} Argon2_type;
/*************************Argon2 internal data types**************************************************/
/*************************Argon2 internal data
* types**************************************************/
/*
* 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 bounds checking).
* Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
* bounds checking).
*/
#ifndef _MSC_VER
typedef struct _block
{
uint64_t v[ARGON2_WORDS_IN_BLOCK];
} __attribute__ ( ( aligned ( 16 ) ) ) block;
typedef struct _block {
uint64_t v[ARGON2_WORDS_IN_BLOCK];
} __attribute__((aligned(16))) block;
#else
typedef struct _block
{
uint64_t v[ARGON2_WORDS_IN_BLOCK];
} __declspec( align( 16 ) ) block;
typedef struct _block {
uint64_t v[ARGON2_WORDS_IN_BLOCK];
} __declspec(align(16)) block;
#endif
/*****************Functions that work with the block******************/
//Initialize each byte of the block with @in
extern void init_block_value( block *b, uint8_t in );
// Initialize each byte of the block with @in
extern void init_block_value(block *b, uint8_t in);
//Copy block @src to block @dst
extern void copy_block( block *dst, const block *src );
//XOR @src onto @dst bytewise
extern void xor_block( block *dst, const block *src );
// Copy block @src to block @dst
extern void copy_block(block *dst, const block *src);
// XOR @src onto @dst bytewise
extern void xor_block(block *dst, const block *src);
/*
* Argon2 instance: memory pointer, number of passes, amount of memory, type, and derived values.
* Used to evaluate the number and location of blocks to construct in each thread
* Argon2 instance: memory pointer, number of passes, amount of memory, type,
* and derived values.
* Used to evaluate the number and location of blocks to construct in each
* thread
*/
typedef struct _Argon2_instance_t
{
block *memory; //Memory pointer
const uint32_t passes; //Number of passes
const uint32_t memory_blocks; //Number of blocks in memory
const uint32_t segment_length;
const uint32_t lane_length;
const uint32_t lanes;
const uint32_t threads;
const Argon2_type type;
const bool print_internals; //whether to print the memory blocks
typedef struct _Argon2_instance_t {
block *memory; // Memory pointer
const uint32_t passes; // Number of passes
const uint32_t memory_blocks; // Number of blocks in memory
const uint32_t segment_length;
const uint32_t lane_length;
const uint32_t lanes;
const uint32_t threads;
const Argon2_type type;
const bool print_internals; // whether to print the memory blocks
} Argon2_instance_t;
/*
* Argon2 position: where we construct the block right now. Used to distribute work between threads.
* Argon2 position: where we construct the block right now. Used to distribute
* work between threads.
*/
typedef struct _Argon2_position_t
{
const uint32_t pass;
const uint32_t lane;
const uint8_t slice;
uint32_t index;
typedef struct _Argon2_position_t {
const uint32_t pass;
const uint32_t lane;
const uint8_t slice;
uint32_t index;
} Argon2_position_t;
/*Struct that holds the inputs for thread handling FillSegment*/
typedef struct _Argon2_thread_data
{
Argon2_instance_t *instance_ptr;
Argon2_position_t pos;
typedef struct _Argon2_thread_data {
Argon2_instance_t *instance_ptr;
Argon2_position_t pos;
} Argon2_thread_data;
/*Macro for endianness conversion*/
@ -113,54 +113,62 @@ typedef struct _Argon2_thread_data
#define BSWAP32(x) __builtin_bswap32(x)
#endif
/*************************Argon2 core functions**************************************************/
/*************************Argon2 core
* functions**************************************************/
/* Allocates memory to the given pointer
* @param memory pointer to the pointer to the memory
* @param m_cost number of blocks to allocate in the memory
* @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(block **memory, uint32_t m_cost);
/* Clears memory
* @param instance pointer to the current instance
* @param clear_memory indicates if we clear the memory with zeros.
*/
void clear_memory( Argon2_instance_t *instance, bool clear );
void clear_memory(Argon2_instance_t *instance, bool clear);
/* Deallocates memory
* @param memory pointer to the blocks
*/
void free_memory( block *memory );
void free_memory(block *memory);
/*
* Computes absolute position of reference block in the lane following a skewed distribution and using a pseudo-random value as input
* Computes absolute position of reference block in the lane following a skewed
* distribution and using a pseudo-random value as input
* @param instance Pointer to the current instance
* @param position Pointer to the current position
* @param pseudo_rand 32-bit pseudo-random value used to determine the position
* @param same_lane Indicates if the block will be taken from the current lane. If so we can reference the current segment
* @param same_lane Indicates if the block will be taken from the current lane.
* If so we can reference the current segment
* @pre All pointers must be valid
*/
uint32_t index_alpha( const Argon2_instance_t *instance, const Argon2_position_t *position, uint32_t pseudo_rand, bool same_lane );
uint32_t index_alpha(const Argon2_instance_t *instance,
const Argon2_position_t *position, uint32_t pseudo_rand,
bool same_lane);
/*
* Function that validates all inputs against predefined restrictions and return an error code
* Function that validates all inputs against predefined restrictions and return
* an error code
* @param context Pointer to current Argon2 context
* @return ARGON2_OK if everything is all right, otherwise one of error codes (all defined in <argon2.h>
* @return ARGON2_OK if everything is all right, otherwise one of error codes
* (all defined in <argon2.h>
*/
int validate_inputs( const Argon2_Context *context );
int validate_inputs(const Argon2_Context *context);
/*
* Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears password and secret if needed
* @param context Pointer to the Argon2 internal structure containing memory pointer, and parameters for time and space requirements.
* Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears
* password and secret if needed
* @param context Pointer to the Argon2 internal structure containing memory
* pointer, and parameters for time and space requirements.
* @param blockhash Buffer for pre-hashing digest
* @param type Argon2 type
* @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes allocated
* @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes
* allocated
*/
void initial_hash( uint8_t *blockhash, Argon2_Context *context, Argon2_type type );
void initial_hash(uint8_t *blockhash, Argon2_Context *context,
Argon2_type type);
/*
* Function creates first 2 blocks per lane
@ -168,58 +176,62 @@ void initial_hash( uint8_t *blockhash, Argon2_Context *context, Argon2_type typ
* @param blockhash Pointer to the pre-hashing digest
* @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_firsts_blocks(uint8_t *blockhash, const Argon2_instance_t *instance);
/*
* Function allocates memory, hashes the inputs with Blake, and creates first two blocks. Returns the pointer to the main memory with 2 blocks per lane
* Function allocates memory, hashes the inputs with Blake, and creates first
* two blocks. Returns the pointer to the main memory with 2 blocks per lane
* initialized
* @param context Pointer to the Argon2 internal structure containing memory pointer, and parameters for time and space requirements.
* @param context Pointer to the Argon2 internal structure containing memory
* pointer, and parameters for time and space requirements.
* @param instance Current Argon2 instance
* @return Zero if successful, -1 if memory failed to allocate. @context->state will be modified if successful.
* @return Zero if successful, -1 if memory failed to allocate. @context->state
* will be modified if successful.
*/
int initialize( Argon2_instance_t *instance, Argon2_Context *context );
int initialize(Argon2_instance_t *instance, Argon2_Context *context);
/*
* XORing the last block of each lane, hashing it, making the tag. Deallocates the memory.
* @param context Pointer to current Argon2 context (use only the out parameters from it)
* XORing the last block of each lane, hashing it, making the tag. Deallocates
* the memory.
* @param context Pointer to current Argon2 context (use only the out parameters
* from it)
* @param instance Pointer to current instance of Argon2
* @pre instance->state must point to necessary amount of memory
* @pre context->out must point to outlen bytes of memory
* @pre if context->free_cbk is not NULL, it should point to a function that deallocates memory
* @pre if context->free_cbk is not NULL, it should point to a function that
* deallocates memory
*/
void finalize( const Argon2_Context *context, Argon2_instance_t *instance );
void finalize(const Argon2_Context *context, Argon2_instance_t *instance);
/*
* Function that fills the segment using previous segments also from other threads
* 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
*/
extern void fill_segment( const Argon2_instance_t *instance, Argon2_position_t position );
extern void fill_segment(const Argon2_instance_t *instance,
Argon2_position_t position);
/*
* Wrapper for FillSegment for <pthread> library
* @param thread_data Pointer to the structure that holds inputs for FillSegment
* @pre all block pointers must be valid
*/
void *fill_segment_thr( void *Argon2_thread_data );
void *fill_segment_thr(void *Argon2_thread_data);
/*
* Function that fills the entire memory t_cost times based on the first two blocks in each lane
* Function that fills the entire memory t_cost times based on the first two
* blocks in each lane
* @param instance Pointer to the current instance
*/
void fill_memory_blocks( Argon2_instance_t *instance );
void 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 );
int argon2_core(Argon2_Context *context, Argon2_type type);
#endif

View File

@ -7,8 +7,10 @@
*
* 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/>.
* 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 "argon2.h"
@ -22,25 +24,21 @@
* 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) ((((-((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)
#define EQ(x, y) ((((-((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) & '/');
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 some bytes to Base64. 'dst_len' is the length (in characters)
* of the output buffer 'dst'; if that buffer is not large enough to
@ -49,45 +47,42 @@ b64_byte_to_char(unsigned x)
* 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;
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 ++ = 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;
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++ = 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;
}
/* ==================================================================== */
/*
* Code specific to Argon2i.
@ -108,59 +103,60 @@ to_base64(char *dst, size_t dst_len, const void *src, size_t src_len)
* The output length is always exactly 32 bytes.
*/
int encode_string(char *dst, size_t dst_len, Argon2_Context *ctx) {
#define SS(str) \
do { \
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)
int
encode_string( char *dst, size_t dst_len, Argon2_Context *ctx )
{
#define SS(str) do { \
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) \
do { \
char tmp[30]; \
sprintf(tmp, "%lu", (unsigned long)(x)); \
SS(tmp); \
} while (0);
#define SX(x) do { \
char tmp[30]; \
sprintf(tmp, "%lu", (unsigned long)(x)); \
SS(tmp); \
} while (0); \
#define SB(buf, len) \
do { \
size_t sb_len = to_base64(dst, dst_len, buf, len); \
if (sb_len == (size_t)-1) { \
return 0; \
} \
dst += sb_len; \
dst_len -= sb_len; \
} while (0);
#define SB(buf, len) do { \
size_t sb_len = to_base64(dst, dst_len, buf, len); \
if (sb_len == (size_t)-1) { \
return 0; \
} \
dst += sb_len; \
dst_len -= sb_len; \
} while (0); \
SS("$argon2i$m=");
SX(ctx->m_cost);
SS(",t=");
SX(ctx->t_cost);
SS(",p=");
SX(ctx->lanes);
SS( "$argon2i$m=" );
SX( ctx->m_cost );
SS( ",t=" );
SX( ctx->t_cost );
SS( ",p=" );
SX( ctx->lanes );
if (ctx->adlen > 0) {
SS(",data=");
SB(ctx->ad, ctx->adlen);
}
if ( ctx->adlen > 0 )
{
SS( ",data=" );
SB( ctx->ad, ctx->adlen );
}
if ( ctx->saltlen == 0 ) return 1;
SS( "$" );
SB( ctx->salt, ctx->saltlen );
if ( ctx->outlen == 0 ) return 1;
SS( "$" );
SB( ctx->out, ctx->outlen );
if (ctx->saltlen == 0)
return 1;
SS("$");
SB(ctx->salt, ctx->saltlen);
if (ctx->outlen == 0)
return 1;
SS("$");
SB(ctx->out, ctx->outlen);
return 1;
#undef SS
#undef SX
#undef SB

217
src/kat.c
View File

@ -6,146 +6,127 @@
*
* 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/>.
* 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 <inttypes.h>
#include "argon2.h"
#include "core.h"
void initial_kat(const uint8_t *blockhash, const Argon2_Context *context,
Argon2_type type) {
FILE *fp = fopen(ARGON2_KAT_FILENAME, "a+");
if (fp && blockhash != NULL && context != NULL) {
fprintf(fp, "=======================================");
void initial_kat( const uint8_t *blockhash, const Argon2_Context *context, Argon2_type type )
{
FILE *fp = fopen( ARGON2_KAT_FILENAME, "a+" );
switch (type) {
case Argon2_d:
fprintf(fp, "Argon2d\n");
break;
if ( fp && blockhash != NULL && context != NULL )
{
fprintf( fp, "=======================================" );
case Argon2_i:
fprintf(fp, "Argon2i\n");
break;
switch ( type )
{
case Argon2_d:
fprintf( fp, "Argon2d\n" );
break;
case Argon2_i:
fprintf( fp, "Argon2i\n" );
break;
default:
break;
}
fprintf( fp, "Iterations: %d, Memory: %d KBytes, Parallelism: %d lanes, Tag length: %d bytes\n",
context->t_cost, context->m_cost, context->lanes, context->outlen );
fprintf( fp, "Password[%d]: ", context->pwdlen );
if ( context->clear_password )
{
fprintf( fp, "CLEARED\n" );
}
else
{
for ( unsigned i = 0; i < context->pwdlen; ++i )
{
fprintf( fp, "%2.2x ", ( ( unsigned char * ) context->pwd )[i] );
}
fprintf( fp, "\n" );
}
fprintf( fp, "Salt[%d]: ", context->saltlen );
for ( unsigned i = 0; i < context->saltlen; ++i )
{
fprintf( fp, "%2.2x ", ( ( unsigned char * ) context->salt )[i] );
}
fprintf( fp, "\n" );
fprintf( fp, "Secret[%d]: ", context->secretlen );
if ( context->clear_secret )
{
fprintf( fp, "CLEARED\n" );
}
else
{
for ( unsigned i = 0; i < context->secretlen; ++i )
{
fprintf( fp, "%2.2x ", ( ( unsigned char * ) context->secret )[i] );
}
fprintf( fp, "\n" );
}
fprintf( fp, "Associated data[%d]: ", context->adlen );
for ( unsigned i = 0; i < context->adlen; ++i )
{
fprintf( fp, "%2.2x ", ( ( unsigned char * ) context->ad )[i] );
}
fprintf( fp, "\n" );
fprintf( fp, "Pre-hashing digest: " );
for ( unsigned i = 0; i < ARGON2_PREHASH_DIGEST_LENGTH; ++i )
{
fprintf( fp, "%2.2x ", ( ( unsigned char * ) blockhash )[i] );
}
fprintf( fp, "\n" );
fclose( fp );
default:
break;
}
fprintf(fp, "Iterations: %d, Memory: %d KBytes, Parallelism: %d lanes, Tag "
"length: %d bytes\n",
context->t_cost, context->m_cost, context->lanes, context->outlen);
fprintf(fp, "Password[%d]: ", context->pwdlen);
if (context->clear_password) {
fprintf(fp, "CLEARED\n");
} else {
for (unsigned i = 0; i < context->pwdlen; ++i) {
fprintf(fp, "%2.2x ", ((unsigned char *)context->pwd)[i]);
}
fprintf(fp, "\n");
}
fprintf(fp, "Salt[%d]: ", context->saltlen);
for (unsigned i = 0; i < context->saltlen; ++i) {
fprintf(fp, "%2.2x ", ((unsigned char *)context->salt)[i]);
}
fprintf(fp, "\n");
fprintf(fp, "Secret[%d]: ", context->secretlen);
if (context->clear_secret) {
fprintf(fp, "CLEARED\n");
} else {
for (unsigned i = 0; i < context->secretlen; ++i) {
fprintf(fp, "%2.2x ", ((unsigned char *)context->secret)[i]);
}
fprintf(fp, "\n");
}
fprintf(fp, "Associated data[%d]: ", context->adlen);
for (unsigned i = 0; i < context->adlen; ++i) {
fprintf(fp, "%2.2x ", ((unsigned char *)context->ad)[i]);
}
fprintf(fp, "\n");
fprintf(fp, "Pre-hashing digest: ");
for (unsigned i = 0; i < ARGON2_PREHASH_DIGEST_LENGTH; ++i) {
fprintf(fp, "%2.2x ", ((unsigned char *)blockhash)[i]);
}
fprintf(fp, "\n");
fclose(fp);
}
}
void print_tag( const void *out, uint32_t outlen )
{
FILE *fp = fopen( ARGON2_KAT_FILENAME, "a+" );
void print_tag(const void *out, uint32_t outlen) {
FILE *fp = fopen(ARGON2_KAT_FILENAME, "a+");
if ( fp && out != NULL )
{
fprintf( fp, "Tag: " );
if (fp && out != NULL) {
fprintf(fp, "Tag: ");
for ( unsigned i = 0; i < outlen; ++i )
{
fprintf( fp, "%2.2x ", ( ( uint8_t * ) out )[i] );
}
fprintf( fp, "\n" );
fclose( fp );
for (unsigned i = 0; i < outlen; ++i) {
fprintf(fp, "%2.2x ", ((uint8_t *)out)[i]);
}
fprintf(fp, "\n");
fclose(fp);
}
}
void internal_kat( const Argon2_instance_t *instance, uint32_t pass )
{
FILE *fp = fopen( ARGON2_KAT_FILENAME, "a+" );
void internal_kat(const Argon2_instance_t *instance, uint32_t pass) {
FILE *fp = fopen(ARGON2_KAT_FILENAME, "a+");
if ( fp && instance != NULL )
{
fprintf( fp, "\n After pass %d:\n", pass );
if (fp && instance != NULL) {
fprintf(fp, "\n After pass %d:\n", pass);
for ( uint32_t 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 (uint32_t 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 ( uint32_t j = 0; j < how_many_words; ++j )
fprintf( fp, "Block %.4d [%3d]: %016" PRIx64 "\n", i, j, instance->memory[i].v[j] );
}
fclose( fp );
for (uint32_t j = 0; j < how_many_words; ++j)
fprintf(fp, "Block %.4d [%3d]: %016" PRIx64 "\n", i, j,
instance->memory[i].v[j]);
}
fclose(fp);
}
}

View File

@ -5,24 +5,26 @@
*
* 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/>.
* 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
* @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 );
void initial_kat(const uint8_t *blockhash, const Argon2_Context *context,
Argon2_type type);
/*
* Function that prints the output tag
@ -30,7 +32,7 @@ void initial_kat( const uint8_t *blockhash, const Argon2_Context *context, Argon
* @param outlen digest length
* @pre out must point to @a outlen bytes
**/
void print_tag( const void *out, uint32_t outlen );
void print_tag(const void *out, uint32_t outlen);
/*
* Function that prints the internal state at given moment
@ -38,7 +40,6 @@ void print_tag( const void *out, uint32_t outlen );
* @param pass current pass number
* @pre instance must have necessary memory allocated
**/
void internal_kat( const Argon2_instance_t *instance, uint32_t pass );
void internal_kat(const Argon2_instance_t *instance, uint32_t pass);
#endif

View File

@ -5,11 +5,12 @@
*
* 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/>.
* 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 <stdlib.h>
@ -25,382 +26,363 @@
#define _MEASURE
#define T_COST_DEF 3
#define LOG_M_COST_DEF 12 /*4 MB*/
#define LOG_M_COST_DEF 12 /*4 MB*/
#define LANES_DEF 4
#define THREADS_DEF 4
#define PWD_DEF "password"
#define UNUSED_PARAMETER(x) (void)(x)
static __inline uint64_t rdtsc( void )
{
static __inline uint64_t rdtsc(void) {
#ifdef _MSC_VER
return __rdtsc();
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
#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
}
/*
* Custom allocate memory
*/
int CustomAllocateMemory( uint8_t **memory, size_t length )
{
*memory = ( uint8_t * )malloc( length );
int CustomAllocateMemory(uint8_t **memory, size_t length) {
*memory = (uint8_t *)malloc(length);
if ( !*memory )
{
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
if (!*memory) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
return ARGON2_OK;
return ARGON2_OK;
}
/*
* Custom free memory
*/
void CustomFreeMemory( uint8_t *memory, size_t length )
{
UNUSED_PARAMETER( length );
void CustomFreeMemory(uint8_t *memory, size_t length) {
UNUSED_PARAMETER(length);
if ( memory )
{
free( memory );
}
if (memory) {
free(memory);
}
}
void usage( const char *cmd )
{
printf( "usage: %s mode [parameters]\n", cmd );
printf( "Mode:\n" );
printf( "\tr\trun Argon2 with the selected parameters\n" );
printf( "\tg\tgenerates test vectors for given Argon2 type\n" );
printf( "\tb\tbenchmarks various Argon2 versions\n" );
printf( "Parameters (for run mode):\n" );
printf( "\t-y, --type [d or i, default i]\n" );
printf( "\t-t, --tcost [time cost in 0..2^24, default %d]\n", T_COST_DEF );
printf( "\t-m, --mcost [base 2 log of memory cost in 0..21, default %d]\n", LOG_M_COST_DEF );
printf( "\t-l, --lanes [number of lanes in %u..%u, default %d]\n", ARGON2_MIN_LANES, ARGON2_MAX_LANES, LANES_DEF );
printf( "\t-p, --threads [number of threads in %u..%u, default %d]\n", ARGON2_MIN_THREADS, ARGON2_MAX_THREADS, THREADS_DEF );
printf( "\t-i, --password [password, default \"%s\"]\n", PWD_DEF );
void usage(const char *cmd) {
printf("usage: %s mode [parameters]\n", cmd);
printf("Mode:\n");
printf("\tr\trun Argon2 with the selected parameters\n");
printf("\tg\tgenerates test vectors for given Argon2 type\n");
printf("\tb\tbenchmarks various Argon2 versions\n");
printf("Parameters (for run mode):\n");
printf("\t-y, --type [d or i, default i]\n");
printf("\t-t, --tcost [time cost in 0..2^24, default %d]\n", T_COST_DEF);
printf("\t-m, --mcost [base 2 log of memory cost in 0..21, default %d]\n",
LOG_M_COST_DEF);
printf("\t-l, --lanes [number of lanes in %u..%u, default %d]\n",
ARGON2_MIN_LANES, ARGON2_MAX_LANES, LANES_DEF);
printf("\t-p, --threads [number of threads in %u..%u, default %d]\n",
ARGON2_MIN_THREADS, ARGON2_MAX_THREADS, THREADS_DEF);
printf("\t-i, --password [password, default \"%s\"]\n", PWD_DEF);
}
void fatal( const char *error )
{
fprintf( stderr, "error: %s\n", error );
exit( 1 );
void fatal(const char *error) {
fprintf(stderr, "error: %s\n", error);
exit(1);
}
void print_bytes( const void *s, size_t len )
{
for( size_t i = 0; i < len; i++ )
{
printf( "%02x", ( ( const unsigned char * ) s )[i] & 0xff );
}
void print_bytes(const void *s, size_t len) {
for (size_t i = 0; i < len; i++) {
printf("%02x", ((const unsigned char *)s)[i] & 0xff);
}
printf( "\n" );
printf("\n");
}
/*
* Benchmarks Argon2 with salt length 16, password length 16, t_cost 1,
and different m_cost and threads
*/
void benchmark()
{
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];
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 t_cost = 1;
memset( pwd_array, 0, inlen );
memset( salt_array, 1, inlen );
uint32_t thread_test[6] = {1, 2, 4, 6, 8, 16};
memset(pwd_array, 0, inlen);
memset(salt_array, 1, inlen);
uint32_t thread_test[6] = {1, 2, 4, 6, 8, 16};
uint32_t m_cost;
uint32_t m_cost;
for ( m_cost = ( uint32_t ) 1 << 10; m_cost <= ( uint32_t ) 1 << 22; m_cost *= 2 )
{
uint32_t i;
for (m_cost = (uint32_t)1 << 10; m_cost <= (uint32_t)1 << 22; m_cost *= 2) {
uint32_t i;
for ( i=0; i <6; ++i )
{
uint32_t thread_n = thread_test[i];
uint64_t start_cycles, stop_cycles, stop_cycles_i;
for (i = 0; i < 6; ++i) {
uint32_t thread_n = thread_test[i];
uint64_t start_cycles, stop_cycles, stop_cycles_i;
clock_t start_time = clock();
start_cycles = rdtsc();
clock_t start_time = clock();
start_cycles = rdtsc();
Argon2_Context context = {out, outlen, pwd_array, inlen, salt_array, inlen,
NULL, 0, NULL, 0, t_cost, m_cost, thread_n, thread_n, NULL, NULL, false, false, false, false
};
argon2d( &context );
stop_cycles = rdtsc();
argon2i( &context );
stop_cycles_i = rdtsc();
clock_t stop_time = clock();
Argon2_Context context = {out, outlen, pwd_array, inlen, salt_array,
inlen, NULL, 0, NULL, 0,
t_cost, m_cost, thread_n, thread_n, NULL,
NULL, false, false, false, false};
argon2d(&context);
stop_cycles = rdtsc();
argon2i(&context);
stop_cycles_i = rdtsc();
clock_t stop_time = clock();
uint64_t delta_d = ( stop_cycles - start_cycles ) / ( m_cost );
uint64_t delta_i = ( stop_cycles_i - stop_cycles ) / ( m_cost );
float mcycles_d = ( float ) ( stop_cycles - start_cycles ) / ( 1 << 20 );
float mcycles_i = ( float ) ( stop_cycles_i - stop_cycles ) / ( 1 << 20 );
printf( "Argon2d %d pass(es) %d Mbytes %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 pass(es) %d Mbytes %d threads: %2.2f cpb %2.2f Mcycles \n", t_cost, m_cost >> 10, thread_n, ( float ) delta_i / 1024, mcycles_i );
uint64_t delta_d = (stop_cycles - start_cycles) / (m_cost);
uint64_t delta_i = (stop_cycles_i - stop_cycles) / (m_cost);
float mcycles_d = (float)(stop_cycles - start_cycles) / (1 << 20);
float mcycles_i = (float)(stop_cycles_i - stop_cycles) / (1 << 20);
printf("Argon2d %d pass(es) %d Mbytes %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 pass(es) %d Mbytes %d threads: %2.2f cpb %2.2f "
"Mcycles \n",
t_cost, m_cost >> 10, thread_n, (float)delta_i / 1024, mcycles_i);
float run_time = ( ( float ) stop_time - start_time ) / ( CLOCKS_PER_SEC );
printf( "%2.4f seconds\n\n", run_time );
}
float run_time = ((float)stop_time - start_time) / (CLOCKS_PER_SEC);
printf("%2.4f seconds\n\n", run_time);
}
}
}
void run(uint8_t *out, char *pwd, uint32_t t_cost, uint32_t m_cost,
uint32_t lanes, uint32_t threads, const char *type, bool print) {
uint64_t start_cycles, stop_cycles;
void run( uint8_t *out, char *pwd, uint32_t t_cost, uint32_t m_cost, uint32_t lanes, uint32_t threads,const char *type, bool print )
{
uint64_t start_cycles, stop_cycles;
clock_t start_time = clock();
start_cycles = rdtsc();
clock_t start_time = clock();
start_cycles = rdtsc();
#define SALT_LEN 16
/*Fixed parameters*/
const unsigned out_length = 32;
const unsigned salt_length = SALT_LEN;
bool clear_memory = false;
bool clear_secret = false;
bool clear_password = false;
uint8_t salt[SALT_LEN];
/*Fixed parameters*/
const unsigned out_length = 32;
const unsigned salt_length = SALT_LEN;
bool clear_memory = false;
bool clear_secret = false;
bool clear_password = false;
uint8_t salt[SALT_LEN];
#undef SALT_LEN
uint8_t *in = NULL;
uint8_t *in = NULL;
if ( pwd )
{
in = malloc( strlen(pwd) + 1 );
strcpy( (char *)in, pwd );
}
else
{
in = malloc( strlen(PWD_DEF) + 1 );
strcpy( (char *)in, PWD_DEF );
}
if (pwd) {
in = malloc(strlen(pwd) + 1);
strcpy((char *)in, pwd);
} else {
in = malloc(strlen(PWD_DEF) + 1);
strcpy((char *)in, PWD_DEF);
}
const unsigned in_length = strlen( ( char * )in );
const unsigned in_length = strlen((char *)in);
UNUSED_PARAMETER( threads );
UNUSED_PARAMETER(threads);
memset( salt, 0x00, salt_length );
memset(salt, 0x00, salt_length);
Argon2_Context context= {out, out_length, in, in_length, salt, salt_length,
NULL, 0, NULL, 0, t_cost, m_cost, lanes, lanes,
NULL, NULL,
clear_password, clear_secret, clear_memory, print
};
printf( "Argon2%s with\n", type );
printf( "\tt_cost = %d\n", t_cost );
printf( "\tm_cost = %d\n", m_cost );
printf( "\tpassword = %s\n", in );
printf( "\tsalt = " ); print_bytes( salt, salt_length );
Argon2_Context context = {
out, out_length, in, in_length, salt, salt_length,
NULL, 0, NULL, 0, t_cost, m_cost,
lanes, lanes, NULL, NULL, clear_password, clear_secret,
clear_memory, print};
printf("Argon2%s with\n", type);
printf("\tt_cost = %d\n", t_cost);
printf("\tm_cost = %d\n", m_cost);
printf("\tpassword = %s\n", in);
printf("\tsalt = ");
print_bytes(salt, salt_length);
if ( !strcmp( type,"d" ) ) argon2d( &context );
else if ( !strcmp( type,"i" ) ) argon2i( &context );
else fatal( "wrong Argon2 type" );
if (!strcmp(type, "d"))
argon2d(&context);
else if (!strcmp(type, "i"))
argon2i(&context);
else
fatal("wrong Argon2 type");
stop_cycles = rdtsc();
clock_t finish_time = clock();
stop_cycles = rdtsc();
clock_t finish_time = clock();
float run_time = ((float)finish_time - start_time) / (CLOCKS_PER_SEC);
printf("%2.3f seconds ", run_time);
float run_time = ( ( float ) finish_time - start_time ) / ( CLOCKS_PER_SEC );
printf( "%2.3f seconds ", run_time );
float mcycles = (float)(stop_cycles - start_cycles) / (1 << 20);
printf("(%.3f mebicycles)\n", mcycles);
float mcycles = ( float ) ( stop_cycles - start_cycles ) / ( 1 << 20 );
printf( "(%.3f mebicycles)\n", mcycles );
print_bytes(out, out_length);
print_bytes( out, out_length );
// show string encoding
char string[300];
encode_string(string, sizeof string, &context);
printf("%s\n", string);
// show string encoding
char string[300];
encode_string( string, sizeof string, &context );
printf( "%s\n", string );
free(in);
free(in);
}
void generate_testvectors( const char *type )
{
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
bool clear_memory = false;
bool clear_secret = false;
bool clear_password = false;
bool print_internals = true;
bool clear_memory = false;
bool clear_secret = false;
bool clear_password = false;
bool print_internals = true;
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 AllocateMemoryCallback myown_allocator = NULL;
const FreeMemoryCallback myown_deallocator = NULL;
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 AllocateMemoryCallback myown_allocator = NULL;
const FreeMemoryCallback myown_deallocator = NULL;
unsigned t_cost = 3;
unsigned m_cost = 16;
unsigned lanes = 4;
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);
memset(pwd, 1, TEST_OUTLEN);
memset(salt, 2, TEST_SALTLEN);
memset(secret, 3, TEST_SECRETLEN);
memset(ad, 4, TEST_ADLEN);
printf( "Generating test vectors for Argon2%s in file \"%s\".\n", type, ARGON2_KAT_FILENAME );
printf("Generating test vectors for Argon2%s in file \"%s\".\n", type,
ARGON2_KAT_FILENAME);
Argon2_Context context = { out, TEST_OUTLEN, pwd, TEST_PWDLEN, salt, TEST_SALTLEN,
secret, TEST_SECRETLEN, ad, TEST_ADLEN, t_cost, m_cost, lanes, lanes,
myown_allocator, myown_deallocator,
clear_password, clear_secret, clear_memory, print_internals
};
#undef TEST_OUTLEN
#undef TEST_PWDLEN
#undef TEST_SALTLEN
#undef TEST_SECRETLEN
#undef TEST_ADLEN
Argon2_Context context = {out,
TEST_OUTLEN,
pwd,
TEST_PWDLEN,
salt,
TEST_SALTLEN,
secret,
TEST_SECRETLEN,
ad,
TEST_ADLEN,
t_cost,
m_cost,
lanes,
lanes,
myown_allocator,
myown_deallocator,
clear_password,
clear_secret,
clear_memory,
print_internals};
#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" );
if (!strcmp(type, "d"))
argon2d(&context);
else if (!strcmp(type, "i"))
argon2i(&context);
else
fatal("wrong Argon2 type");
}
int main( int argc, char *argv[] )
{
unsigned char out[32];
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;
int main(int argc, char *argv[]) {
unsigned char out[32];
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;
bool testvectors = false;
const char *type= "i";
bool testvectors = false;
const char *type = "i";
remove( ARGON2_KAT_FILENAME );
remove(ARGON2_KAT_FILENAME);
if ( argc == 1 )
{
usage( argv[0] );
return 1;
}
if (argc == 1) {
usage(argv[0]);
return 1;
}
for ( int i = 1; i < argc; i++ )
{
char *a = argv[i];
for (int i = 1; i < argc; i++) {
char *a = argv[i];
if ( !strcmp( a, "-m" ) || !strcmp( a, "--mcost" ) )
{
if ( i < argc - 1 )
{
i++;
m_cost = ( uint8_t ) 1 << ( ( uint8_t )atoi( argv[i] ) % 22 );
continue;
}
else fatal( "missing memory cost argument" );
}
else if ( !strcmp( a, "-t" ) || !strcmp( a, "--tcost" ) )
{
if ( i < argc - 1 )
{
i++;
t_cost = atoi( argv[i] ) & 0xffffff;
continue;
}
else fatal( "missing time cost argument" );
}
else if ( !strcmp( a, "-p" ) || !strcmp( a, "--threads" ) )
{
if ( i < argc - 1 )
{
i++;
threads = atoi( argv[i] ) % ARGON2_MAX_THREADS;
continue;
}
else fatal( "missing threads argument" );
}
else if ( !strcmp( a, "-l" ) || !strcmp( a, "--lanes" ) )
{
if ( i < argc - 1 )
{
i++;
lanes = atoi( argv[i] ) % ARGON2_MAX_LANES;
continue;
}
else fatal( "missing lanes argument" );
}
else if ( !strcmp( a, "-y" ) || !strcmp( a, "--type" ) )
{
if ( i < argc - 1 )
{
i++;
type = argv[i];
continue;
}
else fatal( "missing type argument" );
}
else if ( !strcmp( a, "-i" ) || !strcmp( a, "--password" ) )
{
if ( i < argc - 1 )
{
i++;
pwd = argv[i];
continue;
}
else fatal( "missing threads argument" );
}
else if ( !strcmp( a, "r" ) )
{
testvectors = false;
continue;
}
else if ( !strcmp( a, "g" ) )
{
testvectors = true;
continue;
}
else if ( !strcmp( a, "b" ) )
{
benchmark();
return 0;
}
else fatal( "unknown argument" );
}
if ( testvectors )
{
generate_testvectors( type );
return 0;
}
run( out, pwd, t_cost, m_cost, lanes, threads, type, testvectors );
if (!strcmp(a, "-m") || !strcmp(a, "--mcost")) {
if (i < argc - 1) {
i++;
m_cost = (uint8_t)1 << ((uint8_t)atoi(argv[i]) % 22);
continue;
} else
fatal("missing memory cost argument");
} else if (!strcmp(a, "-t") || !strcmp(a, "--tcost")) {
if (i < argc - 1) {
i++;
t_cost = atoi(argv[i]) & 0xffffff;
continue;
} else
fatal("missing time cost argument");
} else if (!strcmp(a, "-p") || !strcmp(a, "--threads")) {
if (i < argc - 1) {
i++;
threads = atoi(argv[i]) % ARGON2_MAX_THREADS;
continue;
} else
fatal("missing threads argument");
} else if (!strcmp(a, "-l") || !strcmp(a, "--lanes")) {
if (i < argc - 1) {
i++;
lanes = atoi(argv[i]) % ARGON2_MAX_LANES;
continue;
} else
fatal("missing lanes argument");
} else if (!strcmp(a, "-y") || !strcmp(a, "--type")) {
if (i < argc - 1) {
i++;
type = argv[i];
continue;
} else
fatal("missing type argument");
} else if (!strcmp(a, "-i") || !strcmp(a, "--password")) {
if (i < argc - 1) {
i++;
pwd = argv[i];
continue;
} else
fatal("missing threads argument");
} else if (!strcmp(a, "r")) {
testvectors = false;
continue;
} else if (!strcmp(a, "g")) {
testvectors = true;
continue;
} else if (!strcmp(a, "b")) {
benchmark();
return 0;
} else
fatal("unknown argument");
}
if (testvectors) {
generate_testvectors(type);
return 0;
}
run(out, pwd, t_cost, m_cost, lanes, threads, type, testvectors);
return 0;
}

312
src/opt.c
View File

@ -5,11 +5,12 @@
*
* 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/>.
* 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>
@ -22,216 +23,205 @@
#include <intrin.h>
#endif
#include "argon2.h"
#include "core.h"
#include "opt.h"
#include "kat.h"
#include "blake2/blamka-round-opt.h"
#include "blake2/blake2-impl.h"
#include "blake2/blake2.h"
/* The KAT file name */
const char *ARGON2_KAT_FILENAME = "kat-argon2-opt.log";
#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 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))
void fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block) {
__m128i t0, t1;
__m128i block_XY[ARGON2_QWORDS_IN_BLOCK];
void fill_block( __m128i *state, const uint8_t *ref_block, uint8_t *next_block )
{
__m128i t0, t1;
__m128i block_XY[ARGON2_QWORDS_IN_BLOCK];
for (uint32_t i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++) {
block_XY[i] = _mm_loadu_si128((__m128i *)ref_block);
ref_block += 16;
}
for ( uint32_t i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++ )
{
block_XY[i] = _mm_loadu_si128( ( __m128i * ) ref_block );
ref_block += 16;
}
for (uint32_t i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++) {
block_XY[i] = state[i] = _mm_xor_si128(state[i], block_XY[i]);
}
for ( uint32_t i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++ )
{
block_XY[i] = state[i] = _mm_xor_si128( state[i], block_XY[i] );
}
BLAKE2_ROUND(state[0], state[1], state[2], state[3], state[4], state[5],
state[6], state[7]);
BLAKE2_ROUND( state[0], state[1], state[2], state[3],
state[4], state[5], state[6], state[7] );
BLAKE2_ROUND(state[8], state[9], state[10], state[11], state[12], state[13],
state[14], state[15]);
BLAKE2_ROUND( state[8], state[9], state[10], state[11],
state[12], state[13], state[14], state[15] );
BLAKE2_ROUND(state[16], state[17], state[18], state[19], state[20], state[21],
state[22], state[23]);
BLAKE2_ROUND( state[16], state[17], state[18], state[19],
state[20], state[21], state[22], state[23] );
BLAKE2_ROUND(state[24], state[25], state[26], state[27], state[28], state[29],
state[30], state[31]);
BLAKE2_ROUND( state[24], state[25], state[26], state[27],
state[28], state[29], state[30], state[31] );
BLAKE2_ROUND(state[32], state[33], state[34], state[35], state[36], state[37],
state[38], state[39]);
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[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]);
BLAKE2_ROUND( state[48], state[49], state[50], state[51],
state[52], state[53], state[54], state[55] );
BLAKE2_ROUND(state[56], state[57], state[58], state[59], state[60], state[61],
state[62], state[63]);
BLAKE2_ROUND( state[56], state[57], state[58], state[59],
state[60], state[61], state[62], state[63] );
BLAKE2_ROUND(state[0], state[8], state[16], state[24], state[32], state[40],
state[48], state[56]);
BLAKE2_ROUND(state[1], state[9], state[17], state[25], state[33], state[41],
state[49], state[57]);
BLAKE2_ROUND( state[0], state[8], state[16], state[24],
state[32], state[40], state[48], state[56] );
BLAKE2_ROUND(state[2], state[10], state[18], state[26], state[34], state[42],
state[50], state[58])
BLAKE2_ROUND( state[1], state[9], state[17], state[25],
state[33], state[41], state[49], state[57] );
BLAKE2_ROUND(state[3], state[11], state[19], state[27], state[35], state[43],
state[51], state[59]);
BLAKE2_ROUND( state[2], state[10], state[18], state[26],
state[34], state[42], state[50], state[58] )
BLAKE2_ROUND(state[4], state[12], state[20], state[28], state[36], state[44],
state[52], state[60]);
BLAKE2_ROUND( state[3], state[11], state[19], state[27],
state[35], state[43], state[51], state[59] );
BLAKE2_ROUND(state[5], state[13], state[21], state[29], state[37], state[45],
state[53], state[61]);
BLAKE2_ROUND( state[4], state[12], state[20], state[28],
state[36], state[44], state[52], state[60] );
BLAKE2_ROUND(state[6], state[14], state[22], state[30], state[38], state[46],
state[54], state[62]);
BLAKE2_ROUND( state[5], state[13], state[21], state[29],
state[37], state[45], state[53], state[61] );
BLAKE2_ROUND(state[7], state[15], state[23], state[31], state[39], state[47],
state[55], state[63]);
BLAKE2_ROUND( state[6], state[14], state[22], state[30],
state[38], state[46], state[54], state[62] );
for (uint32_t i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++) {
// Feedback
state[i] = _mm_xor_si128(state[i], block_XY[i]);
}
BLAKE2_ROUND( state[7], state[15], state[23], state[31],
state[39], state[47], state[55], state[63] );
for ( uint32_t i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++ )
{
// Feedback
state[i] = _mm_xor_si128( state[i], block_XY[i] );
}
for ( uint32_t i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++ )
{
_mm_storeu_si128( ( __m128i * ) next_block, state[i] );
next_block += 16;
}
for (uint32_t i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++) {
_mm_storeu_si128((__m128i *)next_block, state[i]);
next_block += 16;
}
}
void generate_addresses( const Argon2_instance_t *instance, const Argon2_position_t *position, uint64_t *pseudo_rands )
{
block zero_block, address_block,input_block;
init_block_value( &zero_block,0 );
copy_block( &address_block,&zero_block );
copy_block( &input_block,&zero_block );
void generate_addresses(const Argon2_instance_t *instance,
const Argon2_position_t *position,
uint64_t *pseudo_rands) {
block zero_block, address_block, input_block;
init_block_value(&zero_block, 0);
copy_block(&address_block, &zero_block);
copy_block(&input_block, &zero_block);
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] = instance->memory_blocks;
input_block.v[4] = instance->passes;
input_block.v[5] = instance->type;
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] = instance->memory_blocks;
input_block.v[4] = instance->passes;
input_block.v[5] = instance->type;
for ( uint32_t i = 0; i < instance->segment_length; ++i )
{
if ( i % ARGON2_ADDRESSES_IN_BLOCK == 0 )
{
input_block.v[6]++;
block zero_block, zero2_block;
init_block_value( &zero_block,0 );
init_block_value( &zero2_block,0 );
fill_block( ( __m128i * ) & zero_block.v, ( uint8_t * ) & input_block.v, ( uint8_t * ) & address_block.v );
fill_block( ( __m128i * ) & zero2_block.v, ( uint8_t * ) & address_block.v, ( uint8_t * ) & address_block.v );
}
for (uint32_t i = 0; i < instance->segment_length; ++i) {
if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
input_block.v[6]++;
block zero_block, zero2_block;
init_block_value(&zero_block, 0);
init_block_value(&zero2_block, 0);
fill_block((__m128i *)&zero_block.v, (uint8_t *)&input_block.v,
(uint8_t *)&address_block.v);
fill_block((__m128i *)&zero2_block.v, (uint8_t *)&address_block.v,
(uint8_t *)&address_block.v);
}
pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
}
pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
}
}
}
void fill_segment( const Argon2_instance_t *instance, Argon2_position_t position )
{
if ( instance == NULL ) return;
void fill_segment(const Argon2_instance_t *instance,
Argon2_position_t position) {
if (instance == NULL)
return;
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
__m128i state[64];
bool data_independent_addressing = ( instance->type == Argon2_i );
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
__m128i state[64];
bool data_independent_addressing = (instance->type == Argon2_i);
// Pseudo-random values that determine the reference block position
uint64_t *pseudo_rands = ( uint64_t * )malloc( sizeof( uint64_t )*instance->segment_length );
// Pseudo-random values that determine the reference block position
uint64_t *pseudo_rands =
(uint64_t *)malloc(sizeof(uint64_t) * instance->segment_length);
if ( pseudo_rands == NULL ) return;
if (pseudo_rands == NULL)
return;
if ( data_independent_addressing )
{
generate_addresses( instance, &position, pseudo_rands );
if (data_independent_addressing) {
generate_addresses(instance, &position, pseudo_rands);
}
uint32_t 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 * instance->lane_length +
position.slice * instance->segment_length + starting_index;
if (0 == curr_offset % instance->lane_length) {
// Last block in this lane
prev_offset = curr_offset + instance->lane_length - 1;
} else {
// Previous block
prev_offset = curr_offset - 1;
}
memcpy(state, (uint8_t *)((instance->memory + prev_offset)->v),
ARGON2_BLOCK_SIZE);
for (uint32_t i = starting_index; i < instance->segment_length;
++i, ++curr_offset, ++prev_offset) {
/*1.1 Rotating prev_offset if needed */
if (curr_offset % instance->lane_length == 1) {
prev_offset = curr_offset - 1;
}
uint32_t starting_index = 0;
if ( ( 0 == position.pass ) && ( 0 == position.slice ) )
{
starting_index = 2; // we have already generated the first two blocks
/* 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];
}
// Offset of the current block
curr_offset = position.lane * instance->lane_length + position.slice * instance->segment_length + starting_index;
/* 1.2.2 Computing the lane of the reference block */
ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
if ( 0 == curr_offset % instance->lane_length )
{
// Last block in this lane
prev_offset = curr_offset + instance->lane_length - 1;
}
else
{
// Previous block
prev_offset = curr_offset - 1;
if ((position.pass == 0) && (position.slice == 0)) {
// Can not reference other lanes yet
ref_lane = position.lane;
}
memcpy( state, ( uint8_t * ) ( ( instance->memory + prev_offset )->v ), ARGON2_BLOCK_SIZE );
/* 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);
for ( uint32_t i = starting_index; i < instance->segment_length; ++i, ++curr_offset, ++prev_offset )
{
/*1.1 Rotating prev_offset if needed */
if ( curr_offset % instance->lane_length == 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 ) ) % 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 lane. */
position.index = i;
ref_index = index_alpha( instance, &position, pseudo_rand & 0xFFFFFFFF, ref_lane == position.lane );
/* 2 Creating a new block */
block *ref_block = instance->memory + instance->lane_length * ref_lane + ref_index;
block *curr_block = instance->memory + curr_offset;
fill_block( state, ( uint8_t * ) ref_block->v, ( uint8_t * ) curr_block->v );
}
free( pseudo_rands );
/* 2 Creating a new block */
block *ref_block =
instance->memory + instance->lane_length * ref_lane + ref_index;
block *curr_block = instance->memory + curr_offset;
fill_block(state, (uint8_t *)ref_block->v, (uint8_t *)curr_block->v);
}
free(pseudo_rands);
}

View File

@ -5,8 +5,10 @@
*
* 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/>.
* 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 OPT_H
@ -19,26 +21,29 @@
* @param next_block Pointer to the block to be constructed
* @pre all block pointers must be valid
*/
void fill_block( __m128i *state, const uint8_t *ref_block, uint8_t *next_block );
void fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block);
/*
* Generate pseudo-random values to reference blocks in the segment and puts them into the array
* 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 );
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.
* 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_CORE_H */
void fill_segment(const Argon2_instance_t *instance,
Argon2_position_t position);
#endif /* ARGON2_OPT_CORE_H */

255
src/ref.c
View File

@ -5,11 +5,12 @@
*
* 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/>.
* 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>
@ -19,157 +20,151 @@
#include "ref.h"
#include "kat.h"
#include "blake2/blamka-round-ref.h"
#include "blake2/blake2-impl.h"
#include "blake2/blake2.h"
/* The KAT file name */
const char *ARGON2_KAT_FILENAME = "kat-argon2-ref.log";
void fill_block(const block *prev_block, const block *ref_block,
block *next_block) {
block blockR;
copy_block(&blockR, ref_block);
xor_block(&blockR, prev_block);
block block_tmp;
copy_block(&block_tmp, &blockR);
void fill_block( const block *prev_block, const block *ref_block, block *next_block )
{
block blockR;
copy_block( &blockR,ref_block );
xor_block( &blockR,prev_block );
block block_tmp;
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 (unsigned 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 columns of 64-bit words: (0,1,...,15) , then (16,17,..31)... finally (112,113,...127)
for ( unsigned 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 (unsigned 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]);
}
// 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 ( unsigned 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 );
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;
init_block_value( &zero_block,0 );
init_block_value( &input_block,0 );
init_block_value( &address_block,0 );
void generate_addresses(const Argon2_instance_t *instance,
const Argon2_position_t *position,
uint64_t *pseudo_rands) {
block zero_block, input_block, address_block;
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] = instance->memory_blocks;
input_block.v[4] = instance->passes;
input_block.v[5] = instance->type;
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] = instance->memory_blocks;
input_block.v[4] = instance->passes;
input_block.v[5] = instance->type;
for ( uint32_t i = 0; i < instance->segment_length; ++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 );
}
for (uint32_t i = 0; i < instance->segment_length; ++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];
}
pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
}
}
}
void fill_segment( const Argon2_instance_t *instance, Argon2_position_t position )
{
if ( instance == NULL )
{
return;
void fill_segment(const Argon2_instance_t *instance,
Argon2_position_t position) {
if (instance == NULL) {
return;
}
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
bool data_independent_addressing = (instance->type == Argon2_i);
// Pseudo-random values that determine the reference block position
uint64_t *pseudo_rands =
(uint64_t *)malloc(sizeof(uint64_t) * (instance->segment_length));
if (pseudo_rands == NULL) {
return;
}
if (data_independent_addressing) {
generate_addresses(instance, &position, pseudo_rands);
}
uint32_t 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 * instance->lane_length +
position.slice * instance->segment_length + starting_index;
if (0 == curr_offset % instance->lane_length) {
// Last block in this lane
prev_offset = curr_offset + instance->lane_length - 1;
} else {
// Previous block
prev_offset = curr_offset - 1;
}
for (uint32_t i = starting_index; i < instance->segment_length;
++i, ++curr_offset, ++prev_offset) {
/*1.1 Rotating prev_offset if needed */
if (curr_offset % instance->lane_length == 1) {
prev_offset = curr_offset - 1;
}
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
bool data_independent_addressing = ( instance->type == Argon2_i );
// Pseudo-random values that determine the reference block position
uint64_t *pseudo_rands = ( uint64_t * )malloc( sizeof( uint64_t )*( instance->segment_length ) );
if ( pseudo_rands == NULL )
{
return;
/* 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];
}
if ( data_independent_addressing )
{
generate_addresses( instance, &position, pseudo_rands );
/* 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;
}
uint32_t starting_index = 0;
/* 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);
if ( ( 0 == position.pass ) && ( 0 == position.slice ) )
{
starting_index = 2; // we have already generated the first two blocks
}
/* 2 Creating a new block */
block *ref_block =
instance->memory + instance->lane_length * ref_lane + ref_index;
block *curr_block = instance->memory + curr_offset;
fill_block(instance->memory + prev_offset, ref_block, curr_block);
}
// Offset of the current block
curr_offset = position.lane * instance->lane_length + position.slice * instance->segment_length + starting_index;
if ( 0 == curr_offset % instance->lane_length )
{
// Last block in this lane
prev_offset = curr_offset + instance->lane_length - 1;
}
else
{
// Previous block
prev_offset = curr_offset - 1;
}
for ( uint32_t i = starting_index; i < instance->segment_length; ++i, ++curr_offset, ++prev_offset )
{
/*1.1 Rotating prev_offset if needed */
if ( curr_offset % instance->lane_length == 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 ) ) % 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 lane. */
position.index = i;
ref_index = index_alpha( instance, &position, pseudo_rand & 0xFFFFFFFF, ref_lane == position.lane );
/* 2 Creating a new block */
block *ref_block = instance->memory + instance->lane_length * ref_lane + ref_index;
block *curr_block = instance->memory + curr_offset;
fill_block( instance->memory + prev_offset, ref_block, curr_block );
}
free( pseudo_rands );
free(pseudo_rands);
}

View File

@ -5,14 +5,15 @@
*
* 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/>.
* 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 REF_H
#define REF_H
/*
* Function fills a new memory block
* @param prev_block Pointer to the previous block
@ -20,24 +21,29 @@
* @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 );
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
* 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 );
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
* 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_CORE_H */
void fill_segment(const Argon2_instance_t *instance,
Argon2_position_t position);
#endif /* ARGON2_REF_CORE_H */