Merge remote-tracking branch 'upstream/master' into rpc_extanded_8

This commit is contained in:
SergiySW 2017-11-21 00:50:21 +03:00
commit 03094bca9a
53 changed files with 2870 additions and 3002 deletions

3
.gitmodules vendored
View file

@ -11,3 +11,6 @@
path = lmdb
url = https://github.com/LMDB/lmdb.git
branch = mdb.RE/0.9
[submodule "phc-winner-argon2"]
path = phc-winner-argon2
url = https://github.com/clemahieu/phc-winner-argon2.git

View file

@ -1,31 +0,0 @@
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
moral rights retained by the original author(s) and/or performer(s);
publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
rights protecting the extraction, dissemination, use and reuse of data in a Work;
database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.

View file

@ -1,123 +0,0 @@
/*
* Argon2 source code package
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* You should have received a copy of the CC0 Public Domain Dedication along with
* this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdint.h>
#include <map>
#include <string>
#include "argon2.h"
#include "argon2-core.h"
/************************* Error messages *********************************************************************************/
static std::map<Argon2_ErrorCodes, std::string> Argon2_ErrorMessage = {
{ARGON2_OK, "OK"},
{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_PWD_TOO_SHORT, "Password is too short"},
{ARGON2_PWD_TOO_LONG, "Password is too long"},
{ARGON2_SALT_TOO_SHORT, "Salt is too short"},
{ARGON2_SALT_TOO_LONG, "Salt is too long"},
{ARGON2_AD_TOO_SHORT, "Associated data is too short"},
{ARGON2_AD_TOO_LONG, "Associated date is too long"},
{ARGON2_SECRET_TOO_SHORT, "Secret is too short"},
{ARGON2_SECRET_TOO_LONG, "Secret is too long"},
{ARGON2_TIME_TOO_SMALL, "Time cost is too small"},
{ARGON2_TIME_TOO_LARGE, "Time cost is too large"},
{ARGON2_MEMORY_TOO_LITTLE, "Memory cost is too small"},
{ARGON2_MEMORY_TOO_MUCH, "Memory cost is too large"},
{ARGON2_LANES_TOO_FEW, "Too few lanes"},
{ARGON2_LANES_TOO_MANY, "Too many lanes"},
{ARGON2_PWD_PTR_MISMATCH, "Password pointer is NULL, but password length is not 0"},
{ARGON2_SALT_PTR_MISMATCH, "Salt pointer is NULL, but salt length is not 0"},
{ARGON2_SECRET_PTR_MISMATCH, "Secret pointer is NULL, but secret length is not 0"},
{ARGON2_AD_PTR_MISMATCH, "Associated data pointer is NULL, but ad length is not 0"},
{ARGON2_MEMORY_ALLOCATION_ERROR, "Memory allocation error"},
{ARGON2_FREE_MEMORY_CBK_NULL, "The free memory callback is NULL"},
{ARGON2_ALLOCATE_MEMORY_CBK_NULL, "The allocate memory callback is NULL"},
{ARGON2_INCORRECT_PARAMETER, "Argon2_Context context is NULL"},
{ARGON2_INCORRECT_TYPE, "There is no such version of Argon2"},
{ARGON2_OUT_PTR_MISMATCH, "Output pointer mismatch"}
};
int PHS(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) {
uint8_t* default_ad_ptr = NULL;
uint32_t default_ad_length = 0;
uint8_t* default_secret_ptr = NULL;
uint32_t default_secret_length = 0;
uint8_t default_parallelism = 1;
Argon2_Context context((uint8_t*) out, (uint32_t) outlen,
(uint8_t*) in, (uint32_t) inlen,
(uint8_t*) salt, (uint32_t) saltlen,
default_ad_ptr, default_ad_length,
default_secret_ptr, default_secret_length,
(uint32_t) t_cost, (uint32_t) m_cost, default_parallelism);
return Argon2Core(&context, Argon2_d);
}
int Argon2d(Argon2_Context* context) {
return Argon2Core(context, Argon2_d);
}
int Argon2i(Argon2_Context* context) {
return Argon2Core(context, Argon2_i);
}
int Argon2di(Argon2_Context* context) {
return Argon2Core(context, Argon2_di);
}
int Argon2id(Argon2_Context* context) {
return Argon2Core(context, Argon2_id);
}
int Argon2ds(Argon2_Context* context) {
return Argon2Core(context, Argon2_ds);
}
int VerifyD(Argon2_Context* context, const char *hash) {
if (0 == context->outlen || NULL == hash) {
return ARGON2_OUT_PTR_MISMATCH;
}
int result = Argon2Core(context, Argon2_d);
if (ARGON2_OK != result) {
return result;
}
return 0 == memcmp(hash, context->out, context->outlen);
}
const char* ErrorMessage(int error_code) {
if (error_code < ARGON2_ERROR_CODES_LENGTH) {
return Argon2_ErrorMessage[(Argon2_ErrorCodes) error_code].c_str();
}
return "Unknown error code.";
}

View file

@ -1,254 +0,0 @@
/*
* Argon2 source code package
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* You should have received a copy of the CC0 Public Domain Dedication along with
* this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef __ARGON2_H__
#define __ARGON2_H__
#include <cstddef>
/************************* Constants to enable Known Answer Tests (KAT) **************************************************/
/* Enable KAT */
//#define KAT
//#define KAT_INTERNAL
#if defined(KAT) || defined(KAT_INTERNAL)
/* The KAT file name */
extern const char* KAT_FILENAME;
#endif
/*************************Argon2 input parameter restrictions**************************************************/
/* Minimum and maximum number of lanes (degree of parallelism) */
const uint8_t MIN_LANES = 1;
const uint8_t MAX_LANES = 255;
/* Number of synchronization points between lanes per pass */
const uint32_t SYNC_POINTS = 4;
/* Minimum and maximum digest size in bytes */
const uint32_t MIN_OUTLEN = 4;
const uint32_t MAX_OUTLEN = 0xFFFFFFFF;
/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */
const uint32_t MIN_MEMORY = 2 * SYNC_POINTS; // 2 blocks per slice
const uint32_t MAX_MEMORY = 0xFFFFFFFF; // 2^32-1 blocks
/* Minimum and maximum number of passes */
const uint32_t MIN_TIME = 1;
const uint32_t MAX_TIME = 0xFFFFFFFF;
/* Minimum and maximum password length in bytes */
const uint32_t MIN_PWD_LENGTH = 0;
const uint32_t MAX_PWD_LENGTH = 0xFFFFFFFF;
/* Minimum and maximum associated data length in bytes */
const uint32_t MIN_AD_LENGTH = 0;
const uint32_t MAX_AD_LENGTH = 0xFFFFFFFF;
/* Minimum and maximum salt length in bytes */
const uint32_t MIN_SALT_LENGTH = 8;
const uint32_t MAX_SALT_LENGTH = 0xFFFFFFFF;
/* Minimum and maximum key length in bytes */
const uint32_t MIN_SECRET = 0;
const uint32_t MAX_SECRET = 0xFFFFFFFF;
/************************* Error codes *********************************************************************************/
enum Argon2_ErrorCodes {
ARGON2_OK = 0,
ARGON2_OUTPUT_PTR_NULL = 1,
ARGON2_OUTPUT_TOO_SHORT = 2,
ARGON2_OUTPUT_TOO_LONG = 3,
ARGON2_PWD_TOO_SHORT = 4,
ARGON2_PWD_TOO_LONG = 5,
ARGON2_SALT_TOO_SHORT = 6,
ARGON2_SALT_TOO_LONG = 7,
ARGON2_AD_TOO_SHORT = 8,
ARGON2_AD_TOO_LONG = 9,
ARGON2_SECRET_TOO_SHORT = 10,
ARGON2_SECRET_TOO_LONG = 11,
ARGON2_TIME_TOO_SMALL = 12,
ARGON2_TIME_TOO_LARGE = 13,
ARGON2_MEMORY_TOO_LITTLE = 14,
ARGON2_MEMORY_TOO_MUCH = 15,
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_MEMORY_ALLOCATION_ERROR = 22,
ARGON2_FREE_MEMORY_CBK_NULL = 23,
ARGON2_ALLOCATE_MEMORY_CBK_NULL = 24,
ARGON2_INCORRECT_PARAMETER = 25,
ARGON2_INCORRECT_TYPE = 26,
ARGON2_OUT_PTR_MISMATCH = 27,
ARGON2_ERROR_CODES_LENGTH /* Do NOT remove; Do NOT add error codes after this error code */
};
/********************************************* 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*************************************************************/
/*
*****Context: structure to hold Argon2 inputs:
* output array and its length,
* password and its length,
* salt and its length,
* secret and its length,
* associated data and its length,
* 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
****************************
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,NULL,NULL,true,false,false).
*/
struct Argon2_Context {
uint8_t *out; //output array
const uint32_t outlen; //digest length
uint8_t *pwd; //password array
uint32_t pwdlen; //password length
const uint8_t *salt; //salt array
const uint32_t saltlen; //salt length
uint8_t *secret; //key array
uint32_t secretlen; //key length
const uint8_t *ad; //associated data array
const uint32_t adlen; //associated data length
const uint32_t t_cost; //number of passes
const uint32_t m_cost; //amount of memory requested (KB)
const uint32_t lanes; //number of parallel threads
AllocateMemoryCallback allocate_cbk; //pointer to memory allocator
FreeMemoryCallback free_cbk; //pointer to memory deallocator
const bool clear_password; //whether to clear the password array
const bool clear_secret; //whether to clear the secret array
const bool clear_memory; //whether to clear the memory after the run
Argon2_Context(uint8_t *o, uint32_t olen,
/*const*/ uint8_t *m, uint32_t mlen,
/*const*/ uint8_t *n, uint32_t nlen,
/*const*/ uint8_t *s, uint32_t slen,
/*const*/ uint8_t *a, uint32_t alen,
uint32_t t_c, uint32_t m_c, uint32_t l,
AllocateMemoryCallback a_cbk = NULL, FreeMemoryCallback f_cbk = NULL, bool c_p = true, bool c_s = true, bool c_m = false) : out(o), outlen(olen),
pwd(m), pwdlen(mlen),
salt(n), saltlen(nlen),
secret(s), secretlen(slen),
ad(a), adlen(alen),
t_cost(t_c), m_cost(m_c), lanes(l),
allocate_cbk(a_cbk), free_cbk(f_cbk), clear_password(c_p), clear_secret(c_s), clear_memory(c_m) {
}
};
/**
* Function to hash the inputs in the memory-hard fashion
* @param out Pointer to the memory where the hash digest will be written
* @param outlen Digest length in bytes
* @param in Pointer to the input (password)
* @param inlen Input length in bytes
* @param salt Pointer to the salt
* @param saltlen Salt length in bytes
* @pre @a out must have at least @a outlen bytes allocated
* @pre @a in must be at least @inlen bytes long
* @pre @a saltlen must be at least @saltlen bytes long
* @return Zero if successful, 1 otherwise.
*/
extern "C" int PHS(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!!***************
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
extern int Argon2d(Argon2_Context* context);
/*
* * **************Argon2i: Version of Argon2 that picks memory blocks independing 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
*/
extern 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
*/
extern int Argon2di(Argon2_Context* context);
/*
* * **************Argon2ds: Argon2d hardened against GPU attacks, 20% slower***************
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
extern int Argon2ds(Argon2_Context* context);
/*
* * **************Argon2id: First half-pass over memory is password-independent, the rest are password-dependent
********************OK against side channels: they reduce to 1/2-pass Argon2i***************
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
extern 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
* @return Zero if successful, a non zero error code otherwise
*/
extern int VerifyD(Argon2_Context* context, const char *hash);
/*
* Get the associated error message for given erro code
* @return The error message associated with the given error code
*/
const char* ErrorMessage(int error_code);
#endif

View file

@ -1,44 +0,0 @@
#pragma once
#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 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;
uint64_t lessZ = (uint64_t)lessX;
lessZ = lessZ * lessY;
lessZ = lessZ << 1;
uint64_t z = lessZ + x + y;
return z;
}
#endif

View file

@ -1,97 +0,0 @@
#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){
__m128i z = _mm_mul_epu32 (x, y);
z = _mm_slli_epi64 (z, 1);
z = _mm_add_epi64 (z, x);
z = _mm_add_epi64 (z, y);
return 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 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 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);

View file

@ -1,143 +0,0 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
1. source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
2. binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation;
3. the name of the copyright holder is not used to endorse products
built using this software without specific written permission.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
Changes for ARM 9/9/2010
*/
#ifndef _BRG_ENDIAN_H
#define _BRG_ENDIAN_H
#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
#if 0
/* Include files where endian defines and byteswap functions may reside */
#if defined( __sun )
# include <sys/isa_defs.h>
#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ )
# include <sys/endian.h>
#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \
defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )
# include <machine/endian.h>
#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
# if !defined( __MINGW32__ ) && !defined( _AIX )
# include <endian.h>
# if !defined( __BEOS__ )
# include <byteswap.h>
# endif
# endif
#endif
#endif
/* Now attempt to set the define for platform byte order using any */
/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */
/* seem to encompass most endian symbol definitions */
#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )
# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )
# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( _BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( _LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )
# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )
# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
/* if the platform byte order could not be determined, then try to */
/* set this define using common machine defines */
#if !defined(PLATFORM_BYTE_ORDER)
#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
defined( vax ) || defined( vms ) || defined( VMS ) || \
defined( __VMS ) || defined( _M_X64 )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \
defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(__arm__)
# ifdef __BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# else
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif 1 /* **** EDIT HERE IF NECESSARY **** */
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#else
# error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order
#endif
#endif
#endif

View file

@ -1,493 +0,0 @@
/*
* Argon2 source code package
*
* 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/>.
*/
using namespace std;
/*For memory wiping*/
#ifdef _MSC_VER
#include "windows.h"
#include "winbase.h" //For SecureZeroMemory
#endif
#if defined __STDC_LIB_EXT1__
#define __STDC_WANT_LIB_EXT1__ 1
#endif
#define VC_GE_2005( version ) ( version >= 1400 )
#include <inttypes.h>
#include <vector>
#include <thread>
#include <cstring>
#include "argon2.h"
#include "argon2-core.h"
#include "kat.h"
#include "blake2.h"
#include "blake2-impl.h"
#if defined(__clang__)
#if __has_attribute(optnone)
#define NOT_OPTIMIZED __attribute__((optnone))
#endif
#elif defined(__GNUC__)
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
#if GCC_VERSION >= 40400
#define NOT_OPTIMIZED __attribute__((optimize("O0")))
#endif
#else
#define NOT_OPTIMIZED
#endif
block operator^(const block& l, const block& r) {
block a = l;
a ^= r;
return a;
}
int AllocateMemory(block **memory, uint32_t m_cost) {
if (memory != NULL) {
*memory = new block[m_cost];
if (!*memory) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
return ARGON2_OK;
} else return ARGON2_MEMORY_ALLOCATION_ERROR;
}
/* Function that securely cleans the memory
* @param mem Pointer to the memory
* @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);
#elif defined memset_s
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);
#endif
}
void FreeMemory(Argon2_instance_t* instance, bool clear) {
if (instance->state != NULL) {
if (clear) {
if (instance->type == Argon2_ds && instance->Sbox != NULL) {
secure_wipe_memory(instance->Sbox, SBOX_SIZE * sizeof (uint64_t));
}
secure_wipe_memory(instance->state, sizeof (block) * instance->memory_blocks);
}
delete[] instance->state;
if (instance->Sbox != NULL)
delete[] instance->Sbox;
}
}
int blake2b_long(uint8_t *out, const void *in, const uint32_t outlen, const uint64_t inlen)
{
blake2b_state 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);
}
return 0;
}
void Finalize(const Argon2_Context *context, Argon2_instance_t* instance) {
if (context != NULL && instance != NULL) {
block blockhash = instance->state[instance->lane_length - 1];
// XOR the last blocks
for (uint8_t l = 1; l < instance->lanes; ++l) {
uint32_t last_block_in_lane = l * instance->lane_length + (instance->lane_length - 1);
blockhash ^= instance->state[last_block_in_lane];
}
// Hash the result
blake2b_long(context->out, (uint8_t*) blockhash.v, context->outlen, BLOCK_SIZE);
secure_wipe_memory(blockhash.v, BLOCK_SIZE); //clear the blockhash
#ifdef KAT
PrintTag(context->out, context->outlen);
#endif
// Deallocate the memory
if (NULL != context->free_cbk) {
context->free_cbk((uint8_t *) instance->state, instance->memory_blocks * sizeof (block));
} else {
FreeMemory(instance, context->clear_memory);
}
}
}
uint32_t IndexAlpha(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);
}
}
} 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.5 Computing starting position */
uint32_t start_position = 0;
if (0 != position->pass) {
start_position = (position->slice == 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;
}
void FillMemoryBlocks(Argon2_instance_t* instance) {
vector<thread> Threads;
if (instance != NULL) {
for (uint8_t r = 0; r < instance->passes; ++r) {
if (Argon2_ds == instance->type) {
GenerateSbox(instance);
}
for (uint8_t s = 0; s < SYNC_POINTS; ++s) {
for (uint8_t l = 0; l < instance->lanes; ++l) {
Threads.push_back(thread(FillSegment, instance, Argon2_position_t(r, l, s, 0)));
}
for (auto& t : Threads) {
t.join();
}
Threads.clear();
}
#ifdef KAT_INTERNAL
InternalKat(instance, r);
#endif
}
}
}
int ValidateInputs(const Argon2_Context* context) {
if (NULL == context) {
return ARGON2_INCORRECT_PARAMETER;
}
if (NULL == context->out) {
return ARGON2_OUTPUT_PTR_NULL;
}
/* Validate output length */
if (MIN_OUTLEN > context->outlen) {
return ARGON2_OUTPUT_TOO_SHORT;
}
if (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 (MIN_PWD_LENGTH > context->pwdlen) {
return ARGON2_PWD_TOO_SHORT;
}
if (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 (MIN_SALT_LENGTH > context->saltlen) {
return ARGON2_SALT_TOO_SHORT;
}
if (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 (MIN_SECRET > context->secretlen) {
return ARGON2_SECRET_TOO_SHORT;
}
if (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 (MIN_AD_LENGTH > context->adlen) {
return ARGON2_AD_TOO_SHORT;
}
if (MAX_AD_LENGTH < context->adlen) {
return ARGON2_AD_TOO_LONG;
}
}
/* Validate memory cost */
if (MIN_MEMORY > context->m_cost) {
return ARGON2_MEMORY_TOO_LITTLE;
}
if (MAX_MEMORY < context->m_cost) {
return ARGON2_MEMORY_TOO_MUCH;
}
/* Validate time cost */
if (MIN_TIME > context->t_cost) {
return ARGON2_TIME_TOO_SMALL;
}
if (MAX_TIME < context->t_cost) {
return ARGON2_TIME_TOO_LARGE;
}
/* Validate lanes */
if (MIN_LANES > context->lanes) {
return ARGON2_LANES_TOO_FEW;
}
if (MAX_LANES < context->lanes) {
return ARGON2_LANES_TOO_MANY;
}
if (NULL != context->allocate_cbk && NULL == context->free_cbk) {
return ARGON2_FREE_MEMORY_CBK_NULL;
}
if (NULL == context->allocate_cbk && NULL != context->free_cbk) {
return ARGON2_ALLOCATE_MEMORY_CBK_NULL;
}
return ARGON2_OK;
}
void FillFirstBlocks(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 (uint8_t l = 0; l < instance->lanes; ++l) {
blockhash[PREHASH_DIGEST_LENGTH + 4] = l;
blockhash[PREHASH_DIGEST_LENGTH] = 0;
blake2b_long((uint8_t*) (instance->state[l * instance->lane_length].v), blockhash, BLOCK_SIZE, PREHASH_SEED_LENGTH);
blockhash[PREHASH_DIGEST_LENGTH] = 1;
blake2b_long((uint8_t*) (instance->state[l * instance->lane_length + 1].v), blockhash, BLOCK_SIZE, PREHASH_SEED_LENGTH);
}
}
void InitialHash(uint8_t* blockhash, Argon2_Context* context, Argon2_type type) {
blake2b_state BlakeHash;
uint8_t value[sizeof (uint32_t)];
if (NULL == context || NULL == blockhash) {
return;
}
blake2b_init(&BlakeHash, 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, 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;
}
}
store32(&value, context->saltlen);
blake2b_update(&BlakeHash, (const uint8_t*) &value, sizeof (value));
if (context->salt != NULL) {
blake2b_update(&BlakeHash, (const uint8_t*) context->salt, context->saltlen);
}
store32(&value, context->secretlen);
blake2b_update(&BlakeHash, (const uint8_t*) &value, sizeof (value));
if (context->secret != NULL) {
blake2b_update(&BlakeHash, (const uint8_t*) context->secret, context->secretlen);
if (context->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, PREHASH_DIGEST_LENGTH);
}
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;
if (NULL != context->allocate_cbk) {
result = context->allocate_cbk((uint8_t **)&(instance->state), instance->memory_blocks * BLOCK_SIZE);
} else {
result = AllocateMemory(&(instance->state), instance->memory_blocks);
}
if (ARGON2_OK != result) {
return result;
}
// 2. Initial hashing
// H_0 + 8 extra bytes to produce the first blocks
uint8_t blockhash[PREHASH_SEED_LENGTH];
// Hashing all inputs
InitialHash(blockhash, context, instance->type);
// Zeroing 8 extra bytes
secure_wipe_memory(blockhash + PREHASH_DIGEST_LENGTH, PREHASH_SEED_LENGTH - PREHASH_DIGEST_LENGTH);
#ifdef KAT
InitialKat(blockhash, context, instance->type);
#endif
// 3. Creating first blocks, we always have at least two blocks in a slice
FillFirstBlocks(blockhash, instance);
// Clearing the hash
secure_wipe_memory(blockhash, PREHASH_SEED_LENGTH);
return ARGON2_OK;
}
int Argon2Core(Argon2_Context* context, Argon2_type type) {
/* 1. Validate all inputs */
int result = ValidateInputs(context);
if (ARGON2_OK != result) {
return result;
}
if (type > MAX_ARGON2_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;
if (memory_blocks < 2 * SYNC_POINTS * context->lanes) {
memory_blocks = 2 * SYNC_POINTS * context->lanes;
}
uint32_t segment_length = memory_blocks / (context->lanes * SYNC_POINTS);
// Ensure that all segments have equal length
memory_blocks = segment_length * (context->lanes * SYNC_POINTS);
Argon2_instance_t instance(NULL, type, context->t_cost, memory_blocks, context->lanes);
/* 3. Initialization: Hashing inputs, allocating memory, filling first blocks */
result = Initialize(&instance, context);
if (ARGON2_OK != result) {
return result;
}
/* 4. Filling memory */
FillMemoryBlocks(&instance);
/* 5. Finalization */
Finalize(context, &instance);
return ARGON2_OK;
}

View file

@ -1,254 +0,0 @@
/*
* Argon2 source code package
*
* 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/>.
*/
#pragma once
#ifndef __ARGON2_CORE_H__
#define __ARGON2_CORE_H__
#include <cstring>
/*************************Argon2 internal constants**************************************************/
/* Version of the algorithm */
const uint8_t VERSION_NUMBER = 0x10;
/* Memory block size in bytes */
const uint32_t BLOCK_SIZE = 1024;
const uint32_t WORDS_IN_BLOCK = BLOCK_SIZE / sizeof (uint64_t);
const uint32_t QWORDS_IN_BLOCK = WORDS_IN_BLOCK / 2;
/* Number of pseudo-random values generated by one call to Blake in Argon2i to generate reference block positions*/
const uint32_t ADDRESSES_IN_BLOCK = (BLOCK_SIZE * sizeof (uint8_t) / sizeof (uint64_t));
/* Pre-hashing digest length and its extension*/
const uint32_t PREHASH_DIGEST_LENGTH = 64;
const uint32_t PREHASH_SEED_LENGTH = PREHASH_DIGEST_LENGTH + 8;
/* Argon2 primitive type */
enum Argon2_type {
Argon2_d=0,
Argon2_i=1,
Argon2_di=2,
Argon2_id=3,
Argon2_ds=4,
MAX_ARGON2_TYPE /* Do NOT remove; Do NOT other types after this one */
};
/*****SM-related constants******/
const uint32_t SBOX_SIZE = 1 << 10;
const uint32_t SBOX_MASK = SBOX_SIZE / 2 - 1;
/*************************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).
*/
struct block {
uint64_t v[WORDS_IN_BLOCK];
block() { //default ctor
}
block(uint8_t in) {
memset(v, in, BLOCK_SIZE);
}
uint64_t& operator[](const uint8_t i) { //Subscript operator
return v[i];
}
block& operator=(const block& r) { //Assignment operator
memcpy(v, r.v, BLOCK_SIZE);
return *this;
}
block& operator^=(const block& r) { //Xor-assignment
for (uint8_t j = 0; j < WORDS_IN_BLOCK; ++j) {
v[j] ^= r.v[j];
}
return *this;
}
block(const block& r) {
memcpy(v, r.v, BLOCK_SIZE);
}
};
/*
* XORs two blocks
* @param l Left operand
* @param r Right operand
* @return Xors of the blocks
*/
block operator^(const block& l, const block& r);
/*
* 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
*/
struct Argon2_instance_t {
block* state; //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 uint8_t lanes;
const Argon2_type type;
uint64_t *Sbox; //S-boxes for Argon2_ds
Argon2_instance_t(block* ptr = NULL, Argon2_type t = Argon2_d, uint32_t p = 1, uint32_t m = 8, uint8_t l = 1) :
state(ptr), type(t), passes(p), memory_blocks(m), lanes(l), segment_length(m / (l*SYNC_POINTS)), lane_length(m / l), Sbox(NULL) {
};
};
/*
* Argon2 position: where we construct the block right now. Used to distribute work between threads.
*/
struct Argon2_position_t {
const uint32_t pass;
const uint8_t lane;
const uint8_t slice;
uint32_t index;
Argon2_position_t(uint32_t p = 0, uint8_t l = 0, uint8_t s = 0, uint32_t i = 0) : pass(p), slice(s), lane(l), index(i) {
};
};
/*Macro for endianness conversion*/
#if defined(_MSC_VER)
#define BSWAP32(x) _byteswap_ulong(x)
#else
#define BSWAP32(x) __builtin_bswap32(x)
#endif
/*************************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 AllocateMemory(block **memory, uint32_t m_cost);
/* Deallocates memory
* @param instance pointer to the current instance
* @param clear_memory indicates if we clear the memory with zeros.
*/
void FreeMemory(Argon2_instance_t* instance, bool clear_memory);
/*
* 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 GenerateAddresses(const Argon2_instance_t* instance, const Argon2_position_t* position, uint64_t* pseudo_rands);
/*
* 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
* @pre All pointers must be valid
*/
uint32_t IndexAlpha(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
* @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>
*/
int ValidateInputs(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.
* @param blockhash Buffer for pre-hashing digest
* @param type Argon2 type
* @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes allocated
*/
void InitialHash(uint8_t* blockhash, const Argon2_Context* context, Argon2_type type);
/*
* Function creates first 2 blocks per lane
* @param instance Pointer to the current instance
* @param blockhash Pointer to the pre-hashing digest
* @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
*/
void FillFirstBlocks(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
* initialized
* @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.
*/
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)
* @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
*/
void Finalize(const Argon2_Context *context, Argon2_instance_t* instance);
/*
* Function fills a new memory block
* @param prev_block Pointer to the previous block
* @param ref_block Pointer to the reference block
* @param next_block Pointer to the block to be constructed
* @param Sbox Pointer to the Sbox (used in Argon2_ds only)
* @pre all block pointers must be valid
*/
void FillBlock(const block* prev_block, const block* ref_block, block* next_block, const uint64_t* Sbox);
/*
* 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 FillSegment(const Argon2_instance_t* instance, Argon2_position_t position);
/*
* 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 FillMemoryBlocks(const 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 Argon2Core(Argon2_Context* context, Argon2_type type);
/*
* Generates the Sbox from the first memory block (must be ready at that time)
* @param instance Pointer to the current instance
*/
void GenerateSbox(Argon2_instance_t* instance);
#endif

View file

@ -1,250 +0,0 @@
/*
* Argon2 source code package
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* You should have received a copy of the CC0 Public Domain Dedication along with
* this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdint.h>
#if !defined(_MSC_VER)
#include <x86intrin.h>
#else
#include <emmintrin.h>
#include <smmintrin.h>
#include <intrin.h>
#endif
#include "argon2.h"
#include "argon2-core.h"
#include "kat.h"
#include "blake2-round-mka.h"
#include "blake2-impl.h"
#include "blake2.h"
#if defined(KAT) || defined(KAT_INTERNAL)
/* The KAT file name */
const char* KAT_FILENAME = "kat-argon2-opt.log";
#endif
const __m128i r16 = _mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9);
const __m128i r24 = _mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10);
__m128i t0, t1;
/*
* Function fills a new memory block
* @param state Pointer to the just produced block. Content will be updated(!)
* @param ref_block Pointer to the reference block
* @param next_block Pointer to the block to be constructed
* @param Sbox Pointer to the Sbox (used in Argon2_ds only)
* @pre all block pointers must be valid
*/
void FillBlock(__m128i* state, const uint8_t *ref_block, uint8_t *next_block, const uint64_t* Sbox) {
__m128i block_XY[QWORDS_IN_BLOCK];
//__m128i state[64];
for (uint8_t i = 0; i < QWORDS_IN_BLOCK; i++) {
block_XY[i] = _mm_load_si128((__m128i *) ref_block);
ref_block += 16;
}
for (uint8_t i = 0; i < QWORDS_IN_BLOCK; i++) {
block_XY[i] = state[i] = _mm_xor_si128(state[i], block_XY[i]);
}
uint64_t x = 0;
if (Sbox != NULL) {
x = _mm_extract_epi64(block_XY[0], 0) ^ _mm_extract_epi64(block_XY[QWORDS_IN_BLOCK - 1],1);
for (int i = 0; i < 6 * 16; ++i) {
uint32_t x1 = x >> 32;
uint32_t x2 = x & 0xFFFFFFFF;
uint64_t y = Sbox[x1 & SBOX_MASK];
uint64_t z = Sbox[x2 & SBOX_MASK + SBOX_SIZE / 2];
x = (uint64_t) x1 * (uint64_t) x2;
x += y;
x ^= z;
}
}
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[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[32], state[33], state[34], state[35],
state[36], state[37], state[38], state[39]);
BLAKE2_ROUND(state[40], state[41], state[42], state[43],
state[44], state[45], state[46], state[47]);
BLAKE2_ROUND(state[48], state[49], state[50], state[51],
state[52], state[53], state[54], state[55]);
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[2], state[10], state[18], state[26],
state[34], state[42], state[50], state[58])
BLAKE2_ROUND(state[3], state[11], state[19], state[27],
state[35], state[43], state[51], state[59]);
BLAKE2_ROUND(state[4], state[12], state[20], state[28],
state[36], state[44], state[52], state[60]);
BLAKE2_ROUND(state[5], state[13], state[21], state[29],
state[37], state[45], state[53], state[61]);
BLAKE2_ROUND(state[6], state[14], state[22], state[30],
state[38], state[46], state[54], state[62]);
BLAKE2_ROUND(state[7], state[15], state[23], state[31],
state[39], state[47], state[55], state[63]);
for (uint8_t i = 0; i < QWORDS_IN_BLOCK; i++) {
// Feedback
state[i] = _mm_xor_si128(state[i], block_XY[i]);
}
state[0] = _mm_add_epi64(state[0], _mm_set_epi64x(0, x));
state[QWORDS_IN_BLOCK - 1] = _mm_add_epi64(state[QWORDS_IN_BLOCK - 1], _mm_set_epi64x(x, 0));
for (uint8_t i = 0; i < QWORDS_IN_BLOCK; i++) {
_mm_store_si128((__m128i *) next_block, state[i]);
next_block += 16;
}
}
void GenerateAddresses(const Argon2_instance_t* instance, const Argon2_position_t* position, uint64_t* pseudo_rands) {
block input_block(0), 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;
for (uint32_t i = 0; i < instance->segment_length; ++i) {
if (i % ADDRESSES_IN_BLOCK == 0) {
input_block.v[6]++;
block zero_block(0), zero2_block(0);
FillBlock((__m128i *) & zero_block.v, (uint8_t *)& input_block.v, (uint8_t *)& address_block.v, NULL);
FillBlock((__m128i *) & zero2_block.v, (uint8_t *)& address_block.v, (uint8_t *)& address_block.v, NULL);
}
pseudo_rands[i] = address_block[i % ADDRESSES_IN_BLOCK];
}
}
}
/*
* 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 FillSegment(const Argon2_instance_t* instance, Argon2_position_t position) {
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) || (instance->type == Argon2_id && (position.pass == 0) && (position.slice < SYNC_POINTS / 2));
if (instance != NULL) {
// Pseudo-random values that determine the reference block position
uint64_t *pseudo_rands = new uint64_t[instance->segment_length];
if (pseudo_rands != NULL) {
if (data_independent_addressing) {
GenerateAddresses(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->state + prev_offset), 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;
}
/* 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->state[prev_offset][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 = IndexAlpha(instance, &position, pseudo_rand & 0xFFFFFFFF, ref_lane == position.lane);
/* 2 Creating a new block */
block* ref_block = instance->state + instance->lane_length * ref_lane + ref_index;
block* curr_block = instance->state + curr_offset;
FillBlock(state, (uint8_t *) ref_block->v, (uint8_t *) curr_block->v, instance->Sbox);
}
delete[] pseudo_rands;
}
}
}
void GenerateSbox(Argon2_instance_t* instance) {
block start_block(instance->state[0]), out_block(0), zero_block(0);
if (instance == NULL)
return;
if (instance->Sbox == NULL)
instance->Sbox = new uint64_t[SBOX_SIZE];
for (uint32_t i = 0; i < SBOX_SIZE / WORDS_IN_BLOCK; ++i) {
block zero_block(0), zero2_block(0);
FillBlock((__m128i*)zero_block.v, (uint8_t*)start_block.v, (uint8_t*)out_block.v, NULL);
FillBlock((__m128i*) zero2_block.v, (uint8_t*)out_block.v, (uint8_t*)start_block.v,NULL);
memcpy(instance->Sbox + i*WORDS_IN_BLOCK, start_block.v, BLOCK_SIZE);
}
}

View file

@ -1,165 +0,0 @@
/*
* Argon2 source code package
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* You should have received a copy of the CC0 Public Domain Dedication along with
* this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdint.h>
#include "argon2.h"
#include "argon2-core.h"
#include "kat.h"
#include "blake-round-mka.h"
#include "blake2-impl.h"
#include "blake2.h"
#if defined(KAT) || defined(KAT_INTERNAL)
/* The KAT file name */
const char* KAT_FILENAME = "kat-argon2-ref.log";
#endif
void FillBlock(const block* prev_block, const block* ref_block, block* next_block, const uint64_t* Sbox) {
block blockR = *prev_block ^ *ref_block;
block block_tmp = blockR;
uint64_t x = 0;
if (Sbox != NULL) {
x = blockR[0] ^ blockR[WORDS_IN_BLOCK - 1];
for (int i = 0; i < 6 * 16; ++i) {
uint32_t x1 = x >> 32;
uint32_t x2 = x & 0xFFFFFFFF;
uint64_t y = Sbox[x1 & SBOX_MASK];
uint64_t z = Sbox[x2 & SBOX_MASK + SBOX_SIZE / 2];
x = (uint64_t) x1 * (uint64_t) x2;
x += y;
x ^= z;
}
}
// 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[16 * i], blockR[16 * i + 1], blockR[16 * i + 2], blockR[16 * i + 3],
blockR[16 * i + 4], blockR[16 * i + 5], blockR[16 * i + 6], blockR[16 * i + 7],
blockR[16 * i + 8], blockR[16 * i + 9], blockR[16 * i + 10], blockR[16 * i + 11],
blockR[16 * i + 12], blockR[16 * i + 13], blockR[16 * i + 14], blockR[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[2 * i], blockR[2 * i + 1], blockR[2 * i + 16], blockR[2 * i + 17],
blockR[2 * i + 32], blockR[2 * i + 33], blockR[2 * i + 48], blockR[2 * i + 49],
blockR[2 * i + 64], blockR[2 * i + 65], blockR[2 * i + 80], blockR[2 * i + 81],
blockR[2 * i + 96], blockR[2 * i + 97], blockR[2 * i + 112], blockR[2 * i + 113]);
}
*next_block = blockR ^ block_tmp;
next_block->v[0] += x;
next_block->v[WORDS_IN_BLOCK - 1] += x;
}
void GenerateAddresses(const Argon2_instance_t* instance, const Argon2_position_t* position, uint64_t* pseudo_rands) {
block zero_block(0), input_block(0), 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;
for (uint32_t i = 0; i < instance->segment_length; ++i) {
if (i % ADDRESSES_IN_BLOCK == 0) {
input_block.v[6]++;
FillBlock(&zero_block, &input_block, &address_block, NULL);
FillBlock(&zero_block, &address_block, &address_block, NULL);
}
pseudo_rands[i] = address_block[i % ADDRESSES_IN_BLOCK];
}
}
}
void FillSegment(const Argon2_instance_t* instance, Argon2_position_t position) {
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
bool data_independent_addressing = (instance->type == Argon2_i) || (instance->type == Argon2_id && (position.pass == 0) && (position.slice < SYNC_POINTS / 2));
if (instance != NULL) {
// Pseudo-random values that determine the reference block position
uint64_t *pseudo_rands = new uint64_t[instance->segment_length];
if (pseudo_rands != NULL) {
if (data_independent_addressing) {
GenerateAddresses(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;
}
/* 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->state[prev_offset][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 = IndexAlpha(instance, &position, pseudo_rand & 0xFFFFFFFF, ref_lane == position.lane);
/* 2 Creating a new block */
block* ref_block = instance->state + instance->lane_length * ref_lane + ref_index;
block* curr_block = instance->state + curr_offset;
FillBlock(instance->state + prev_offset, ref_block, curr_block, instance->Sbox);
}
delete[] pseudo_rands;
}
}
}
void GenerateSbox(Argon2_instance_t* instance) {
block zero_block(0), start_block(instance->state[0]), out_block(0);
if (instance == NULL)
return;
if (instance->Sbox == NULL)
instance->Sbox = new uint64_t[SBOX_SIZE];
for (uint32_t i = 0; i < SBOX_SIZE / WORDS_IN_BLOCK; ++i) {
FillBlock(&zero_block, &start_block, &out_block, NULL);
FillBlock(&zero_block, &out_block, &start_block, NULL);
memcpy(instance->Sbox + i*WORDS_IN_BLOCK, start_block.v, BLOCK_SIZE);
}
}

View file

@ -1,126 +0,0 @@
/*
* Argon2 source code package
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* You should have received a copy of the CC0 Public Domain Dedication along with
* this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <cstdio>
#include <inttypes.h>
#include "argon2.h"
#include "argon2-core.h"
#ifdef KAT
void InitialKat(const uint8_t* blockhash, const Argon2_Context* context, Argon2_type type) {
FILE* fp = fopen(KAT_FILENAME, "a+");
if (fp && blockhash != NULL && context != NULL) {
fprintf(fp, "=======================================");
switch (type) {
case Argon2_d:
fprintf(fp, "Argon2d\n");
break;
case Argon2_i:
fprintf(fp, "Argon2i\n");
break;
case Argon2_di:
fprintf(fp, "Argon2di\n");
break;
case Argon2_id:
fprintf(fp, "Argon2id\n");
break;
case Argon2_ds:
fprintf(fp, "Argon2ds\n");
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 < PREHASH_DIGEST_LENGTH; ++i) {
fprintf(fp, "%2.2x ", ((unsigned char*) blockhash)[i]);
}
fprintf(fp, "\n");
fclose(fp);
}
}
void PrintTag(const void* out, uint32_t outlen) {
FILE* fp = fopen(KAT_FILENAME, "a+");
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);
}
}
#endif
#ifdef KAT_INTERNAL
void InternalKat(const Argon2_instance_t* instance, uint32_t pass) {
FILE* fp = fopen(KAT_FILENAME, "a+");
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 > WORDS_IN_BLOCK) ? 1 : WORDS_IN_BLOCK;
for (uint32_t j = 0; j < how_many_words; ++j)
fprintf(fp, "Block %.4d [%3d]: %016" PRIx64 "\n", i, j, instance->state[i][j]);
}
fclose(fp);
}
}
#endif

View file

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

View file

@ -21,6 +21,14 @@ else (WIN32)
IF (CMAKE_SYSTEM_PROCESSOR MATCHES "^(i.86|x86(_64)?)$")
set (PLATFORM_COMPILE_FLAGS "${PLATFORM_COMPILE_FLAGS} -msse4")
set (BLAKE2_IMPLEMENTATION "blake2/blake2b.c")
if (ENABLE_AVX2)
set (PLATFORM_COMPILE_FLAGS "${PLATFORM_COMPILE_FLAGS} -mavx2 -mbmi -mbmi2")
if (PERMUTE_WITH_GATHER)
set (PLATFORM_COMPILE_FLAGS "${PLATFORM_COMPILE_FLAGS} -DPERMUTE_WITH_GATHER")
elseif (PERMUTE_WITH_SHUFFLES)
set (PLATFORM_COMPILE_FLAGS "${PLATFORM_COMPILE_FLAGS} -DPERMUTE_WITH_SHUFFLES")
endif()
endif()
else()
set (BLAKE2_IMPLEMENTATION "blake2/blake2b-ref.c")
endif()
@ -77,15 +85,14 @@ add_library (ed25519
ed25519-donna/ed25519.h
ed25519-donna/ed25519.c)
include_directories("${CMAKE_SOURCE_DIR}/Argon2/Source/Argon2")
include_directories("${CMAKE_SOURCE_DIR}/Argon2/Source/Blake2")
include_directories("${CMAKE_SOURCE_DIR}/Argon2/Source/Core")
include_directories("${CMAKE_SOURCE_DIR}/phc-winner-argon2/include")
include_directories("${CMAKE_SOURCE_DIR}/phc-winner-argon2/src")
include_directories("${CMAKE_SOURCE_DIR}/blake2")
if (CMAKE_SYSTEM_PROCESSOR EQUAL "x86_64")
set (ARGON_CORE Argon2/Source/Core/argon2-opt-core.cpp)
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
set (ARGON_CORE phc-winner-argon2/src/opt.c)
else ()
set (ARGON_CORE Argon2/Source/Core/argon2-ref-core.cpp)
set (ARGON_CORE phc-winner-argon2/src/ref.c)
endif ()
add_subdirectory (gtest)
@ -105,11 +112,11 @@ set (USE_INTERMEDIATE_OBJECTS_TARGET OFF CACHE BOOL "")
add_subdirectory (cryptopp)
add_library (argon2
Argon2/Source/Argon2/argon2.cpp
Argon2/Source/Argon2/argon2.h
Argon2/Source/Common/brg-endian.h
Argon2/Source/Core/argon2-core.cpp
Argon2/Source/Core/argon2-core.h
phc-winner-argon2/src/argon2.c
phc-winner-argon2/include/argon2.h
phc-winner-argon2/src/core.c
phc-winner-argon2/src/thread.c
phc-winner-argon2/src/encoding.c
${ARGON_CORE})
add_library (xxhash
@ -240,7 +247,7 @@ add_executable (rai_node
rai/rai_node/daemon.hpp
rai/rai_node/entry.cpp)
set_target_properties (argon2 PROPERTIES COMPILE_FLAGS "${PLATFORM_CXX_FLAGS} ${PLATFORM_COMPILE_FLAGS}")
set_target_properties (argon2 PROPERTIES COMPILE_FLAGS "${PLATFORM_C_FLAGS} ${PLATFORM_COMPILE_FLAGS}")
set_target_properties (blake2 PROPERTIES COMPILE_FLAGS "${PLATFORM_C_FLAGS} ${PLATFORM_COMPILE_FLAGS} -D__SSE2__")
set_target_properties (ed25519 PROPERTIES COMPILE_FLAGS "${PLATFORM_C_FLAGS} ${PLATFORM_COMPILE_FLAGS} -DED25519_CUSTOMHASH -DED25519_CUSTOMRNG")
set_target_properties (secure node rai_node PROPERTIES COMPILE_FLAGS "${PLATFORM_CXX_FLAGS} ${PLATFORM_COMPILE_FLAGS} -DQT_NO_KEYWORDS -DACTIVE_NETWORK=${ACTIVE_NETWORK} -DRAIBLOCKS_VERSION_MAJOR=${CPACK_PACKAGE_VERSION_MAJOR} -DRAIBLOCKS_VERSION_MINOR=${CPACK_PACKAGE_VERSION_MINOR} -DBOOST_ASIO_HAS_STD_ARRAY=1")

View file

@ -1,21 +1,22 @@
/*
BLAKE2 reference source code package - optimized C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#pragma once
#ifndef __BLAKE2_CONFIG_H__
#define __BLAKE2_CONFIG_H__
#ifndef BLAKE2_CONFIG_H
#define BLAKE2_CONFIG_H
// These don't work everywhere
#if defined(__SSE2__)
/* These don't work everywhere */
#if defined(__SSE2__) || defined(__x86_64__) || defined(__amd64__)
#define HAVE_SSE2
#endif
@ -31,6 +32,10 @@
#define HAVE_AVX
#endif
#if defined(__AVX2__)
#define HAVE_AVX2
#endif
#if defined(__XOP__)
#define HAVE_XOP
#endif
@ -69,4 +74,3 @@
#endif
#endif

View file

@ -1,133 +1,160 @@
/*
BLAKE2 reference source code package - optimized C implementations
BLAKE2 reference source code package - reference C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#pragma once
#ifndef __BLAKE2_IMPL_H__
#define __BLAKE2_IMPL_H__
#ifndef BLAKE2_IMPL_H
#define BLAKE2_IMPL_H
#include <stdint.h>
#include <string.h>
static inline uint32_t load32( const void *src )
#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
#if defined(_MSC_VER)
#define BLAKE2_INLINE __inline
#elif defined(__GNUC__)
#define BLAKE2_INLINE __inline__
#else
#define BLAKE2_INLINE
#endif
#else
#define BLAKE2_INLINE inline
#endif
static BLAKE2_INLINE uint32_t load32( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
return *( uint32_t * )( src );
#else
const uint8_t *p = ( uint8_t * )src;
uint32_t w = *p++;
w |= ( uint32_t )( *p++ ) << 8;
w |= ( uint32_t )( *p++ ) << 16;
w |= ( uint32_t )( *p++ ) << 24;
uint32_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return (( uint32_t )( p[0] ) << 0) |
(( uint32_t )( p[1] ) << 8) |
(( uint32_t )( p[2] ) << 16) |
(( uint32_t )( p[3] ) << 24) ;
#endif
}
static inline uint64_t load64( const void *src )
static BLAKE2_INLINE uint64_t load64( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
return *( uint64_t * )( src );
#else
const uint8_t *p = ( 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;
uint64_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return (( uint64_t )( p[0] ) << 0) |
(( uint64_t )( p[1] ) << 8) |
(( uint64_t )( p[2] ) << 16) |
(( uint64_t )( p[3] ) << 24) |
(( uint64_t )( p[4] ) << 32) |
(( uint64_t )( p[5] ) << 40) |
(( uint64_t )( p[6] ) << 48) |
(( uint64_t )( p[7] ) << 56) ;
#endif
}
static inline void store32( void *dst, uint32_t w )
static BLAKE2_INLINE uint16_t load16( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
*( uint32_t * )( dst ) = w;
uint16_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return (( uint16_t )( p[0] ) << 0) |
(( uint16_t )( p[1] ) << 8) ;
#endif
}
static BLAKE2_INLINE void store16( void *dst, uint16_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
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;
#endif
}
static inline void store64( void *dst, uint64_t w )
static BLAKE2_INLINE void store32( void *dst, uint32_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
*( uint64_t * )( dst ) = 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;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
#endif
}
static inline uint64_t load48( const void *src )
static BLAKE2_INLINE void store64( void *dst, uint64_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
p[4] = (uint8_t)(w >> 32);
p[5] = (uint8_t)(w >> 40);
p[6] = (uint8_t)(w >> 48);
p[7] = (uint8_t)(w >> 56);
#endif
}
static BLAKE2_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;
return (( uint64_t )( p[0] ) << 0) |
(( uint64_t )( p[1] ) << 8) |
(( uint64_t )( p[2] ) << 16) |
(( uint64_t )( p[3] ) << 24) |
(( uint64_t )( p[4] ) << 32) |
(( uint64_t )( p[5] ) << 40) ;
}
static inline void store48( void *dst, uint64_t w )
static BLAKE2_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;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
p[4] = (uint8_t)(w >> 32);
p[5] = (uint8_t)(w >> 40);
}
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 uint32_t rotr32( const uint32_t w, const unsigned c )
static BLAKE2_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 )
static BLAKE2_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 )
static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
{
volatile uint8_t *p = ( volatile uint8_t * )v;
while( n-- ) *p++ = 0;
static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
memset_v(v, 0, n);
}
#endif

View file

@ -1,26 +1,27 @@
/*
BLAKE2 reference source code package - optimized C implementations
BLAKE2 reference source code package - reference C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#pragma once
#ifndef __BLAKE2_H__
#define __BLAKE2_H__
#ifndef BLAKE2_H
#define BLAKE2_H
#include <stddef.h>
#include <stdint.h>
#if defined(_MSC_VER)
#define ALIGN(x) __declspec(align(x))
#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
#else
#define ALIGN(x) __attribute__ ((__aligned__(x)))
#define BLAKE2_PACKED(x) x __attribute__((packed))
#endif
#if defined(__cplusplus)
@ -45,112 +46,150 @@ extern "C" {
BLAKE2B_PERSONALBYTES = 16
};
#pragma pack(push, 1)
typedef struct __blake2s_param
{
uint8_t digest_length; // 1
uint8_t key_length; // 2
uint8_t fanout; // 3
uint8_t depth; // 4
uint32_t leaf_length; // 8
uint8_t node_offset[6];// 14
uint8_t node_depth; // 15
uint8_t inner_length; // 16
// uint8_t reserved[0];
uint8_t salt[BLAKE2S_SALTBYTES]; // 24
uint8_t personal[BLAKE2S_PERSONALBYTES]; // 32
} blake2s_param;
ALIGN( 64 ) typedef struct __blake2s_state
typedef struct blake2s_state__
{
uint32_t h[8];
uint32_t t[2];
uint32_t f[2];
uint8_t buf[2 * BLAKE2S_BLOCKBYTES];
uint8_t buf[BLAKE2S_BLOCKBYTES];
size_t buflen;
size_t outlen;
uint8_t last_node;
} blake2s_state;
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
typedef struct blake2b_state__
{
uint64_t h[8];
uint64_t t[2];
uint64_t f[2];
uint8_t buf[2 * BLAKE2B_BLOCKBYTES];
uint8_t buf[BLAKE2B_BLOCKBYTES];
size_t buflen;
size_t outlen;
uint8_t last_node;
} blake2b_state;
ALIGN( 64 ) typedef struct __blake2sp_state
typedef struct blake2sp_state__
{
blake2s_state S[8][1];
blake2s_state R[1];
uint8_t buf[8 * BLAKE2S_BLOCKBYTES];
size_t buflen;
uint8_t buf[8 * BLAKE2S_BLOCKBYTES];
size_t buflen;
size_t outlen;
} blake2sp_state;
ALIGN( 64 ) typedef struct __blake2bp_state
typedef struct blake2bp_state__
{
blake2b_state S[4][1];
blake2b_state R[1];
uint8_t buf[4 * BLAKE2B_BLOCKBYTES];
size_t buflen;
uint8_t buf[4 * BLAKE2B_BLOCKBYTES];
size_t buflen;
size_t outlen;
} blake2bp_state;
#pragma pack(pop)
// Streaming API
int blake2s_init( blake2s_state *S, const uint8_t outlen );
int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen );
int blake2s_final( blake2s_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 blake2sp_init( blake2sp_state *S, const uint8_t outlen );
int blake2sp_init_key( blake2sp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
int blake2sp_update( blake2sp_state *S, const uint8_t *in, uint64_t inlen );
int blake2sp_final( blake2sp_state *S, uint8_t *out, uint8_t outlen );
int blake2bp_init( blake2bp_state *S, const uint8_t outlen );
int blake2bp_init_key( blake2bp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
int blake2bp_update( blake2bp_state *S, const uint8_t *in, uint64_t inlen );
int blake2bp_final( blake2bp_state *S, uint8_t *out, uint8_t outlen );
// Simple API
int blake2s( 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 );
int blake2sp( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
int blake2bp( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
static inline int blake2( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
BLAKE2_PACKED(struct blake2s_param__
{
return blake2b( out, in, key, outlen, inlen, keylen );
}
uint8_t digest_length; /* 1 */
uint8_t key_length; /* 2 */
uint8_t fanout; /* 3 */
uint8_t depth; /* 4 */
uint32_t leaf_length; /* 8 */
uint32_t node_offset; /* 12 */
uint16_t xof_length; /* 14 */
uint8_t node_depth; /* 15 */
uint8_t inner_length; /* 16 */
/* uint8_t reserved[0]; */
uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
});
typedef struct blake2s_param__ blake2s_param;
BLAKE2_PACKED(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 */
uint32_t node_offset; /* 12 */
uint32_t xof_length; /* 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__ blake2b_param;
typedef struct blake2xs_state__
{
blake2s_state S[1];
blake2s_param P[1];
} blake2xs_state;
typedef struct blake2xb_state__
{
blake2b_state S[1];
blake2b_param P[1];
} blake2xb_state;
/* Padded structs result in a compile-time error */
enum {
BLAKE2_DUMMY_1 = 1/(sizeof(blake2s_param) == BLAKE2S_OUTBYTES),
BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES)
};
/* Streaming API */
int blake2s_init( blake2s_state *S, size_t outlen );
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
int blake2s_update( blake2s_state *S, const void *in, size_t inlen );
int blake2s_final( blake2s_state *S, void *out, size_t outlen );
int blake2b_init( blake2b_state *S, size_t outlen );
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
int blake2b_update( blake2b_state *S, const void *in, size_t inlen );
int blake2b_final( blake2b_state *S, void *out, size_t outlen );
int blake2sp_init( blake2sp_state *S, size_t outlen );
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
int blake2bp_init( blake2bp_state *S, size_t outlen );
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
/* Variable output length API */
int blake2xs_init( blake2xs_state *S, const size_t outlen );
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
int blake2xb_init( blake2xb_state *S, const size_t outlen );
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
/* Simple API */
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
/* This is simply an alias for blake2b */
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
#if defined(__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,207 @@
/*
https://github.com/sneves/blake2-avx2
https://github.com/jedisct1/libsodium/
*/
#ifndef blake2b_compress_avx2_H
#define blake2b_compress_avx2_H
#define LOAD128(p) _mm_load_si128((__m128i *) (p))
#define STORE128(p, r) _mm_store_si128((__m128i *) (p), r)
#define LOADU128(p) _mm_loadu_si128((__m128i *) (p))
#define STOREU128(p, r) _mm_storeu_si128((__m128i *) (p), r)
#define LOAD(p) _mm256_load_si256((__m256i *) (p))
#define STORE(p, r) _mm256_store_si256((__m256i *) (p), r)
#define LOADU(p) _mm256_loadu_si256((__m256i *) (p))
#define STOREU(p, r) _mm256_storeu_si256((__m256i *) (p), r)
static inline uint64_t
LOADU64(const void *p)
{
uint64_t v;
memcpy(&v, p, sizeof v);
return v;
}
#define ROTATE16 \
_mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, 2, \
3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9)
#define ROTATE24 \
_mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, 3, \
4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10)
#define ADD(a, b) _mm256_add_epi64(a, b)
#define SUB(a, b) _mm256_sub_epi64(a, b)
#define XOR(a, b) _mm256_xor_si256(a, b)
#define AND(a, b) _mm256_and_si256(a, b)
#define OR(a, b) _mm256_or_si256(a, b)
#define ROT32(x) _mm256_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1))
#define ROT24(x) _mm256_shuffle_epi8((x), ROTATE24)
#define ROT16(x) _mm256_shuffle_epi8((x), ROTATE16)
#define ROT63(x) _mm256_or_si256(_mm256_srli_epi64((x), 63), ADD((x), (x)))
#define BLAKE2B_G1_V1(a, b, c, d, m) \
do { \
a = ADD(a, m); \
a = ADD(a, b); \
d = XOR(d, a); \
d = ROT32(d); \
c = ADD(c, d); \
b = XOR(b, c); \
b = ROT24(b); \
} while (0)
#define BLAKE2B_G2_V1(a, b, c, d, m) \
do { \
a = ADD(a, m); \
a = ADD(a, b); \
d = XOR(d, a); \
d = ROT16(d); \
c = ADD(c, d); \
b = XOR(b, c); \
b = ROT63(b); \
} while (0)
#define BLAKE2B_DIAG_V1(a, b, c, d) \
do { \
d = _mm256_permute4x64_epi64(d, _MM_SHUFFLE(2, 1, 0, 3)); \
c = _mm256_permute4x64_epi64(c, _MM_SHUFFLE(1, 0, 3, 2)); \
b = _mm256_permute4x64_epi64(b, _MM_SHUFFLE(0, 3, 2, 1)); \
} while (0)
#define BLAKE2B_UNDIAG_V1(a, b, c, d) \
do { \
d = _mm256_permute4x64_epi64(d, _MM_SHUFFLE(0, 3, 2, 1)); \
c = _mm256_permute4x64_epi64(c, _MM_SHUFFLE(1, 0, 3, 2)); \
b = _mm256_permute4x64_epi64(b, _MM_SHUFFLE(2, 1, 0, 3)); \
} while (0)
#if defined(PERMUTE_WITH_SHUFFLES)
#include "blake2b-load-avx2.h"
#elif defined(PERMUTE_WITH_GATHER)
#else
#include "blake2b-load-avx2-simple.h"
#endif
#if defined(PERMUTE_WITH_GATHER)
ALIGN(64) static const uint32_t indices[12][16] = {
{ 0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15},
{14, 4, 9, 13,10, 8, 15, 6, 1, 0, 11, 5,12, 2, 7, 3},
{11, 12, 5, 15, 8, 0, 2, 13,10, 3, 7, 9,14, 6, 1, 4},
{ 7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8},
{ 9, 5, 2, 10, 0, 7, 4, 15,14, 11, 6, 3, 1, 12, 8, 13},
{ 2, 6, 0, 8,12, 10, 11, 3, 4, 7, 15, 1,13, 5, 14, 9},
{12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11},
{13, 7, 12, 3,11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10},
{ 6, 14, 11, 0,15, 9, 3, 8,12, 13, 1, 10, 2, 7, 4, 5},
{10, 8, 7, 1, 2, 4, 6, 5,15, 9, 3, 13,11, 14, 12, 0},
{ 0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15},
{14, 4, 9, 13,10, 8, 15, 6, 1, 0, 11, 5,12, 2, 7, 3},
};
#define BLAKE2B_ROUND_V1(a, b, c, d, r, m) do { \
__m256i b0; \
b0 = _mm256_i32gather_epi64((void *)(m), LOAD128(&indices[r][ 0]), 8); \
BLAKE2B_G1_V1(a, b, c, d, b0); \
b0 = _mm256_i32gather_epi64((void *)(m), LOAD128(&indices[r][ 4]), 8); \
BLAKE2B_G2_V1(a, b, c, d, b0); \
BLAKE2B_DIAG_V1(a, b, c, d); \
b0 = _mm256_i32gather_epi64((void *)(m), LOAD128(&indices[r][ 8]), 8); \
BLAKE2B_G1_V1(a, b, c, d, b0); \
b0 = _mm256_i32gather_epi64((void *)(m), LOAD128(&indices[r][12]), 8); \
BLAKE2B_G2_V1(a, b, c, d, b0); \
BLAKE2B_UNDIAG_V1(a, b, c, d); \
} while(0)
#define BLAKE2B_ROUNDS_V1(a, b, c, d, m) do { \
int i; \
for(i = 0; i < 12; ++i) { \
BLAKE2B_ROUND_V1(a, b, c, d, i, m); \
} \
} while(0)
#else /* !PERMUTE_WITH_GATHER */
#define BLAKE2B_ROUND_V1(a, b, c, d, r, m) do { \
__m256i b0; \
BLAKE2B_LOAD_MSG_ ##r ##_1(b0); \
BLAKE2B_G1_V1(a, b, c, d, b0); \
BLAKE2B_LOAD_MSG_ ##r ##_2(b0); \
BLAKE2B_G2_V1(a, b, c, d, b0); \
BLAKE2B_DIAG_V1(a, b, c, d); \
BLAKE2B_LOAD_MSG_ ##r ##_3(b0); \
BLAKE2B_G1_V1(a, b, c, d, b0); \
BLAKE2B_LOAD_MSG_ ##r ##_4(b0); \
BLAKE2B_G2_V1(a, b, c, d, b0); \
BLAKE2B_UNDIAG_V1(a, b, c, d); \
} while(0)
#define BLAKE2B_ROUNDS_V1(a, b, c, d, m) do { \
BLAKE2B_ROUND_V1(a, b, c, d, 0, (m)); \
BLAKE2B_ROUND_V1(a, b, c, d, 1, (m)); \
BLAKE2B_ROUND_V1(a, b, c, d, 2, (m)); \
BLAKE2B_ROUND_V1(a, b, c, d, 3, (m)); \
BLAKE2B_ROUND_V1(a, b, c, d, 4, (m)); \
BLAKE2B_ROUND_V1(a, b, c, d, 5, (m)); \
BLAKE2B_ROUND_V1(a, b, c, d, 6, (m)); \
BLAKE2B_ROUND_V1(a, b, c, d, 7, (m)); \
BLAKE2B_ROUND_V1(a, b, c, d, 8, (m)); \
BLAKE2B_ROUND_V1(a, b, c, d, 9, (m)); \
BLAKE2B_ROUND_V1(a, b, c, d, 10, (m)); \
BLAKE2B_ROUND_V1(a, b, c, d, 11, (m)); \
} while(0)
#endif
#if defined(PERMUTE_WITH_GATHER)
#define DECLARE_MESSAGE_WORDS(m)
#elif defined(PERMUTE_WITH_SHUFFLES)
#define DECLARE_MESSAGE_WORDS(m) \
const __m256i m0 = _mm256_broadcastsi128_si256(LOADU128((m) + 0)); \
const __m256i m1 = _mm256_broadcastsi128_si256(LOADU128((m) + 16)); \
const __m256i m2 = _mm256_broadcastsi128_si256(LOADU128((m) + 32)); \
const __m256i m3 = _mm256_broadcastsi128_si256(LOADU128((m) + 48)); \
const __m256i m4 = _mm256_broadcastsi128_si256(LOADU128((m) + 64)); \
const __m256i m5 = _mm256_broadcastsi128_si256(LOADU128((m) + 80)); \
const __m256i m6 = _mm256_broadcastsi128_si256(LOADU128((m) + 96)); \
const __m256i m7 = _mm256_broadcastsi128_si256(LOADU128((m) + 112)); \
__m256i t0, t1;
#else
#define DECLARE_MESSAGE_WORDS(m) \
const uint64_t m0 = LOADU64((m) + 0); \
const uint64_t m1 = LOADU64((m) + 8); \
const uint64_t m2 = LOADU64((m) + 16); \
const uint64_t m3 = LOADU64((m) + 24); \
const uint64_t m4 = LOADU64((m) + 32); \
const uint64_t m5 = LOADU64((m) + 40); \
const uint64_t m6 = LOADU64((m) + 48); \
const uint64_t m7 = LOADU64((m) + 56); \
const uint64_t m8 = LOADU64((m) + 64); \
const uint64_t m9 = LOADU64((m) + 72); \
const uint64_t m10 = LOADU64((m) + 80); \
const uint64_t m11 = LOADU64((m) + 88); \
const uint64_t m12 = LOADU64((m) + 96); \
const uint64_t m13 = LOADU64((m) + 104); \
const uint64_t m14 = LOADU64((m) + 112); \
const uint64_t m15 = LOADU64((m) + 120);
#endif
#define BLAKE2B_COMPRESS_V1(a, b, m, t0, t1, f0, f1) \
do { \
DECLARE_MESSAGE_WORDS(m) \
const __m256i iv0 = a; \
const __m256i iv1 = b; \
__m256i c = LOAD(&blake2b_IV[0]); \
__m256i d = \
XOR(LOAD(&blake2b_IV[4]), _mm256_set_epi64x(f1, f0, t1, t0)); \
BLAKE2B_ROUNDS_V1(a, b, c, d, m); \
a = XOR(a, c); \
b = XOR(b, d); \
a = XOR(a, iv0); \
b = XOR(b, iv1); \
} while (0)
#endif

View file

@ -0,0 +1,54 @@
#ifndef BLAKE2_AVX2_BLAKE2B_LOAD_AVX2_SIMPLE_H
#define BLAKE2_AVX2_BLAKE2B_LOAD_AVX2_SIMPLE_H
#define BLAKE2B_LOAD_MSG_0_1(b0) b0 = _mm256_set_epi64x(m6, m4, m2, m0);
#define BLAKE2B_LOAD_MSG_0_2(b0) b0 = _mm256_set_epi64x(m7, m5, m3, m1);
#define BLAKE2B_LOAD_MSG_0_3(b0) b0 = _mm256_set_epi64x(m14, m12, m10, m8);
#define BLAKE2B_LOAD_MSG_0_4(b0) b0 = _mm256_set_epi64x(m15, m13, m11, m9);
#define BLAKE2B_LOAD_MSG_1_1(b0) b0 = _mm256_set_epi64x(m13, m9, m4, m14);
#define BLAKE2B_LOAD_MSG_1_2(b0) b0 = _mm256_set_epi64x(m6, m15, m8, m10);
#define BLAKE2B_LOAD_MSG_1_3(b0) b0 = _mm256_set_epi64x(m5, m11, m0, m1);
#define BLAKE2B_LOAD_MSG_1_4(b0) b0 = _mm256_set_epi64x(m3, m7, m2, m12);
#define BLAKE2B_LOAD_MSG_2_1(b0) b0 = _mm256_set_epi64x(m15, m5, m12, m11);
#define BLAKE2B_LOAD_MSG_2_2(b0) b0 = _mm256_set_epi64x(m13, m2, m0, m8);
#define BLAKE2B_LOAD_MSG_2_3(b0) b0 = _mm256_set_epi64x(m9, m7, m3, m10);
#define BLAKE2B_LOAD_MSG_2_4(b0) b0 = _mm256_set_epi64x(m4, m1, m6, m14);
#define BLAKE2B_LOAD_MSG_3_1(b0) b0 = _mm256_set_epi64x(m11, m13, m3, m7);
#define BLAKE2B_LOAD_MSG_3_2(b0) b0 = _mm256_set_epi64x(m14, m12, m1, m9);
#define BLAKE2B_LOAD_MSG_3_3(b0) b0 = _mm256_set_epi64x(m15, m4, m5, m2);
#define BLAKE2B_LOAD_MSG_3_4(b0) b0 = _mm256_set_epi64x(m8, m0, m10, m6);
#define BLAKE2B_LOAD_MSG_4_1(b0) b0 = _mm256_set_epi64x(m10, m2, m5, m9);
#define BLAKE2B_LOAD_MSG_4_2(b0) b0 = _mm256_set_epi64x(m15, m4, m7, m0);
#define BLAKE2B_LOAD_MSG_4_3(b0) b0 = _mm256_set_epi64x(m3, m6, m11, m14);
#define BLAKE2B_LOAD_MSG_4_4(b0) b0 = _mm256_set_epi64x(m13, m8, m12, m1);
#define BLAKE2B_LOAD_MSG_5_1(b0) b0 = _mm256_set_epi64x(m8, m0, m6, m2);
#define BLAKE2B_LOAD_MSG_5_2(b0) b0 = _mm256_set_epi64x(m3, m11, m10, m12);
#define BLAKE2B_LOAD_MSG_5_3(b0) b0 = _mm256_set_epi64x(m1, m15, m7, m4);
#define BLAKE2B_LOAD_MSG_5_4(b0) b0 = _mm256_set_epi64x(m9, m14, m5, m13);
#define BLAKE2B_LOAD_MSG_6_1(b0) b0 = _mm256_set_epi64x(m4, m14, m1, m12);
#define BLAKE2B_LOAD_MSG_6_2(b0) b0 = _mm256_set_epi64x(m10, m13, m15, m5);
#define BLAKE2B_LOAD_MSG_6_3(b0) b0 = _mm256_set_epi64x(m8, m9, m6, m0);
#define BLAKE2B_LOAD_MSG_6_4(b0) b0 = _mm256_set_epi64x(m11, m2, m3, m7);
#define BLAKE2B_LOAD_MSG_7_1(b0) b0 = _mm256_set_epi64x(m3, m12, m7, m13);
#define BLAKE2B_LOAD_MSG_7_2(b0) b0 = _mm256_set_epi64x(m9, m1, m14, m11);
#define BLAKE2B_LOAD_MSG_7_3(b0) b0 = _mm256_set_epi64x(m2, m8, m15, m5);
#define BLAKE2B_LOAD_MSG_7_4(b0) b0 = _mm256_set_epi64x(m10, m6, m4, m0);
#define BLAKE2B_LOAD_MSG_8_1(b0) b0 = _mm256_set_epi64x(m0, m11, m14, m6);
#define BLAKE2B_LOAD_MSG_8_2(b0) b0 = _mm256_set_epi64x(m8, m3, m9, m15);
#define BLAKE2B_LOAD_MSG_8_3(b0) b0 = _mm256_set_epi64x(m10, m1, m13, m12);
#define BLAKE2B_LOAD_MSG_8_4(b0) b0 = _mm256_set_epi64x(m5, m4, m7, m2);
#define BLAKE2B_LOAD_MSG_9_1(b0) b0 = _mm256_set_epi64x(m1, m7, m8, m10);
#define BLAKE2B_LOAD_MSG_9_2(b0) b0 = _mm256_set_epi64x(m5, m6, m4, m2);
#define BLAKE2B_LOAD_MSG_9_3(b0) b0 = _mm256_set_epi64x(m13, m3, m9, m15);
#define BLAKE2B_LOAD_MSG_9_4(b0) b0 = _mm256_set_epi64x(m0, m12, m14, m11);
#define BLAKE2B_LOAD_MSG_10_1(b0) b0 = _mm256_set_epi64x(m6, m4, m2, m0);
#define BLAKE2B_LOAD_MSG_10_2(b0) b0 = _mm256_set_epi64x(m7, m5, m3, m1);
#define BLAKE2B_LOAD_MSG_10_3(b0) b0 = _mm256_set_epi64x(m14, m12, m10, m8);
#define BLAKE2B_LOAD_MSG_10_4(b0) b0 = _mm256_set_epi64x(m15, m13, m11, m9);
#define BLAKE2B_LOAD_MSG_11_1(b0) b0 = _mm256_set_epi64x(m13, m9, m4, m14);
#define BLAKE2B_LOAD_MSG_11_2(b0) b0 = _mm256_set_epi64x(m6, m15, m8, m10);
#define BLAKE2B_LOAD_MSG_11_3(b0) b0 = _mm256_set_epi64x(m5, m11, m0, m1);
#define BLAKE2B_LOAD_MSG_11_4(b0) b0 = _mm256_set_epi64x(m3, m7, m2, m12);
#endif

340
blake2/blake2b-load-avx2.h Normal file
View file

@ -0,0 +1,340 @@
#ifndef BLAKE2_AVX2_BLAKE2B_LOAD_AVX2_H
#define BLAKE2_AVX2_BLAKE2B_LOAD_AVX2_H
#define BLAKE2B_LOAD_MSG_0_1(b0) do { \
t0 = _mm256_unpacklo_epi64(m0, m1); \
t1 = _mm256_unpacklo_epi64(m2, m3); \
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
} while(0)
#define BLAKE2B_LOAD_MSG_0_2(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m0, m1);\
t1 = _mm256_unpackhi_epi64(m2, m3);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_0_3(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m4, m5);\
t1 = _mm256_unpacklo_epi64(m6, m7);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_0_4(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m4, m5);\
t1 = _mm256_unpackhi_epi64(m6, m7);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_1_1(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m7, m2);\
t1 = _mm256_unpackhi_epi64(m4, m6);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_1_2(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m5, m4);\
t1 = _mm256_alignr_epi8(m3, m7, 8);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_1_3(b0) \
do { \
t0 = _mm256_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2));\
t1 = _mm256_unpackhi_epi64(m5, m2);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_1_4(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m6, m1);\
t1 = _mm256_unpackhi_epi64(m3, m1);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_2_1(b0) \
do { \
t0 = _mm256_alignr_epi8(m6, m5, 8);\
t1 = _mm256_unpackhi_epi64(m2, m7);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_2_2(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m4, m0);\
t1 = _mm256_blend_epi32(m6, m1, 0x33);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_2_3(b0) \
do { \
t0 = _mm256_blend_epi32(m1, m5, 0x33);\
t1 = _mm256_unpackhi_epi64(m3, m4);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_2_4(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m7, m3);\
t1 = _mm256_alignr_epi8(m2, m0, 8);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_3_1(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m3, m1);\
t1 = _mm256_unpackhi_epi64(m6, m5);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_3_2(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m4, m0);\
t1 = _mm256_unpacklo_epi64(m6, m7);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_3_3(b0) \
do { \
t0 = _mm256_blend_epi32(m2, m1, 0x33);\
t1 = _mm256_blend_epi32(m7, m2, 0x33);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_3_4(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m3, m5);\
t1 = _mm256_unpacklo_epi64(m0, m4);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_4_1(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m4, m2);\
t1 = _mm256_unpacklo_epi64(m1, m5);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_4_2(b0) \
do { \
t0 = _mm256_blend_epi32(m3, m0, 0x33);\
t1 = _mm256_blend_epi32(m7, m2, 0x33);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_4_3(b0) \
do { \
t0 = _mm256_blend_epi32(m5, m7, 0x33);\
t1 = _mm256_blend_epi32(m1, m3, 0x33);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_4_4(b0) \
do { \
t0 = _mm256_alignr_epi8(m6, m0, 8);\
t1 = _mm256_blend_epi32(m6, m4, 0x33);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_5_1(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m1, m3);\
t1 = _mm256_unpacklo_epi64(m0, m4);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_5_2(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m6, m5);\
t1 = _mm256_unpackhi_epi64(m5, m1);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_5_3(b0) \
do { \
t0 = _mm256_blend_epi32(m3, m2, 0x33);\
t1 = _mm256_unpackhi_epi64(m7, m0);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_5_4(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m6, m2);\
t1 = _mm256_blend_epi32(m4, m7, 0x33);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_6_1(b0) \
do { \
t0 = _mm256_blend_epi32(m0, m6, 0x33);\
t1 = _mm256_unpacklo_epi64(m7, m2);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_6_2(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m2, m7);\
t1 = _mm256_alignr_epi8(m5, m6, 8);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_6_3(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m0, m3);\
t1 = _mm256_shuffle_epi32(m4, _MM_SHUFFLE(1,0,3,2));\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_6_4(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m3, m1);\
t1 = _mm256_blend_epi32(m5, m1, 0x33);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_7_1(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m6, m3);\
t1 = _mm256_blend_epi32(m1, m6, 0x33);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_7_2(b0) \
do { \
t0 = _mm256_alignr_epi8(m7, m5, 8);\
t1 = _mm256_unpackhi_epi64(m0, m4);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_7_3(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m2, m7);\
t1 = _mm256_unpacklo_epi64(m4, m1);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_7_4(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m0, m2);\
t1 = _mm256_unpacklo_epi64(m3, m5);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_8_1(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m3, m7);\
t1 = _mm256_alignr_epi8(m0, m5, 8);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_8_2(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m7, m4);\
t1 = _mm256_alignr_epi8(m4, m1, 8);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_8_3(b0) \
do { \
t0 = m6;\
t1 = _mm256_alignr_epi8(m5, m0, 8);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_8_4(b0) \
do { \
t0 = _mm256_blend_epi32(m3, m1, 0x33);\
t1 = m2;\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_9_1(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m5, m4);\
t1 = _mm256_unpackhi_epi64(m3, m0);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_9_2(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m1, m2);\
t1 = _mm256_blend_epi32(m2, m3, 0x33);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_9_3(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m7, m4);\
t1 = _mm256_unpackhi_epi64(m1, m6);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_9_4(b0) \
do { \
t0 = _mm256_alignr_epi8(m7, m5, 8);\
t1 = _mm256_unpacklo_epi64(m6, m0);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_10_1(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m0, m1);\
t1 = _mm256_unpacklo_epi64(m2, m3);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_10_2(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m0, m1);\
t1 = _mm256_unpackhi_epi64(m2, m3);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_10_3(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m4, m5);\
t1 = _mm256_unpacklo_epi64(m6, m7);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_10_4(b0) \
do { \
t0 = _mm256_unpackhi_epi64(m4, m5);\
t1 = _mm256_unpackhi_epi64(m6, m7);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_11_1(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m7, m2);\
t1 = _mm256_unpackhi_epi64(m4, m6);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_11_2(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m5, m4);\
t1 = _mm256_alignr_epi8(m3, m7, 8);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_11_3(b0) \
do { \
t0 = _mm256_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2));\
t1 = _mm256_unpackhi_epi64(m5, m2);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#define BLAKE2B_LOAD_MSG_11_4(b0) \
do { \
t0 = _mm256_unpacklo_epi64(m6, m1);\
t1 = _mm256_unpackhi_epi64(m3, m1);\
b0 = _mm256_blend_epi32(t0, t1, 0xF0);\
} while(0)
#endif

View file

@ -1,18 +1,19 @@
/*
BLAKE2 reference source code package - optimized C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#pragma once
#ifndef __BLAKE2B_LOAD_SSE2_H__
#define __BLAKE2B_LOAD_SSE2_H__
#ifndef BLAKE2B_LOAD_SSE2_H
#define BLAKE2B_LOAD_SSE2_H
#define LOAD_MSG_0_1(b0, b1) b0 = _mm_set_epi64x(m2, m0); b1 = _mm_set_epi64x(m6, m4)
#define LOAD_MSG_0_2(b0, b1) b0 = _mm_set_epi64x(m3, m1); b1 = _mm_set_epi64x(m7, m5)
@ -65,4 +66,3 @@
#endif

View file

@ -1,18 +1,19 @@
/*
BLAKE2 reference source code package - optimized C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#pragma once
#ifndef __BLAKE2B_LOAD_SSE41_H__
#define __BLAKE2B_LOAD_SSE41_H__
#ifndef BLAKE2B_LOAD_SSE41_H
#define BLAKE2B_LOAD_SSE41_H
#define LOAD_MSG_0_1(b0, b1) \
do \
@ -399,4 +400,3 @@ b1 = _mm_unpackhi_epi64(m3, m1); \
#endif

View file

@ -1,23 +1,21 @@
/*
BLAKE2 reference source code package - optimized C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#pragma once
#ifndef __BLAKE2B_ROUND_H__
#define __BLAKE2B_ROUND_H__
#ifndef BLAKE2B_ROUND_H
#define BLAKE2B_ROUND_H
#define LOAD(p) _mm_load_si128( (__m128i *)(p) )
#define STORE(p,r) _mm_store_si128((__m128i *)(p), r)
#define LOADU(p) _mm_loadu_si128( (__m128i *)(p) )
#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))
@ -62,7 +60,7 @@
\
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); \
@ -81,7 +79,7 @@
\
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); \
@ -157,4 +155,3 @@
UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h);
#endif

View file

@ -1,14 +1,16 @@
/*
BLAKE2 reference source code package - optimized C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdint.h>
@ -20,8 +22,8 @@
#include "blake2-config.h"
#if defined (_MSC_VER)
#include <intrin.h>
#ifdef _MSC_VER
#include <intrin.h> /* for _mm_set_epi64x */
#endif
#include <emmintrin.h>
#if defined(HAVE_SSSE3)
@ -37,9 +39,13 @@
#include <x86intrin.h>
#endif
#if defined(HAVE_AVX2)
#include "blake2b-compress-avx2.h"
#else
#include "blake2b-round.h"
#endif
ALIGN( 64 ) static const uint64_t blake2b_IV[8] =
static const uint64_t blake2b_IV[8] =
{
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
@ -47,194 +53,93 @@ ALIGN( 64 ) static const uint64_t blake2b_IV[8] =
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
};
static const uint8_t blake2b_sigma[12][16] =
/* Some helper functions */
static void blake2b_set_lastnode( blake2b_state *S )
{
{ 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 }
};
/* Some helper functions, not necessarily useful */
static inline int blake2b_set_lastnode( blake2b_state *S )
{
S->f[1] = ~0ULL;
return 0;
S->f[1] = (uint64_t)-1;
}
static inline int blake2b_clear_lastnode( blake2b_state *S )
static int blake2b_is_lastblock( const blake2b_state *S )
{
S->f[1] = 0ULL;
return 0;
return S->f[0] != 0;
}
static inline int blake2b_set_lastblock( blake2b_state *S )
static void blake2b_set_lastblock( blake2b_state *S )
{
if( S->last_node ) blake2b_set_lastnode( S );
S->f[0] = ~0ULL;
return 0;
S->f[0] = (uint64_t)-1;
}
static inline int blake2b_clear_lastblock( blake2b_state *S )
static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
{
if( S->last_node ) blake2b_clear_lastnode( S );
S->f[0] = 0ULL;
return 0;
}
static inline int blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
{
#if __x86_64__
// ADD/ADC chain
__uint128_t t = ( ( __uint128_t )S->t[1] << 64 ) | S->t[0];
t += inc;
S->t[0] = ( uint64_t )( t >> 0 );
S->t[1] = ( uint64_t )( t >> 64 );
#else
S->t[0] += inc;
S->t[1] += ( S->t[0] < inc );
#endif
return 0;
}
// Parameter-related functions
static inline int blake2b_param_set_digest_length( blake2b_param *P, const uint8_t digest_length )
{
P->digest_length = digest_length;
return 0;
}
static inline int blake2b_param_set_fanout( blake2b_param *P, const uint8_t fanout )
{
P->fanout = fanout;
return 0;
}
static inline int blake2b_param_set_max_depth( blake2b_param *P, const uint8_t depth )
{
P->depth = depth;
return 0;
}
static inline int blake2b_param_set_leaf_length( blake2b_param *P, const uint32_t leaf_length )
{
P->leaf_length = leaf_length;
return 0;
}
static inline int blake2b_param_set_node_offset( blake2b_param *P, const uint64_t node_offset )
{
P->node_offset = node_offset;
return 0;
}
static inline int blake2b_param_set_node_depth( blake2b_param *P, const uint8_t node_depth )
{
P->node_depth = node_depth;
return 0;
}
static inline int blake2b_param_set_inner_length( blake2b_param *P, const uint8_t inner_length )
{
P->inner_length = inner_length;
return 0;
}
static inline int blake2b_param_set_salt( blake2b_param *P, const uint8_t salt[BLAKE2B_SALTBYTES] )
{
memcpy( P->salt, salt, BLAKE2B_SALTBYTES );
return 0;
}
static inline int blake2b_param_set_personal( blake2b_param *P, const uint8_t personal[BLAKE2B_PERSONALBYTES] )
{
memcpy( P->personal, personal, BLAKE2B_PERSONALBYTES );
return 0;
}
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];
return 0;
}
/* init xors IV with input parameter block */
int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
{
uint8_t *p, *h, *v;
//blake2b_init0( S );
v = ( uint8_t * )( blake2b_IV );
h = ( uint8_t * )( S->h );
p = ( uint8_t * )( P );
size_t i;
/*blake2b_init0( S ); */
const unsigned char * v = ( const unsigned char * )( blake2b_IV );
const unsigned char * p = ( const unsigned char * )( P );
unsigned char * h = ( unsigned char * )( S->h );
/* IV XOR ParamBlock */
memset( S, 0, sizeof( blake2b_state ) );
for( int i = 0; i < BLAKE2B_OUTBYTES; ++i ) h[i] = v[i] ^ p[i];
for( i = 0; i < BLAKE2B_OUTBYTES; ++i ) h[i] = v[i] ^ p[i];
S->outlen = P->digest_length;
return 0;
}
/* Some sort of default parameter block initialization, for sequential blake2b */
int blake2b_init( blake2b_state *S, const uint8_t outlen )
int blake2b_init( blake2b_state *S, size_t outlen )
{
blake2b_param P[1];
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
const blake2b_param P =
{
outlen,
0,
1,
1,
0,
0,
0,
0,
{0},
{0},
{0}
};
return blake2b_init_param( S, &P );
P->digest_length = (uint8_t)outlen;
P->key_length = 0;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, 0 );
store32( &P->xof_length, 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 )
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
{
blake2b_param P[1];
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
if ( ( !keylen ) || keylen > BLAKE2B_KEYBYTES ) return -1;
const blake2b_param P =
{
outlen,
keylen,
1,
1,
0,
0,
0,
0,
{0},
{0},
{0}
};
P->digest_length = (uint8_t)outlen;
P->key_length = (uint8_t)keylen;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, 0 );
store32( &P->xof_length, 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 )
if( blake2b_init_param( S, P ) < 0 )
return 0;
{
@ -247,7 +152,19 @@ int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, c
return 0;
}
static inline int blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
#if defined(HAVE_AVX2)
static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
{
__m256i a = LOADU(&S->h[0]);
__m256i b = LOADU(&S->h[4]);
BLAKE2B_COMPRESS_V1(a, b, block, S->t[0], S->t[1], S->f[0], S->f[1]);
STOREU(&S->h[0], a);
STOREU(&S->h[4], b);
}
#else
static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
{
__m128i row1l, row1h;
__m128i row2l, row2h;
@ -269,22 +186,22 @@ static inline int blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2
const __m128i m6 = LOADU( block + 96 );
const __m128i m7 = LOADU( block + 112 );
#else
const uint64_t m0 = ( ( uint64_t * )block )[ 0];
const uint64_t m1 = ( ( uint64_t * )block )[ 1];
const uint64_t m2 = ( ( uint64_t * )block )[ 2];
const uint64_t m3 = ( ( uint64_t * )block )[ 3];
const uint64_t m4 = ( ( uint64_t * )block )[ 4];
const uint64_t m5 = ( ( uint64_t * )block )[ 5];
const uint64_t m6 = ( ( uint64_t * )block )[ 6];
const uint64_t m7 = ( ( uint64_t * )block )[ 7];
const uint64_t m8 = ( ( uint64_t * )block )[ 8];
const uint64_t m9 = ( ( uint64_t * )block )[ 9];
const uint64_t m10 = ( ( uint64_t * )block )[10];
const uint64_t m11 = ( ( uint64_t * )block )[11];
const uint64_t m12 = ( ( uint64_t * )block )[12];
const uint64_t m13 = ( ( uint64_t * )block )[13];
const uint64_t m14 = ( ( uint64_t * )block )[14];
const uint64_t m15 = ( ( uint64_t * )block )[15];
const uint64_t m0 = load64(block + 0 * sizeof(uint64_t));
const uint64_t m1 = load64(block + 1 * sizeof(uint64_t));
const uint64_t m2 = load64(block + 2 * sizeof(uint64_t));
const uint64_t m3 = load64(block + 3 * sizeof(uint64_t));
const uint64_t m4 = load64(block + 4 * sizeof(uint64_t));
const uint64_t m5 = load64(block + 5 * sizeof(uint64_t));
const uint64_t m6 = load64(block + 6 * sizeof(uint64_t));
const uint64_t m7 = load64(block + 7 * sizeof(uint64_t));
const uint64_t m8 = load64(block + 8 * sizeof(uint64_t));
const uint64_t m9 = load64(block + 9 * sizeof(uint64_t));
const uint64_t m10 = load64(block + 10 * sizeof(uint64_t));
const uint64_t m11 = load64(block + 11 * sizeof(uint64_t));
const uint64_t m12 = load64(block + 12 * sizeof(uint64_t));
const uint64_t m13 = load64(block + 13 * sizeof(uint64_t));
const uint64_t m14 = load64(block + 14 * sizeof(uint64_t));
const uint64_t m15 = load64(block + 15 * sizeof(uint64_t));
#endif
row1l = LOADU( &S->h[0] );
row1h = LOADU( &S->h[2] );
@ -314,70 +231,70 @@ static inline int blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2
row2h = _mm_xor_si128( row4h, row2h );
STOREU( &S->h[4], _mm_xor_si128( LOADU( &S->h[4] ), row2l ) );
STOREU( &S->h[6], _mm_xor_si128( LOADU( &S->h[6] ), row2h ) );
return 0;
}
#endif
int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen )
int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
{
while( inlen > 0 )
const unsigned char * in = (const unsigned char *)pin;
if( inlen > 0 )
{
size_t left = S->buflen;
size_t fill = 2 * BLAKE2B_BLOCKBYTES - left;
size_t fill = BLAKE2B_BLOCKBYTES - left;
if( inlen > fill )
{
memcpy( S->buf + left, in, fill ); // Fill buffer
S->buflen += fill;
S->buflen = 0;
memcpy( S->buf + left, in, fill ); /* Fill buffer */
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;
blake2b_compress( S, S->buf ); /* Compress */
in += fill; inlen -= fill;
while(inlen > BLAKE2B_BLOCKBYTES) {
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress( S, in );
in += BLAKE2B_BLOCKBYTES;
inlen -= BLAKE2B_BLOCKBYTES;
}
}
memcpy( S->buf + S->buflen, in, inlen );
S->buflen += inlen;
}
return 0;
}
int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen )
int blake2b_final( blake2b_state *S, void *out, size_t outlen )
{
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( out == NULL || outlen < S->outlen )
return -1;
if( blake2b_is_lastblock( S ) )
return -1;
blake2b_increment_counter( S, S->buflen );
blake2b_set_lastblock( S );
memset( S->buf + S->buflen, 0, 2 * BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
blake2b_compress( S, S->buf );
memcpy( out, &S->h[0], outlen );
memcpy( out, &S->h[0], S->outlen );
return 0;
}
int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
{
blake2b_state S[1];
/* Verify parameters */
if ( NULL == in ) return -1;
if ( NULL == in && inlen > 0 ) return -1;
if ( NULL == out ) return -1;
if( NULL == key ) keylen = 0;
if( NULL == key && keylen > 0 ) return -1;
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
if( keylen > BLAKE2B_KEYBYTES ) return -1;
if( keylen )
{
@ -388,46 +305,86 @@ int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen
if( blake2b_init( S, outlen ) < 0 ) return -1;
}
blake2b_update( S, ( uint8_t * )in, inlen );
blake2b_update( S, ( const uint8_t * )in, inlen );
blake2b_final( S, out, outlen );
return 0;
}
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
return blake2b(out, outlen, in, inlen, key, keylen);
}
#if defined(SUPERCOP)
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
{
return blake2b( out, in, NULL, BLAKE2B_OUTBYTES, inlen, 0 );
return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );
}
#endif
#if defined(BLAKE2B_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main( int argc, char **argv )
int main( void )
{
uint8_t key[BLAKE2B_KEYBYTES];
uint8_t buf[KAT_LENGTH];
uint8_t buf[BLAKE2_KAT_LENGTH];
size_t i, step;
for( size_t i = 0; i < BLAKE2B_KEYBYTES; ++i )
for( i = 0; i < BLAKE2B_KEYBYTES; ++i )
key[i] = ( uint8_t )i;
for( size_t i = 0; i < KAT_LENGTH; ++i )
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
buf[i] = ( uint8_t )i;
for( size_t i = 0; i < KAT_LENGTH; ++i )
/* Test simple API */
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
{
uint8_t hash[BLAKE2B_OUTBYTES];
blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES );
blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
{
puts( "error" );
return -1;
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
uint8_t hash[BLAKE2B_OUTBYTES];
blake2b_state S;
uint8_t * p = buf;
size_t mlen = i;
int err = 0;
if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
goto fail;
}
while (mlen >= step) {
if ( (err = blake2b_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2b_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
goto fail;
}
if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
goto fail;
}
}
}
puts( "ok" );
return 0;
fail:
puts("error");
return -1;
}
#endif

View file

@ -1,14 +1,16 @@
/*
BLAKE2 reference source code package - optimized C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdio.h>
@ -25,32 +27,48 @@
#define PARALLELISM_DEGREE 4
static inline int blake2bp_init_leaf( blake2b_state *S, uint8_t outlen, uint8_t keylen, uint64_t offset )
/*
blake2b_init_param defaults to setting the expecting output length
from the digest_length parameter block field.
In some cases, however, we do not want this, as the output length
of these instances is given by inner_length instead.
*/
static int blake2bp_init_leaf_param( blake2b_state *S, const blake2b_param *P )
{
int err = blake2b_init_param(S, P);
S->outlen = P->inner_length;
return err;
}
static int blake2bp_init_leaf( blake2b_state *S, size_t outlen, size_t keylen, uint64_t offset )
{
blake2b_param P[1];
P->digest_length = outlen;
P->key_length = keylen;
P->digest_length = (uint8_t)outlen;
P->key_length = (uint8_t)keylen;
P->fanout = PARALLELISM_DEGREE;
P->depth = 2;
P->leaf_length = 0;
P->node_offset = offset;
P->xof_length = 0;
P->node_depth = 0;
P->inner_length = BLAKE2B_OUTBYTES;
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 );
return blake2bp_init_leaf_param( S, P );
}
static inline int blake2bp_init_root( blake2b_state *S, uint8_t outlen, uint8_t keylen )
static int blake2bp_init_root( blake2b_state *S, size_t outlen, size_t keylen )
{
blake2b_param P[1];
P->digest_length = outlen;
P->key_length = keylen;
P->digest_length = (uint8_t)outlen;
P->key_length = (uint8_t)keylen;
P->fanout = PARALLELISM_DEGREE;
P->depth = 2;
P->leaf_length = 0;
P->node_offset = 0;
P->xof_length = 0;
P->node_depth = 1;
P->inner_length = BLAKE2B_OUTBYTES;
memset( P->reserved, 0, sizeof( P->reserved ) );
@ -60,17 +78,19 @@ static inline int blake2bp_init_root( blake2b_state *S, uint8_t outlen, uint8_t
}
int blake2bp_init( blake2bp_state *S, const uint8_t outlen )
int blake2bp_init( blake2bp_state *S, size_t outlen )
{
size_t i;
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
memset( S->buf, 0, sizeof( S->buf ) );
S->buflen = 0;
S->outlen = outlen;
if( blake2bp_init_root( S->R, outlen, 0 ) < 0 )
return -1;
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
if( blake2bp_init_leaf( S->S[i], outlen, 0, i ) < 0 ) return -1;
S->R->last_node = 1;
@ -78,19 +98,22 @@ int blake2bp_init( blake2bp_state *S, const uint8_t outlen )
return 0;
}
int blake2bp_init_key( blake2bp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen )
{
size_t i;
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
if( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
memset( S->buf, 0, sizeof( S->buf ) );
S->buflen = 0;
S->outlen = outlen;
if( blake2bp_init_root( S->R, outlen, keylen ) < 0 )
return -1;
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
if( blake2bp_init_leaf( S->S[i], outlen, keylen, i ) < 0 ) return -1;
S->R->last_node = 1;
@ -100,7 +123,7 @@ int blake2bp_init_key( blake2bp_state *S, const uint8_t outlen, const void *key,
memset( block, 0, BLAKE2B_BLOCKBYTES );
memcpy( block, key, keylen );
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2b_update( S->S[i], block, BLAKE2B_BLOCKBYTES );
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
@ -109,16 +132,18 @@ int blake2bp_init_key( blake2bp_state *S, const uint8_t outlen, const void *key,
}
int blake2bp_update( blake2bp_state *S, const uint8_t *in, uint64_t inlen )
int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
{
const unsigned char * in = (const unsigned char *)pin;
size_t left = S->buflen;
size_t fill = sizeof( S->buf ) - left;
size_t i;
if( left && inlen >= fill )
{
memcpy( S->buf + left, in, fill );
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES );
in += fill;
@ -130,19 +155,19 @@ int blake2bp_update( blake2bp_state *S, const uint8_t *in, uint64_t inlen )
#pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)
#else
for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
#endif
{
#if defined(_OPENMP)
size_t id__ = omp_get_thread_num();
size_t i = omp_get_thread_num();
#endif
uint64_t inlen__ = inlen;
const uint8_t *in__ = ( const uint8_t * )in;
in__ += id__ * BLAKE2B_BLOCKBYTES;
size_t inlen__ = inlen;
const unsigned char *in__ = ( const unsigned char * )in;
in__ += i * BLAKE2B_BLOCKBYTES;
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
{
blake2b_update( S->S[id__], in__, BLAKE2B_BLOCKBYTES );
blake2b_update( S->S[i], in__, BLAKE2B_BLOCKBYTES );
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
}
@ -160,11 +185,16 @@ int blake2bp_update( blake2bp_state *S, const uint8_t *in, uint64_t inlen )
int blake2bp_final( blake2bp_state *S, uint8_t *out, const uint8_t outlen )
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen )
{
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
size_t i;
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
if(out == NULL || outlen < S->outlen) {
return -1;
}
for( i = 0; i < PARALLELISM_DEGREE; ++i )
{
if( S->buflen > i * BLAKE2B_BLOCKBYTES )
{
@ -178,30 +208,34 @@ int blake2bp_final( blake2bp_state *S, uint8_t *out, const uint8_t outlen )
blake2b_final( S->S[i], hash[i], BLAKE2B_OUTBYTES );
}
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2b_update( S->R, hash[i], BLAKE2B_OUTBYTES );
blake2b_final( S->R, out, outlen );
return 0;
return blake2b_final( S->R, out, S->outlen );
}
int blake2bp( uint8_t *out, const void *in, const void *key, uint8_t outlen, uint64_t inlen, uint8_t keylen )
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
{
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
blake2b_state S[PARALLELISM_DEGREE][1];
blake2b_state FS[1];
size_t i;
/* Verify parameters */
if ( NULL == in ) return -1;
if ( NULL == in && inlen > 0 ) return -1;
if ( NULL == out ) return -1;
if ( NULL == key ) keylen = 0;
if( NULL == key && keylen > 0 ) return -1;
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
if( keylen > BLAKE2B_KEYBYTES ) return -1;
for( i = 0; i < PARALLELISM_DEGREE; ++i )
if( blake2bp_init_leaf( S[i], outlen, keylen, i ) < 0 ) return -1;
S[PARALLELISM_DEGREE - 1]->last_node = 1; // mark last node
S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */
if( keylen > 0 )
{
@ -209,7 +243,7 @@ int blake2bp( uint8_t *out, const void *in, const void *key, uint8_t outlen, uin
memset( block, 0, BLAKE2B_BLOCKBYTES );
memcpy( block, key, keylen );
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2b_update( S[i], block, BLAKE2B_BLOCKBYTES );
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
@ -219,78 +253,109 @@ int blake2bp( uint8_t *out, const void *in, const void *key, uint8_t outlen, uin
#pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)
#else
for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
#endif
{
#if defined(_OPENMP)
size_t id__ = omp_get_thread_num();
size_t i = omp_get_thread_num();
#endif
uint64_t inlen__ = inlen;
const uint8_t *in__ = ( const uint8_t * )in;
in__ += id__ * BLAKE2B_BLOCKBYTES;
size_t inlen__ = inlen;
const unsigned char *in__ = ( const unsigned char * )in;
in__ += i * BLAKE2B_BLOCKBYTES;
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
{
blake2b_update( S[id__], in__, BLAKE2B_BLOCKBYTES );
blake2b_update( S[i], in__, BLAKE2B_BLOCKBYTES );
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
}
if( inlen__ > id__ * BLAKE2B_BLOCKBYTES )
if( inlen__ > i * BLAKE2B_BLOCKBYTES )
{
const size_t left = inlen__ - id__ * BLAKE2B_BLOCKBYTES;
const size_t left = inlen__ - i * BLAKE2B_BLOCKBYTES;
const size_t len = left <= BLAKE2B_BLOCKBYTES ? left : BLAKE2B_BLOCKBYTES;
blake2b_update( S[id__], in__, len );
blake2b_update( S[i], in__, len );
}
blake2b_final( S[id__], hash[id__], BLAKE2B_OUTBYTES );
blake2b_final( S[i], hash[i], BLAKE2B_OUTBYTES );
}
if( blake2bp_init_root( FS, outlen, keylen ) < 0 )
return -1;
FS->last_node = 1; // Mark as last node
FS->last_node = 1; /* Mark as last node */
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2b_update( FS, hash[i], BLAKE2B_OUTBYTES );
blake2b_final( FS, out, outlen );
return 0;
return blake2b_final( FS, out, outlen );
}
#if defined(BLAKE2BP_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main( int argc, char **argv )
int main( void )
{
uint8_t key[BLAKE2B_KEYBYTES];
uint8_t buf[KAT_LENGTH];
uint8_t buf[BLAKE2_KAT_LENGTH];
size_t i, step;
for( size_t i = 0; i < BLAKE2B_KEYBYTES; ++i )
for( i = 0; i < BLAKE2B_KEYBYTES; ++i )
key[i] = ( uint8_t )i;
for( size_t i = 0; i < KAT_LENGTH; ++i )
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
buf[i] = ( uint8_t )i;
for( size_t i = 0; i < KAT_LENGTH; ++i )
/* Test simple API */
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
{
uint8_t hash[BLAKE2B_OUTBYTES];
//blake2bp( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES );
blake2bp_state S[1];
blake2bp_init_key( S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES );
blake2bp_update( S, buf, i );
blake2bp_final( S, hash, BLAKE2B_OUTBYTES );
blake2bp( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
if( 0 != memcmp( hash, blake2bp_keyed_kat[i], BLAKE2B_OUTBYTES ) )
{
puts( "error" );
return -1;
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
uint8_t hash[BLAKE2B_OUTBYTES];
blake2bp_state S;
uint8_t * p = buf;
size_t mlen = i;
int err = 0;
if( (err = blake2bp_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
goto fail;
}
while (mlen >= step) {
if ( (err = blake2bp_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2bp_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2bp_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
goto fail;
}
if (0 != memcmp(hash, blake2bp_keyed_kat[i], BLAKE2B_OUTBYTES)) {
goto fail;
}
}
}
puts( "ok" );
return 0;
fail:
puts("error");
return -1;
}
#endif

View file

@ -1,18 +1,19 @@
/*
BLAKE2 reference source code package - optimized C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#pragma once
#ifndef __BLAKE2S_LOAD_SSE2_H__
#define __BLAKE2S_LOAD_SSE2_H__
#ifndef BLAKE2S_LOAD_SSE2_H
#define BLAKE2S_LOAD_SSE2_H
#define LOAD_MSG_0_1(buf) buf = _mm_set_epi32(m6,m4,m2,m0)
#define LOAD_MSG_0_2(buf) buf = _mm_set_epi32(m7,m5,m3,m1)

View file

@ -1,18 +1,19 @@
/*
BLAKE2 reference source code package - optimized C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#pragma once
#ifndef __BLAKE2S_LOAD_SSE41_H__
#define __BLAKE2S_LOAD_SSE41_H__
#ifndef BLAKE2S_LOAD_SSE41_H
#define BLAKE2S_LOAD_SSE41_H
#define LOAD_MSG_0_1(buf) \
buf = TOI(_mm_shuffle_ps(TOF(m0), TOF(m1), _MM_SHUFFLE(2,0,2,0)));
@ -226,4 +227,3 @@ t2 = _mm_blend_epi16(t0,t1,0x0F); \
buf = _mm_shuffle_epi32(t2,_MM_SHUFFLE(0,1,2,3));
#endif

View file

@ -1,31 +1,34 @@
/*
BLAKE2 reference source code package - optimized C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#pragma once
#ifndef __BLAKE2S_LOAD_XOP_H__
#define __BLAKE2S_LOAD_XOP_H__
#ifndef BLAKE2S_LOAD_XOP_H
#define BLAKE2S_LOAD_XOP_H
#define TOB(x) ((x)*4*0x01010101 + 0x03020100) // ..or not TOB
#define TOB(x) ((x)*4*0x01010101 + 0x03020100) /* ..or not TOB */
#if 0
/* Basic VPPERM emulation, for testing purposes */
/*static __m128i _mm_perm_epi8(const __m128i src1, const __m128i src2, const __m128i sel)
static __m128i _mm_perm_epi8(const __m128i src1, const __m128i src2, const __m128i sel)
{
const __m128i sixteen = _mm_set1_epi8(16);
const __m128i t0 = _mm_shuffle_epi8(src1, sel);
const __m128i s1 = _mm_shuffle_epi8(src2, _mm_sub_epi8(sel, sixteen));
const __m128i mask = _mm_or_si128(_mm_cmpeq_epi8(sel, sixteen),
_mm_cmpgt_epi8(sel, sixteen)); // (>=16) = 0xff : 00
_mm_cmpgt_epi8(sel, sixteen)); /* (>=16) = 0xff : 00 */
return _mm_blendv_epi8(t0, s1, mask);
}*/
}
#endif
#define LOAD_MSG_0_1(buf) \
buf = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(6),TOB(4),TOB(2),TOB(0)) );
@ -166,7 +169,7 @@ buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(1),TOB(7)) );
#define LOAD_MSG_8_3(buf) \
t0 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(6),TOB(1),TOB(0),TOB(0)) ); \
buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(5),TOB(4)) ); \
#define LOAD_MSG_8_4(buf) \
buf = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(5),TOB(4),TOB(7),TOB(2)) );
@ -186,4 +189,3 @@ t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(0),TOB(0),TOB(0),TOB(7)) ); \
buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(4),TOB(6),TOB(0)) );
#endif

View file

@ -1,23 +1,21 @@
/*
BLAKE2 reference source code package - optimized C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#pragma once
#ifndef __BLAKE2S_ROUND_H__
#define __BLAKE2S_ROUND_H__
#ifndef BLAKE2S_ROUND_H
#define BLAKE2S_ROUND_H
#define LOAD(p) _mm_load_si128( (__m128i *)(p) )
#define STORE(p,r) _mm_store_si128((__m128i *)(p), r)
#define LOADU(p) _mm_loadu_si128( (__m128i *)(p) )
#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))
@ -34,7 +32,7 @@
: (16==-(c)) ? _mm_shuffle_epi8(r,r16) \
: _mm_xor_si128(_mm_srli_epi32( (r), -(c) ),_mm_slli_epi32( (r), 32-(-(c)) )) )
#else
#define _mm_roti_epi32(r, c) _mm_xor_si128(_mm_srli_epi32( (r), -(c) ),_mm_slli_epi32( (r), 32-(-c) ))
#define _mm_roti_epi32(r, c) _mm_xor_si128(_mm_srli_epi32( (r), -(c) ),_mm_slli_epi32( (r), 32-(-(c)) ))
#endif
#else
/* ... */
@ -86,6 +84,5 @@
LOAD_MSG_ ##r ##_4(buf4); \
G2(row1,row2,row3,row4,buf4); \
UNDIAGONALIZE(row1,row2,row3,row4); \
#endif
#endif

View file

@ -1,14 +1,16 @@
/*
BLAKE2 reference source code package - optimized C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdint.h>
@ -37,192 +39,104 @@
#include "blake2s-round.h"
ALIGN( 64 ) static const uint32_t blake2s_IV[8] =
static const uint32_t blake2s_IV[8] =
{
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
};
static const uint8_t blake2s_sigma[10][16] =
/* Some helper functions */
static void blake2s_set_lastnode( blake2s_state *S )
{
{ 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 } ,
};
/* Some helper functions, not necessarily useful */
static inline int blake2s_set_lastnode( blake2s_state *S )
{
S->f[1] = ~0U;
return 0;
S->f[1] = (uint32_t)-1;
}
static inline int blake2s_clear_lastnode( blake2s_state *S )
static int blake2s_is_lastblock( const blake2s_state *S )
{
S->f[1] = 0U;
return 0;
return S->f[0] != 0;
}
static inline int blake2s_set_lastblock( blake2s_state *S )
static void blake2s_set_lastblock( blake2s_state *S )
{
if( S->last_node ) blake2s_set_lastnode( S );
S->f[0] = ~0U;
return 0;
S->f[0] = (uint32_t)-1;
}
static inline int blake2s_clear_lastblock( blake2s_state *S )
{
if( S->last_node ) blake2s_clear_lastnode( S );
S->f[0] = 0U;
return 0;
}
static inline int blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
static void blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
{
uint64_t t = ( ( uint64_t )S->t[1] << 32 ) | S->t[0];
t += inc;
S->t[0] = ( uint32_t )( t >> 0 );
S->t[1] = ( uint32_t )( t >> 32 );
return 0;
}
// Parameter-related functions
static inline int blake2s_param_set_digest_length( blake2s_param *P, const uint8_t digest_length )
{
P->digest_length = digest_length;
return 0;
}
static inline int blake2s_param_set_fanout( blake2s_param *P, const uint8_t fanout )
{
P->fanout = fanout;
return 0;
}
static inline int blake2s_param_set_max_depth( blake2s_param *P, const uint8_t depth )
{
P->depth = depth;
return 0;
}
static inline int blake2s_param_set_leaf_length( blake2s_param *P, const uint32_t leaf_length )
{
P->leaf_length = leaf_length;
return 0;
}
static inline int blake2s_param_set_node_offset( blake2s_param *P, const uint64_t node_offset )
{
store48( P->node_offset, node_offset );
return 0;
}
static inline int blake2s_param_set_node_depth( blake2s_param *P, const uint8_t node_depth )
{
P->node_depth = node_depth;
return 0;
}
static inline int blake2s_param_set_inner_length( blake2s_param *P, const uint8_t inner_length )
{
P->inner_length = inner_length;
return 0;
}
static inline int blake2s_param_set_salt( blake2s_param *P, const uint8_t salt[BLAKE2S_SALTBYTES] )
{
memcpy( P->salt, salt, BLAKE2S_SALTBYTES );
return 0;
}
static inline int blake2s_param_set_personal( blake2s_param *P, const uint8_t personal[BLAKE2S_PERSONALBYTES] )
{
memcpy( P->personal, personal, BLAKE2S_PERSONALBYTES );
return 0;
}
static inline int blake2s_init0( blake2s_state *S )
{
memset( S, 0, sizeof( blake2s_state ) );
for( int i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];
return 0;
}
/* init2 xors IV with input parameter block */
int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
{
uint8_t *p, *h, *v;
//blake2s_init0( S );
v = ( uint8_t * )( blake2s_IV );
h = ( uint8_t * )( S->h );
p = ( uint8_t * )( P );
size_t i;
/*blake2s_init0( S ); */
const uint8_t * v = ( const uint8_t * )( blake2s_IV );
const uint8_t * p = ( const uint8_t * )( P );
uint8_t * h = ( uint8_t * )( S->h );
/* IV XOR ParamBlock */
memset( S, 0, sizeof( blake2s_state ) );
for( int i = 0; i < BLAKE2S_OUTBYTES; ++i ) h[i] = v[i] ^ p[i];
for( i = 0; i < BLAKE2S_OUTBYTES; ++i ) h[i] = v[i] ^ p[i];
S->outlen = P->digest_length;
return 0;
}
/* Some sort of default parameter block initialization, for sequential blake2s */
int blake2s_init( blake2s_state *S, const uint8_t outlen )
int blake2s_init( blake2s_state *S, size_t outlen )
{
blake2s_param P[1];
/* Move interval verification here? */
if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
const blake2s_param P =
{
outlen,
0,
1,
1,
0,
{0},
0,
0,
{0},
{0}
};
return blake2s_init_param( S, &P );
P->digest_length = (uint8_t)outlen;
P->key_length = 0;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, 0 );
store16( &P->xof_length, 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 blake2s_init_param( S, P );
}
int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen )
{
blake2s_param P[1];
/* Move interval verification here? */
if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
if ( ( !key ) || ( !keylen ) || keylen > BLAKE2S_KEYBYTES ) return -1;
const blake2s_param P =
{
outlen,
keylen,
1,
1,
0,
{0},
0,
0,
{0},
{0}
};
P->digest_length = (uint8_t)outlen;
P->key_length = (uint8_t)keylen;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, 0 );
store16( &P->xof_length, 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( blake2s_init_param( S, &P ) < 0 )
if( blake2s_init_param( S, P ) < 0 )
return -1;
{
@ -236,7 +150,7 @@ int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, c
}
static inline int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCKBYTES] )
static void blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCKBYTES] )
{
__m128i row1, row2, row3, row4;
__m128i buf1, buf2, buf3, buf4;
@ -257,27 +171,27 @@ static inline int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2
const __m128i m2 = LOADU( block + 32 );
const __m128i m3 = LOADU( block + 48 );
#else
const uint32_t m0 = ( ( uint32_t * )block )[ 0];
const uint32_t m1 = ( ( uint32_t * )block )[ 1];
const uint32_t m2 = ( ( uint32_t * )block )[ 2];
const uint32_t m3 = ( ( uint32_t * )block )[ 3];
const uint32_t m4 = ( ( uint32_t * )block )[ 4];
const uint32_t m5 = ( ( uint32_t * )block )[ 5];
const uint32_t m6 = ( ( uint32_t * )block )[ 6];
const uint32_t m7 = ( ( uint32_t * )block )[ 7];
const uint32_t m8 = ( ( uint32_t * )block )[ 8];
const uint32_t m9 = ( ( uint32_t * )block )[ 9];
const uint32_t m10 = ( ( uint32_t * )block )[10];
const uint32_t m11 = ( ( uint32_t * )block )[11];
const uint32_t m12 = ( ( uint32_t * )block )[12];
const uint32_t m13 = ( ( uint32_t * )block )[13];
const uint32_t m14 = ( ( uint32_t * )block )[14];
const uint32_t m15 = ( ( uint32_t * )block )[15];
const uint32_t m0 = load32(block + 0 * sizeof(uint32_t));
const uint32_t m1 = load32(block + 1 * sizeof(uint32_t));
const uint32_t m2 = load32(block + 2 * sizeof(uint32_t));
const uint32_t m3 = load32(block + 3 * sizeof(uint32_t));
const uint32_t m4 = load32(block + 4 * sizeof(uint32_t));
const uint32_t m5 = load32(block + 5 * sizeof(uint32_t));
const uint32_t m6 = load32(block + 6 * sizeof(uint32_t));
const uint32_t m7 = load32(block + 7 * sizeof(uint32_t));
const uint32_t m8 = load32(block + 8 * sizeof(uint32_t));
const uint32_t m9 = load32(block + 9 * sizeof(uint32_t));
const uint32_t m10 = load32(block + 10 * sizeof(uint32_t));
const uint32_t m11 = load32(block + 11 * sizeof(uint32_t));
const uint32_t m12 = load32(block + 12 * sizeof(uint32_t));
const uint32_t m13 = load32(block + 13 * sizeof(uint32_t));
const uint32_t m14 = load32(block + 14 * sizeof(uint32_t));
const uint32_t m15 = load32(block + 15 * sizeof(uint32_t));
#endif
row1 = ff0 = LOADU( &S->h[0] );
row2 = ff1 = LOADU( &S->h[4] );
row3 = _mm_setr_epi32( 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A );
row4 = _mm_xor_si128( _mm_setr_epi32( 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 ), LOADU( &S->t[0] ) );
row3 = _mm_loadu_si128( (__m128i const *)&blake2s_IV[0] );
row4 = _mm_xor_si128( _mm_loadu_si128( (__m128i const *)&blake2s_IV[4] ), LOADU( &S->t[0] ) );
ROUND( 0 );
ROUND( 1 );
ROUND( 2 );
@ -290,76 +204,74 @@ static inline int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2
ROUND( 9 );
STOREU( &S->h[0], _mm_xor_si128( ff0, _mm_xor_si128( row1, row3 ) ) );
STOREU( &S->h[4], _mm_xor_si128( ff1, _mm_xor_si128( row2, row4 ) ) );
return 0;
}
/* inlen now in bytes */
int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen )
int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
{
while( inlen > 0 )
const unsigned char * in = (const unsigned char *)pin;
if( inlen > 0 )
{
size_t left = S->buflen;
size_t fill = 2 * BLAKE2S_BLOCKBYTES - left;
size_t fill = BLAKE2S_BLOCKBYTES - left;
if( inlen > fill )
{
memcpy( S->buf + left, in, fill ); // Fill buffer
S->buflen += fill;
S->buflen = 0;
memcpy( S->buf + left, in, fill ); /* Fill buffer */
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
blake2s_compress( S, S->buf ); // Compress
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left
S->buflen -= BLAKE2S_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;
blake2s_compress( S, S->buf ); /* Compress */
in += fill; inlen -= fill;
while(inlen > BLAKE2S_BLOCKBYTES) {
blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
blake2s_compress( S, in );
in += BLAKE2S_BLOCKBYTES;
inlen -= BLAKE2S_BLOCKBYTES;
}
}
memcpy( S->buf + S->buflen, in, inlen );
S->buflen += inlen;
}
return 0;
}
/* Is this correct? */
int blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen )
int blake2s_final( blake2s_state *S, void *out, size_t outlen )
{
uint8_t buffer[BLAKE2S_OUTBYTES];
uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
size_t i;
if( S->buflen > BLAKE2S_BLOCKBYTES )
{
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
blake2s_compress( S, S->buf );
S->buflen -= BLAKE2S_BLOCKBYTES;
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen );
}
if( out == NULL || outlen < S->outlen )
return -1;
blake2s_increment_counter( S, ( uint32_t )S->buflen );
if( blake2s_is_lastblock( S ) )
return -1;
blake2s_increment_counter( S, (uint32_t)S->buflen );
blake2s_set_lastblock( S );
memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
memset( S->buf + S->buflen, 0, BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
blake2s_compress( S, S->buf );
for( int i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
store32( buffer + sizeof( S->h[i] ) * i, S->h[i] );
memcpy( out, buffer, outlen );
memcpy( out, buffer, S->outlen );
secure_zero_memory( buffer, sizeof(buffer) );
return 0;
}
/* inlen, at least, should be uint64_t. Others can be size_t. */
int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
{
blake2s_state S[1];
/* Verify parameters */
if ( NULL == in ) return -1;
if ( NULL == in && inlen > 0 ) return -1;
if ( NULL == out ) return -1;
if ( NULL == key ) keylen = 0; /* Fail here instead if keylen != 0 and key == NULL? */
if ( NULL == key && keylen > 0) return -1;
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
if( keylen > BLAKE2S_KEYBYTES ) return -1;
if( keylen > 0 )
{
@ -370,7 +282,7 @@ int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen
if( blake2s_init( S, outlen ) < 0 ) return -1;
}
blake2s_update( S, ( uint8_t * )in, inlen );
blake2s_update( S, ( const uint8_t * )in, inlen );
blake2s_final( S, out, outlen );
return 0;
}
@ -378,39 +290,74 @@ int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen
#if defined(SUPERCOP)
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
{
return blake2s( out, in, NULL, BLAKE2S_OUTBYTES, inlen, 0 );
return blake2s( out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0 );
}
#endif
#if defined(BLAKE2S_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main( int argc, char **argv )
int main( void )
{
uint8_t key[BLAKE2S_KEYBYTES];
uint8_t buf[KAT_LENGTH];
uint8_t buf[BLAKE2_KAT_LENGTH];
size_t i, step;
for( size_t i = 0; i < BLAKE2S_KEYBYTES; ++i )
for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
key[i] = ( uint8_t )i;
for( size_t i = 0; i < KAT_LENGTH; ++i )
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
buf[i] = ( uint8_t )i;
for( size_t i = 0; i < KAT_LENGTH; ++i )
/* Test simple API */
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
{
uint8_t hash[BLAKE2S_OUTBYTES];
blake2s( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
if( blake2s( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES ) < 0 ||
0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
{
puts( "error" );
return -1;
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
uint8_t hash[BLAKE2S_OUTBYTES];
blake2s_state S;
uint8_t * p = buf;
size_t mlen = i;
int err = 0;
if( (err = blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
goto fail;
}
while (mlen >= step) {
if ( (err = blake2s_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2s_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
goto fail;
}
if (0 != memcmp(hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES)) {
goto fail;
}
}
}
puts( "ok" );
return 0;
fail:
puts("error");
return -1;
}
#endif

View file

@ -1,14 +1,16 @@
/*
BLAKE2 reference source code package - optimized C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.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/>.
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdlib.h>
@ -24,31 +26,47 @@
#define PARALLELISM_DEGREE 8
static inline int blake2sp_init_leaf( blake2s_state *S, uint8_t outlen, uint8_t keylen, uint64_t offset )
/*
blake2sp_init_param defaults to setting the expecting output length
from the digest_length parameter block field.
In some cases, however, we do not want this, as the output length
of these instances is given by inner_length instead.
*/
static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P )
{
int err = blake2s_init_param(S, P);
S->outlen = P->inner_length;
return err;
}
static int blake2sp_init_leaf( blake2s_state *S, size_t outlen, size_t keylen, uint64_t offset )
{
blake2s_param P[1];
P->digest_length = outlen;
P->key_length = keylen;
P->digest_length = (uint8_t)outlen;
P->key_length = (uint8_t)keylen;
P->fanout = PARALLELISM_DEGREE;
P->depth = 2;
P->leaf_length = 0;
store48( P->node_offset, offset );
P->node_offset = offset;
P->xof_length = 0;
P->node_depth = 0;
P->inner_length = BLAKE2S_OUTBYTES;
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
return blake2s_init_param( S, P );
return blake2sp_init_leaf_param( S, P );
}
static inline int blake2sp_init_root( blake2s_state *S, uint8_t outlen, uint8_t keylen )
static int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen )
{
blake2s_param P[1];
P->digest_length = outlen;
P->key_length = keylen;
P->digest_length = (uint8_t)outlen;
P->key_length = (uint8_t)keylen;
P->fanout = PARALLELISM_DEGREE;
P->depth = 2;
P->leaf_length = 0;
store48( P->node_offset, 0ULL );
P->node_offset = 0;
P->xof_length = 0;
P->node_depth = 1;
P->inner_length = BLAKE2S_OUTBYTES;
memset( P->salt, 0, sizeof( P->salt ) );
@ -57,17 +75,20 @@ static inline int blake2sp_init_root( blake2s_state *S, uint8_t outlen, uint8_t
}
int blake2sp_init( blake2sp_state *S, const uint8_t outlen )
int blake2sp_init( blake2sp_state *S, size_t outlen )
{
size_t i;
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
memset( S->buf, 0, sizeof( S->buf ) );
S->buflen = 0;
S->outlen = outlen;
if( blake2sp_init_root( S->R, outlen, 0 ) < 0 )
return -1;
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
if( blake2sp_init_leaf( S->S[i], outlen, 0, i ) < 0 ) return -1;
S->R->last_node = 1;
@ -75,19 +96,22 @@ int blake2sp_init( blake2sp_state *S, const uint8_t outlen )
return 0;
}
int blake2sp_init_key( blake2sp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
{
size_t i;
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
memset( S->buf, 0, sizeof( S->buf ) );
S->buflen = 0;
S->outlen = outlen;
if( blake2sp_init_root( S->R, outlen, keylen ) < 0 )
return -1;
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
if( blake2sp_init_leaf( S->S[i], outlen, keylen, i ) < 0 ) return -1;
S->R->last_node = 1;
@ -97,7 +121,7 @@ int blake2sp_init_key( blake2sp_state *S, const uint8_t outlen, const void *key,
memset( block, 0, BLAKE2S_BLOCKBYTES );
memcpy( block, key, keylen );
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
@ -106,16 +130,18 @@ int blake2sp_init_key( blake2sp_state *S, const uint8_t outlen, const void *key,
}
int blake2sp_update( blake2sp_state *S, const uint8_t *in, uint64_t inlen )
int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
{
const unsigned char * in = (const unsigned char *)pin;
size_t left = S->buflen;
size_t fill = sizeof( S->buf ) - left;
size_t i;
if( left && inlen >= fill )
{
memcpy( S->buf + left, in, fill );
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
in += fill;
@ -127,19 +153,19 @@ int blake2sp_update( blake2sp_state *S, const uint8_t *in, uint64_t inlen )
#pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)
#else
for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
#endif
{
#if defined(_OPENMP)
size_t id__ = omp_get_thread_num();
size_t i = omp_get_thread_num();
#endif
uint64_t inlen__ = inlen;
const uint8_t *in__ = ( const uint8_t * )in;
in__ += id__ * BLAKE2S_BLOCKBYTES;
size_t inlen__ = inlen;
const unsigned char *in__ = ( const unsigned char * )in;
in__ += i * BLAKE2S_BLOCKBYTES;
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
{
blake2s_update( S->S[id__], in__, BLAKE2S_BLOCKBYTES );
blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
}
@ -156,11 +182,16 @@ int blake2sp_update( blake2sp_state *S, const uint8_t *in, uint64_t inlen )
}
int blake2sp_final( blake2sp_state *S, uint8_t *out, const uint8_t outlen )
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
{
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
size_t i;
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
if(out == NULL || outlen < S->outlen) {
return -1;
}
for( i = 0; i < PARALLELISM_DEGREE; ++i )
{
if( S->buflen > i * BLAKE2S_BLOCKBYTES )
{
@ -174,31 +205,35 @@ int blake2sp_final( blake2sp_state *S, uint8_t *out, const uint8_t outlen )
blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
}
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
blake2s_final( S->R, out, outlen );
return 0;
return blake2s_final( S->R, out, S->outlen );
}
int blake2sp( uint8_t *out, const void *in, const void *key, uint8_t outlen, uint64_t inlen, uint8_t keylen )
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
{
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
blake2s_state S[PARALLELISM_DEGREE][1];
blake2s_state FS[1];
size_t i;
/* Verify parameters */
if ( NULL == in ) return -1;
if ( NULL == in && inlen > 0 ) return -1;
if ( NULL == out ) return -1;
if ( NULL == key ) keylen = 0;
if ( NULL == key && keylen > 0) return -1;
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
if( keylen > BLAKE2S_KEYBYTES ) return -1;
for( i = 0; i < PARALLELISM_DEGREE; ++i )
if( blake2sp_init_leaf( S[i], outlen, keylen, i ) < 0 ) return -1;
S[PARALLELISM_DEGREE - 1]->last_node = 1; // mark last node
S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */
if( keylen > 0 )
{
@ -206,7 +241,7 @@ int blake2sp( uint8_t *out, const void *in, const void *key, uint8_t outlen, uin
memset( block, 0, BLAKE2S_BLOCKBYTES );
memcpy( block, key, keylen );
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
@ -216,31 +251,31 @@ int blake2sp( uint8_t *out, const void *in, const void *key, uint8_t outlen, uin
#pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)
#else
for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
#endif
{
#if defined(_OPENMP)
size_t id__ = omp_get_thread_num();
size_t i = omp_get_thread_num();
#endif
uint64_t inlen__ = inlen;
const uint8_t *in__ = ( const uint8_t * )in;
in__ += id__ * BLAKE2S_BLOCKBYTES;
size_t inlen__ = inlen;
const unsigned char *in__ = ( const unsigned char * )in;
in__ += i * BLAKE2S_BLOCKBYTES;
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
{
blake2s_update( S[id__], in__, BLAKE2S_BLOCKBYTES );
blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
}
if( inlen__ > id__ * BLAKE2S_BLOCKBYTES )
if( inlen__ > i * BLAKE2S_BLOCKBYTES )
{
const size_t left = inlen__ - id__ * BLAKE2S_BLOCKBYTES;
const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;
const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
blake2s_update( S[id__], in__, len );
blake2s_update( S[i], in__, len );
}
blake2s_final( S[id__], hash[id__], BLAKE2S_OUTBYTES );
blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );
}
if( blake2sp_init_root( FS, outlen, keylen ) < 0 )
@ -248,44 +283,76 @@ int blake2sp( uint8_t *out, const void *in, const void *key, uint8_t outlen, uin
FS->last_node = 1;
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
blake2s_final( FS, out, outlen );
return 0;
return blake2s_final( FS, out, outlen );
}
#if defined(BLAKE2SP_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main( int argc, char **argv )
int main( void )
{
uint8_t key[BLAKE2S_KEYBYTES];
uint8_t buf[KAT_LENGTH];
uint8_t buf[BLAKE2_KAT_LENGTH];
size_t i, step;
for( size_t i = 0; i < BLAKE2S_KEYBYTES; ++i )
for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
key[i] = ( uint8_t )i;
for( size_t i = 0; i < KAT_LENGTH; ++i )
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
buf[i] = ( uint8_t )i;
for( size_t i = 0; i < KAT_LENGTH; ++i )
/* Test simple API */
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
{
uint8_t hash[BLAKE2S_OUTBYTES];
blake2sp( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES );
blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )
{
puts( "error" );
return -1;
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
uint8_t hash[BLAKE2S_OUTBYTES];
blake2sp_state S;
uint8_t * p = buf;
size_t mlen = i;
int err = 0;
if( (err = blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
goto fail;
}
while (mlen >= step) {
if ( (err = blake2sp_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2sp_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
goto fail;
}
if (0 != memcmp(hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES)) {
goto fail;
}
}
}
puts( "ok" );
return 0;
fail:
puts("error");
return -1;
}
#endif

241
blake2/blake2xb.c Normal file
View file

@ -0,0 +1,241 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2016, JP Aumasson <jeanphilippe.aumasson@gmail.com>.
Copyright 2016, Samuel Neves <sneves@dei.uc.pt>.
You may use this under the terms of the CC0, the OpenSSL Licence, or
the Apache Public License 2.0, at your option. The terms of these
licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "blake2.h"
#include "blake2-impl.h"
int blake2xb_init( blake2xb_state *S, const size_t outlen ) {
return blake2xb_init_key(S, outlen, NULL, 0);
}
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen)
{
if ( outlen == 0 || outlen > 0xFFFFFFFFUL ) {
return -1;
}
if (NULL != key && keylen > BLAKE2B_KEYBYTES) {
return -1;
}
if (NULL == key && keylen > 0) {
return -1;
}
/* Initialize parameter block */
S->P->digest_length = BLAKE2B_OUTBYTES;
S->P->key_length = keylen;
S->P->fanout = 1;
S->P->depth = 1;
store32( &S->P->leaf_length, 0 );
store32( &S->P->node_offset, 0 );
store32( &S->P->xof_length, outlen );
S->P->node_depth = 0;
S->P->inner_length = 0;
memset( S->P->reserved, 0, sizeof( S->P->reserved ) );
memset( S->P->salt, 0, sizeof( S->P->salt ) );
memset( S->P->personal, 0, sizeof( S->P->personal ) );
if( blake2b_init_param( S->S, S->P ) < 0 ) {
return -1;
}
if (keylen > 0) {
uint8_t block[BLAKE2B_BLOCKBYTES];
memset(block, 0, BLAKE2B_BLOCKBYTES);
memcpy(block, key, keylen);
blake2b_update(S->S, block, BLAKE2B_BLOCKBYTES);
secure_zero_memory(block, BLAKE2B_BLOCKBYTES);
}
return 0;
}
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ) {
return blake2b_update( S->S, in, inlen );
}
int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
blake2b_state C[1];
blake2b_param P[1];
uint32_t xof_length = load32(&S->P->xof_length);
uint8_t root[BLAKE2B_BLOCKBYTES];
size_t i;
if (NULL == out) {
return -1;
}
/* outlen must match the output size defined in xof_length, */
/* unless it was -1, in which case anything goes except 0. */
if(xof_length == 0xFFFFFFFFUL) {
if(outlen == 0) {
return -1;
}
} else {
if(outlen != xof_length) {
return -1;
}
}
/* Finalize the root hash */
if (blake2b_final(S->S, root, BLAKE2B_OUTBYTES) < 0) {
return -1;
}
/* Set common block structure values */
/* Copy values from parent instance, and only change the ones below */
memcpy(P, S->P, sizeof(blake2b_param));
P->key_length = 0;
P->fanout = 0;
P->depth = 0;
store32(&P->leaf_length, BLAKE2B_OUTBYTES);
P->inner_length = BLAKE2B_OUTBYTES;
P->node_depth = 0;
for (i = 0; outlen > 0; ++i) {
const size_t block_size = (outlen < BLAKE2B_OUTBYTES) ? outlen : BLAKE2B_OUTBYTES;
/* Initialize state */
P->digest_length = block_size;
store32(&P->node_offset, i);
blake2b_init_param(C, P);
/* Process key if needed */
blake2b_update(C, root, BLAKE2B_OUTBYTES);
if (blake2b_final(C, (uint8_t *)out + i * BLAKE2B_OUTBYTES, block_size) < 0 ) {
return -1;
}
outlen -= block_size;
}
secure_zero_memory(root, sizeof(root));
secure_zero_memory(P, sizeof(P));
secure_zero_memory(C, sizeof(C));
/* Put blake2xb in an invalid state? cf. blake2s_is_lastblock */
return 0;
}
int blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
{
blake2xb_state S[1];
/* Verify parameters */
if (NULL == in && inlen > 0)
return -1;
if (NULL == out)
return -1;
if (NULL == key && keylen > 0)
return -1;
if (keylen > BLAKE2B_KEYBYTES)
return -1;
if (outlen == 0)
return -1;
/* Initialize the root block structure */
if (blake2xb_init_key(S, outlen, key, keylen) < 0) {
return -1;
}
/* Absorb the input message */
blake2xb_update(S, in, inlen);
/* Compute the root node of the tree and the final hash using the counter construction */
return blake2xb_final(S, out, outlen);
}
#if defined(BLAKE2XB_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main( void )
{
uint8_t key[BLAKE2B_KEYBYTES];
uint8_t buf[BLAKE2_KAT_LENGTH];
size_t i, step, outlen;
for( i = 0; i < BLAKE2B_KEYBYTES; ++i ) {
key[i] = ( uint8_t )i;
}
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) {
buf[i] = ( uint8_t )i;
}
/* Testing length of ouputs rather than inputs */
/* (Test of input lengths mostly covered by blake2s tests) */
/* Test simple API */
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
{
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
if( blake2xb( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2B_KEYBYTES ) < 0 ) {
goto fail;
}
if( 0 != memcmp( hash, blake2xb_keyed_kat[outlen-1], outlen ) )
{
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
for (outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen) {
uint8_t hash[BLAKE2_KAT_LENGTH];
blake2xb_state S;
uint8_t * p = buf;
size_t mlen = BLAKE2_KAT_LENGTH;
int err = 0;
if( (err = blake2xb_init_key(&S, outlen, key, BLAKE2B_KEYBYTES)) < 0 ) {
goto fail;
}
while (mlen >= step) {
if ( (err = blake2xb_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2xb_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2xb_final(&S, hash, outlen)) < 0) {
goto fail;
}
if (0 != memcmp(hash, blake2xb_keyed_kat[outlen-1], outlen)) {
goto fail;
}
}
}
puts( "ok" );
return 0;
fail:
puts("error");
return -1;
}
#endif

239
blake2/blake2xs.c Normal file
View file

@ -0,0 +1,239 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2016, JP Aumasson <jeanphilippe.aumasson@gmail.com>.
Copyright 2016, Samuel Neves <sneves@dei.uc.pt>.
You may use this under the terms of the CC0, the OpenSSL Licence, or
the Apache Public License 2.0, at your option. The terms of these
licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "blake2.h"
#include "blake2-impl.h"
int blake2xs_init( blake2xs_state *S, const size_t outlen ) {
return blake2xs_init_key(S, outlen, NULL, 0);
}
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen )
{
if ( outlen == 0 || outlen > 0xFFFFUL ) {
return -1;
}
if (NULL != key && keylen > BLAKE2B_KEYBYTES) {
return -1;
}
if (NULL == key && keylen > 0) {
return -1;
}
/* Initialize parameter block */
S->P->digest_length = BLAKE2S_OUTBYTES;
S->P->key_length = keylen;
S->P->fanout = 1;
S->P->depth = 1;
store32( &S->P->leaf_length, 0 );
store32( &S->P->node_offset, 0 );
store16( &S->P->xof_length, outlen );
S->P->node_depth = 0;
S->P->inner_length = 0;
memset( S->P->salt, 0, sizeof( S->P->salt ) );
memset( S->P->personal, 0, sizeof( S->P->personal ) );
if( blake2s_init_param( S->S, S->P ) < 0 ) {
return -1;
}
if (keylen > 0) {
uint8_t block[BLAKE2S_BLOCKBYTES];
memset(block, 0, BLAKE2S_BLOCKBYTES);
memcpy(block, key, keylen);
blake2s_update(S->S, block, BLAKE2S_BLOCKBYTES);
secure_zero_memory(block, BLAKE2S_BLOCKBYTES);
}
return 0;
}
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ) {
return blake2s_update( S->S, in, inlen );
}
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
blake2s_state C[1];
blake2s_param P[1];
uint16_t xof_length = load16(&S->P->xof_length);
uint8_t root[BLAKE2S_BLOCKBYTES];
size_t i;
if (NULL == out) {
return -1;
}
/* outlen must match the output size defined in xof_length, */
/* unless it was -1, in which case anything goes except 0. */
if(xof_length == 0xFFFFUL) {
if(outlen == 0) {
return -1;
}
} else {
if(outlen != xof_length) {
return -1;
}
}
/* Finalize the root hash */
if (blake2s_final(S->S, root, BLAKE2S_OUTBYTES) < 0) {
return -1;
}
/* Set common block structure values */
/* Copy values from parent instance, and only change the ones below */
memcpy(P, S->P, sizeof(blake2s_param));
P->key_length = 0;
P->fanout = 0;
P->depth = 0;
store32(&P->leaf_length, BLAKE2S_OUTBYTES);
P->inner_length = BLAKE2S_OUTBYTES;
P->node_depth = 0;
for (i = 0; outlen > 0; ++i) {
const size_t block_size = (outlen < BLAKE2S_OUTBYTES) ? outlen : BLAKE2S_OUTBYTES;
/* Initialize state */
P->digest_length = block_size;
store32(&P->node_offset, i);
blake2s_init_param(C, P);
/* Process key if needed */
blake2s_update(C, root, BLAKE2S_OUTBYTES);
if (blake2s_final(C, (uint8_t *)out + i * BLAKE2S_OUTBYTES, block_size) < 0) {
return -1;
}
outlen -= block_size;
}
secure_zero_memory(root, sizeof(root));
secure_zero_memory(P, sizeof(P));
secure_zero_memory(C, sizeof(C));
/* Put blake2xs in an invalid state? cf. blake2s_is_lastblock */
return 0;
}
int blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
{
blake2xs_state S[1];
/* Verify parameters */
if (NULL == in && inlen > 0)
return -1;
if (NULL == out)
return -1;
if (NULL == key && keylen > 0)
return -1;
if (keylen > BLAKE2S_KEYBYTES)
return -1;
if (outlen == 0)
return -1;
/* Initialize the root block structure */
if (blake2xs_init_key(S, outlen, key, keylen) < 0) {
return -1;
}
/* Absorb the input message */
blake2xs_update(S, in, inlen);
/* Compute the root node of the tree and the final hash using the counter construction */
return blake2xs_final(S, out, outlen);
}
#if defined(BLAKE2XS_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main( void )
{
uint8_t key[BLAKE2S_KEYBYTES];
uint8_t buf[BLAKE2_KAT_LENGTH];
size_t i, step, outlen;
for( i = 0; i < BLAKE2S_KEYBYTES; ++i ) {
key[i] = ( uint8_t )i;
}
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) {
buf[i] = ( uint8_t )i;
}
/* Testing length of ouputs rather than inputs */
/* (Test of input lengths mostly covered by blake2s tests) */
/* Test simple API */
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
{
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
if( blake2xs( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2S_KEYBYTES ) < 0 ) {
goto fail;
}
if( 0 != memcmp( hash, blake2xs_keyed_kat[outlen-1], outlen ) )
{
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
for (outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen) {
uint8_t hash[BLAKE2_KAT_LENGTH];
blake2xs_state S;
uint8_t * p = buf;
size_t mlen = BLAKE2_KAT_LENGTH;
int err = 0;
if( (err = blake2xs_init_key(&S, outlen, key, BLAKE2S_KEYBYTES)) < 0 ) {
goto fail;
}
while (mlen >= step) {
if ( (err = blake2xs_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2xs_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2xs_final(&S, hash, outlen)) < 0) {
goto fail;
}
if (0 != memcmp(hash, blake2xs_keyed_kat[outlen-1], outlen)) {
goto fail;
}
}
}
puts( "ok" );
return 0;
fail:
puts("error");
return -1;
}
#endif

139
blake2/genkat-c.c Normal file
View file

@ -0,0 +1,139 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "blake2.h"
#define STR_(x) #x
#define STR(x) STR_(x)
#define LENGTH 256
#define MAKE_KAT(name, size_prefix) \
do { \
printf("static const uint8_t " #name "_kat[BLAKE2_KAT_LENGTH][" #size_prefix \
"_OUTBYTES] = \n{\n"); \
\
for (i = 0; i < LENGTH; ++i) { \
name(hash, size_prefix##_OUTBYTES, in, i, NULL, 0); \
printf("\t{\n\t\t"); \
\
for (j = 0; j < size_prefix##_OUTBYTES; ++j) \
printf("0x%02X%s", hash[j], \
(j + 1) == size_prefix##_OUTBYTES ? "\n" : j && !((j + 1) % 8) ? ",\n\t\t" : ", "); \
\
printf("\t},\n"); \
} \
\
printf("};\n\n\n\n\n"); \
} while (0)
#define MAKE_KEYED_KAT(name, size_prefix) \
do { \
printf("static const uint8_t " #name "_keyed_kat[BLAKE2_KAT_LENGTH][" #size_prefix \
"_OUTBYTES] = \n{\n"); \
\
for (i = 0; i < LENGTH; ++i) { \
name(hash, size_prefix##_OUTBYTES, in, i, key, size_prefix##_KEYBYTES); \
printf("\t{\n\t\t"); \
\
for (j = 0; j < size_prefix##_OUTBYTES; ++j) \
printf("0x%02X%s", hash[j], \
(j + 1) == size_prefix##_OUTBYTES ? "\n" : j && !((j + 1) % 8) ? ",\n\t\t" : ", "); \
\
printf("\t},\n"); \
} \
\
printf("};\n\n\n\n\n"); \
} while (0)
#define MAKE_XOF_KAT(name) \
do { \
printf("static const uint8_t " #name "_kat[BLAKE2_KAT_LENGTH][BLAKE2_KAT_LENGTH] = \n{\n"); \
\
for (i = 1; i <= LENGTH; ++i) { \
name(hash, i, in, LENGTH, NULL, 0); \
printf("\t{\n\t\t"); \
\
for (j = 0; j < i; ++j) \
printf("0x%02X%s", hash[j], \
(j + 1) == LENGTH ? "\n" : j && !((j + 1) % 8) ? ",\n\t\t" : ", "); \
\
for (j = i; j < LENGTH; ++j) \
printf("0x00%s", (j + 1) == LENGTH ? "\n" : j && !((j + 1) % 8) ? ",\n\t\t" : ", "); \
\
printf("\t},\n"); \
} \
\
printf("};\n\n\n\n\n"); \
} while (0)
#define MAKE_XOF_KEYED_KAT(name, size_prefix) \
do { \
printf("static const uint8_t " #name \
"_keyed_kat[BLAKE2_KAT_LENGTH][BLAKE2_KAT_LENGTH] = \n{\n"); \
\
for (i = 1; i <= LENGTH; ++i) { \
name(hash, i, in, LENGTH, key, size_prefix##_KEYBYTES); \
printf("\t{\n\t\t"); \
\
for (j = 0; j < i; ++j) \
printf("0x%02X%s", hash[j], \
(j + 1) == LENGTH ? "\n" : j && !((j + 1) % 8) ? ",\n\t\t" : ", "); \
\
for (j = i; j < LENGTH; ++j) \
printf("0x00%s", (j + 1) == LENGTH ? "\n" : j && !((j + 1) % 8) ? ",\n\t\t" : ", "); \
\
printf("\t},\n"); \
} \
\
printf("};\n\n\n\n\n"); \
} while (0)
int main() {
uint8_t key[64] = {0};
uint8_t in[LENGTH] = {0};
uint8_t hash[LENGTH] = {0};
size_t i, j;
for (i = 0; i < sizeof(in); ++i)
in[i] = i;
for (i = 0; i < sizeof(key); ++i)
key[i] = i;
puts("#ifndef BLAKE2_KAT_H\n"
"#define BLAKE2_KAT_H\n\n\n"
"#include <stdint.h>\n\n"
"#define BLAKE2_KAT_LENGTH " STR(LENGTH) "\n\n\n");
MAKE_KAT(blake2s, BLAKE2S);
MAKE_KEYED_KAT(blake2s, BLAKE2S);
MAKE_KAT(blake2b, BLAKE2B);
MAKE_KEYED_KAT(blake2b, BLAKE2B);
MAKE_KAT(blake2sp, BLAKE2S);
MAKE_KEYED_KAT(blake2sp, BLAKE2S);
MAKE_KAT(blake2bp, BLAKE2B);
MAKE_KEYED_KAT(blake2bp, BLAKE2B);
MAKE_XOF_KAT(blake2xs);
MAKE_XOF_KEYED_KAT(blake2xs, BLAKE2S);
MAKE_XOF_KAT(blake2xb);
MAKE_XOF_KEYED_KAT(blake2xb, BLAKE2B);
puts("#endif");
return 0;
}

154
blake2/genkat-json.c Normal file
View file

@ -0,0 +1,154 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "blake2.h"
#define STR_(x) #x
#define STR(x) STR_(x)
#define LENGTH 256
#define MAKE_KAT(name, size_prefix, first) \
do { \
for (i = 0; i < LENGTH; ++i) { \
printf("%s\n{\n", i == 0 && first ? "" : ","); \
\
printf(" \"hash\": \"" #name "\",\n"); \
printf(" \"in\": \""); \
for (j = 0; j < i; ++j) \
printf("%02x", in[j]); \
\
printf("\",\n"); \
printf(" \"key\": \"\",\n"); \
printf(" \"out\": \""); \
\
name(hash, size_prefix##_OUTBYTES, in, i, NULL, 0); \
\
for (j = 0; j < size_prefix##_OUTBYTES; ++j) \
printf("%02x", hash[j]); \
printf("\"\n"); \
printf("}"); \
} \
} while (0)
#define MAKE_KEYED_KAT(name, size_prefix, first) \
do { \
for (i = 0; i < LENGTH; ++i) { \
printf("%s\n{\n", i == 0 && first ? "" : ","); \
\
printf(" \"hash\": \"" #name "\",\n"); \
printf(" \"in\": \""); \
for (j = 0; j < i; ++j) \
printf("%02x", in[j]); \
\
printf("\",\n"); \
printf(" \"key\": \""); \
for (j = 0; j < size_prefix##_KEYBYTES; ++j) \
printf("%02x", key[j]); \
printf("\",\n"); \
printf(" \"out\": \""); \
\
name(hash, size_prefix##_OUTBYTES, in, i, key, size_prefix##_KEYBYTES); \
\
for (j = 0; j < size_prefix##_OUTBYTES; ++j) \
printf("%02x", hash[j]); \
printf("\"\n"); \
printf("}"); \
} \
} while (0)
#define MAKE_XOF_KAT(name, first) \
do { \
for (i = 1; i <= LENGTH; ++i) { \
printf("%s\n{\n", i == 1 && first ? "" : ","); \
\
printf(" \"hash\": \"" #name "\",\n"); \
printf(" \"in\": \""); \
for (j = 0; j < LENGTH; ++j) \
printf("%02x", in[j]); \
\
printf("\",\n"); \
printf(" \"key\": \"\",\n"); \
printf(" \"out\": \""); \
\
name(hash, i, in, LENGTH, NULL, 0); \
\
for (j = 0; j < i; ++j) \
printf("%02x", hash[j]); \
printf("\"\n"); \
printf("}"); \
} \
} while (0)
#define MAKE_XOF_KEYED_KAT(name, size_prefix, first) \
do { \
for (i = 1; i <= LENGTH; ++i) { \
printf("%s\n{\n", i == 1 && first ? "" : ","); \
\
printf(" \"hash\": \"" #name "\",\n"); \
printf(" \"in\": \""); \
for (j = 0; j < LENGTH; ++j) \
printf("%02x", in[j]); \
\
printf("\",\n"); \
printf(" \"key\": \""); \
for (j = 0; j < size_prefix##_KEYBYTES; ++j) \
printf("%02x", key[j]); \
printf("\",\n"); \
printf(" \"out\": \""); \
\
name(hash, i, in, LENGTH, key, size_prefix##_KEYBYTES); \
\
for (j = 0; j < i; ++j) \
printf("%02x", hash[j]); \
printf("\"\n"); \
printf("}"); \
} \
} while (0)
int main() {
uint8_t key[64] = {0};
uint8_t in[LENGTH] = {0};
uint8_t hash[LENGTH] = {0};
size_t i, j;
for (i = 0; i < sizeof(in); ++i)
in[i] = i;
for (i = 0; i < sizeof(key); ++i)
key[i] = i;
printf("[");
MAKE_KAT(blake2s, BLAKE2S, 1);
MAKE_KEYED_KAT(blake2s, BLAKE2S, 0);
MAKE_KAT(blake2b, BLAKE2B, 0);
MAKE_KEYED_KAT(blake2b, BLAKE2B, 0);
MAKE_KAT(blake2sp, BLAKE2S, 0);
MAKE_KEYED_KAT(blake2sp, BLAKE2S, 0);
MAKE_KAT(blake2bp, BLAKE2B, 0);
MAKE_KEYED_KAT(blake2bp, BLAKE2B, 0);
MAKE_XOF_KAT(blake2xs, 0);
MAKE_XOF_KEYED_KAT(blake2xs, BLAKE2S, 0);
MAKE_XOF_KAT(blake2xb, 0);
MAKE_XOF_KEYED_KAT(blake2xb, BLAKE2B, 0);
printf("\n]\n");
fflush(stdout);
return 0;
}

View file

@ -1,7 +1,8 @@
CC=gcc
CFLAGS=-std=c99 -Wall -pedantic -O3 -march=native
CFLAGS=-O3 -I../testvectors -Wall -Wextra -std=c89 -pedantic -Wno-long-long
BLAKEBINS=blake2s blake2b blake2sp blake2bp blake2xs blake2xb
all: blake2s blake2b blake2sp blake2bp
all: $(BLAKEBINS) check
blake2s: blake2s.c
$(CC) blake2s.c -o $@ $(CFLAGS) -DBLAKE2S_SELFTEST
@ -15,5 +16,25 @@ blake2sp: blake2sp.c blake2s.c
blake2bp: blake2bp.c blake2b.c
$(CC) blake2bp.c blake2b.c -o $@ $(CFLAGS) -DBLAKE2BP_SELFTEST
clean:
rm -rf *.o blake2s blake2b blake2sp blake2bp
blake2xs: blake2xs.c blake2s.c
$(CC) blake2xs.c blake2s.c -o $@ $(CFLAGS) -DBLAKE2XS_SELFTEST
blake2xb: blake2xb.c blake2b.c
$(CC) blake2xb.c blake2b.c -o $@ $(CFLAGS) -DBLAKE2XB_SELFTEST
check: blake2s blake2b blake2sp blake2bp blake2xs blake2xb
./blake2s
./blake2b
./blake2sp
./blake2bp
./blake2xs
./blake2xb
kat:
$(CC) $(CFLAGS) -o genkat-c genkat-c.c blake2b.c blake2s.c blake2sp.c blake2bp.c blake2xs.c blake2xb.c
$(CC) $(CFLAGS) -g -o genkat-json genkat-json.c blake2b.c blake2s.c blake2sp.c blake2bp.c blake2xs.c blake2xb.c
./genkat-c > blake2-kat.h
./genkat-json > blake2-kat.json
clean:
rm -rf *.o genkat-c genkat-json blake2-kat.h blake2-kat.json $(BLAKEBINS)

1
phc-winner-argon2 Submodule

@ -0,0 +1 @@
Subproject commit ea080f9d8e560023707521b760bdc0e6d65a6d31

View file

@ -15,7 +15,5 @@ enum class rai_networks
rai_live_network
};
rai::rai_networks const rai_network = rai_networks::ACTIVE_NETWORK;
int const database_check_interval = rai_network == rai::rai_networks::rai_test_network ? 64 : 256;
size_t const database_size_increment = rai_network == rai::rai_networks::rai_test_network ? 2 * 1024 * 1024 : 1024 * 1024 * 1024;
size_t const blocks_per_transaction = rai::rai_network == rai::rai_networks::rai_test_network ? 2 : 16384;
}

View file

@ -921,8 +921,52 @@ TEST (block_store, upgrade_v8_v9)
rai::block_store store (init, path);
ASSERT_FALSE (init);
rai::transaction transaction (store.environment, nullptr, false);
ASSERT_EQ (9, store.version_get (transaction));
ASSERT_LT (8, store.version_get (transaction));
auto vote (store.vote_get (transaction, key.pub));
ASSERT_NE (nullptr, vote);
ASSERT_EQ (10, vote->sequence);
}
TEST (block_store, upgrade_v9_v10)
{
auto path (rai::unique_path ());
rai::block_hash hash (0);
{
bool init (false);
rai::block_store store (init, path);
ASSERT_FALSE (init);
rai::transaction transaction (store.environment, nullptr, true);
rai::genesis genesis;;
genesis.initialize (transaction, store);
rai::ledger ledger (store);
store.version_put (transaction, 9);
rai::account_info info;
store.account_get (transaction, rai::test_genesis_key.pub, info);
rai::keypair key0;
rai::uint128_t balance (rai::genesis_amount);
hash = info.head;
for (auto i (1); i < 32; ++i) // Making 31 send blocks (+ 1 open = 32 total)
{
balance = balance - rai::Gxrb_ratio;
rai::send_block block0 (hash, key0.pub, balance, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
ASSERT_EQ (rai::process_result::progress, ledger.process (transaction, block0).code);
hash = block0.hash ();
}
rai::block_info block_info_auto; // Checking automatic block_info creation for block 32
store.block_info_get (transaction, hash, block_info_auto);
ASSERT_EQ (block_info_auto.account, rai::test_genesis_key.pub);
ASSERT_EQ (block_info_auto.balance.number (), balance);
ASSERT_EQ (0, mdb_drop (transaction, store.blocks_info, 0)); // Cleaning blocks_info subdatabase
bool block_info_exists (store.block_info_exists (transaction, hash));
ASSERT_EQ (block_info_exists, 0); // Checking if automatic block_info is deleted
}
bool init (false);
rai::block_store store (init, path);
ASSERT_FALSE (init);
rai::transaction transaction (store.environment, nullptr, false);
ASSERT_LT (9, store.version_get (transaction));
rai::block_info block_info;
store.block_info_get (transaction, hash, block_info);
ASSERT_EQ (block_info.account, rai::test_genesis_key.pub);
ASSERT_EQ (block_info.balance.number (), rai::genesis_amount - rai::Gxrb_ratio * 31);
}

View file

@ -1361,7 +1361,7 @@ TEST (rpc, version)
ASSERT_EQ (200, response1.status);
ASSERT_EQ ("1", response1.json.get <std::string> ("rpc_version"));
ASSERT_EQ (200, response1.status);
ASSERT_EQ ("9", response1.json.get <std::string> ("store_version"));
ASSERT_EQ ("10", response1.json.get <std::string> ("store_version"));
ASSERT_EQ (boost::str (boost::format ("RaiBlocks %1%.%2%") % RAIBLOCKS_VERSION_MAJOR % RAIBLOCKS_VERSION_MINOR), response1.json.get <std::string> ("node_vendor"));
auto headers (response1.resp.find ("Access-Control-Allow-Origin"));
ASSERT_NE (response1.resp.end (), headers);

View file

@ -256,6 +256,8 @@ rai::frontier_req_client::frontier_req_client (std::shared_ptr <rai::bootstrap_c
connection (connection_a),
current (0),
count (0),
landing ("059F68AAB29DE0D3A27443625C7EA9CDDB6517A8B76FE37727EF6A4D76832AD5"),
faucet ("8E319CE6F3025E5B2DF66DA7AB1467FE48F1679C13DD43BFDB29FA2E9FC40D3B"),
next_report (std::chrono::system_clock::now () + std::chrono::seconds (15))
{
rai::transaction transaction (connection->node->store.environment, nullptr, false);
@ -279,8 +281,17 @@ void rai::frontier_req_client::receive_frontier ()
void rai::frontier_req_client::request_account (rai::account const & account_a, rai::block_hash const & latest_a)
{
// Account they know about and we don't.
connection->attempt->pulls.push_back (rai::pull_info (account_a, latest_a, rai::block_hash (0)));
// Account they know about and we don't.
rai::account account_1 ("6B31E80CABDD2FEE6F54A7BDBF91B666010418F4438EF0B48168F93CD79DBC85"); // xrb_1tsjx18cqqbhxsqobbxxqyauesi31iehaiwgy4ta4t9s9mdsuh671npo1st9
rai::account account_2 ("FD6EE9E0E107A6A8584DB94A3F154799DD5C2A7D6ABED0889DA3B837B0E61663"); // xrb_3zdgx9ig43x8o3e6ugcc9wcnh8gxdio9ttoyt46buaxr8yrge7m5331qdwhk
if (account_a != landing && account_a != faucet && account_a != account_1 && account_a != account_2)
{
connection->attempt->pulls.push_back (rai::pull_info (account_a, latest_a, rai::block_hash (0)));
}
else
{
connection->attempt->pulls.push_front (rai::pull_info (account_a, latest_a, rai::block_hash (0)));
}
}
void rai::frontier_req_client::unsynced (MDB_txn * transaction_a, rai::block_hash const & ours_a, rai::block_hash const & theirs_a)
@ -348,8 +359,6 @@ void rai::frontier_req_client::received_frontier (boost::system::error_code cons
else
{
// They know about a block we don't.
rai::account landing ("059F68AAB29DE0D3A27443625C7EA9CDDB6517A8B76FE37727EF6A4D76832AD5");
rai::account faucet ("8E319CE6F3025E5B2DF66DA7AB1467FE48F1679C13DD43BFDB29FA2E9FC40D3B");
if (account != rai::genesis_account && account != landing && account != faucet)
{
connection->attempt->pulls.push_back (rai::pull_info (account, latest, info.head));

View file

@ -105,6 +105,8 @@ public:
rai::account current;
rai::account_info info;
unsigned count;
rai::account landing;
rai::account faucet;
std::chrono::system_clock::time_point next_report;
std::promise <bool> promise;
};

View file

@ -363,7 +363,7 @@ bool rai::confirm_req::operator == (rai::confirm_req const & other_a) const
rai::confirm_ack::confirm_ack (bool & error_a, rai::stream & stream_a) :
message (error_a, stream_a),
vote (std::make_shared <rai::vote> (error_a, stream_a))
vote (std::make_shared <rai::vote> (error_a, stream_a, block_type ()))
{
}
@ -403,7 +403,7 @@ void rai::confirm_ack::serialize (rai::stream & stream_a)
{
assert (block_type () == rai::block_type::send || block_type () == rai::block_type::receive || block_type () == rai::block_type::open || block_type () == rai::block_type::change);
write_header (stream_a);
vote->serialize (stream_a);
vote->serialize (stream_a, block_type ());
}
bool rai::confirm_ack::operator == (rai::confirm_ack const & other_a) const

View file

@ -1309,14 +1309,6 @@ vote_processor (*this),
warmed_up (0),
block_processor (*this)
{
store.environment.sizing_action = [this] ()
{
auto this_l (shared_from_this ());
background ([this_l] ()
{
this_l->store.environment.handle_environment_sizing ();
});
};
wallets.observer = [this] (rai::account const & account_a, bool active)
{
observers.wallet (account_a, active);

View file

@ -49,10 +49,10 @@ typedef struct __blake2b_state
__constant static ulong blake2b_IV[8] =
{
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
0x6a09e667f3bcc908UL, 0xbb67ae8584caa73bUL,
0x3c6ef372fe94f82bUL, 0xa54ff53a5f1d36f1UL,
0x510e527fade682d1UL, 0x9b05688c2b3e6c1fUL,
0x1f83d9abfb41bd6bUL, 0x5be0cd19137e2179UL
};
__constant static uchar blake2b_sigma[12][16] =
@ -206,7 +206,7 @@ static inline int blake2b_init( blake2b_state *S, const uchar outlen )
return blake2b_init_param( S, P );
}
static int blake2b_compress( blake2b_state *S, const uchar block[BLAKE2B_BLOCKBYTES] )
static int blake2b_compress( blake2b_state *S, __private const uchar block[BLAKE2B_BLOCKBYTES] )
{
ulong m[16];
ulong v[16];
@ -382,7 +382,7 @@ __kernel void raiblocks_work (__global ulong * attempt, __global ulong * result_
void printstate (blake2b_state * S)
{
printf ("%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n", S->h[0], S->h[1], S->h[2], S->h[3], S->h[4], S->h[5], S->h[6], S->h[7], S->t[0], S->t[1], S->f[0], S->f[1]);
printf ("%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n", S->h[0], S->h[1], S->h[2], S->h[3], S->h[4], S->h[5], S->h[6], S->h[7], S->t[0], S->t[1], S->f[0], S->f[1]);
for (int i = 0; i < 256; ++i)
{
printf ("%02x", S->buf[i]);

View file

@ -850,7 +850,7 @@ void rai::wallet_store::upgrade_v2_v3 ()
void rai::kdf::phs (rai::raw_key & result_a, std::string const & password_a, rai::uint256_union const & salt_a)
{
std::lock_guard <std::mutex> lock (mutex);
auto success (PHS (result_a.data.bytes.data (), result_a.data.bytes.size (), password_a.data (), password_a.size (), salt_a.bytes.data (), salt_a.bytes.size (), 1, rai::wallet_store::kdf_work));
auto success (argon2_hash (1, rai::wallet_store::kdf_work, 1, password_a.data (), password_a.size (), salt_a.bytes.data (), salt_a.bytes.size (), result_a.data.bytes.data (), result_a.data.bytes.size (), NULL, 0, Argon2_d, 0x10));
assert (success == 0); (void) success;
}
@ -1350,26 +1350,34 @@ public:
auto existing (keys.find (key.account));
if (existing != keys.end ())
{
rai::account_info info;
auto error (wallet->node.store.account_get (transaction, pending.source, info));
assert (!error);
BOOST_LOG (wallet->node.log) << boost::str (boost::format ("Found a pending block %1% from account %2% with head %3%") % pending.source.to_string () % pending.source.to_account () % info.head.to_string ());
auto account (pending.source);
if (already_searched.find (account) == already_searched.end ())
auto amount (pending.amount.number ());
if (wallet->node.config.receive_minimum.number () <= amount)
{
auto this_l (shared_from_this ());
std::shared_ptr <rai::block> block_l (wallet->node.store.block_get (transaction, info.head));
wallet->node.background ([this_l, account, block_l]
rai::account_info info;
auto error (wallet->node.store.account_get (transaction, pending.source, info));
assert (!error);
BOOST_LOG (wallet->node.log) << boost::str (boost::format ("Found a pending block %1% from account %2% with head %3%") % pending.source.to_string () % pending.source.to_account () % info.head.to_string ());
auto account (pending.source);
if (already_searched.find (account) == already_searched.end ())
{
rai::transaction transaction (this_l->wallet->node.store.environment, nullptr, true);
this_l->wallet->node.active.start (transaction, block_l, [this_l, account] (std::shared_ptr <rai::block>)
auto this_l (shared_from_this ());
std::shared_ptr <rai::block> block_l (wallet->node.store.block_get (transaction, info.head));
wallet->node.background ([this_l, account, block_l]
{
// If there were any forks for this account they've been rolled back and we can receive anything remaining from this account
this_l->receive_all (account);
rai::transaction transaction (this_l->wallet->node.store.environment, nullptr, true);
this_l->wallet->node.active.start (transaction, block_l, [this_l, account] (std::shared_ptr <rai::block>)
{
// If there were any forks for this account they've been rolled back and we can receive anything remaining from this account
this_l->receive_all (account);
});
this_l->wallet->node.network.broadcast_confirm_req (block_l);
});
this_l->wallet->node.network.broadcast_confirm_req (block_l);
});
already_searched.insert (account);
already_searched.insert (account);
}
}
else
{
BOOST_LOG (wallet->node.log) << boost::str (boost::format ("Not receiving block %1% due to minimum receive threshold") % pending.source.to_string ());
}
}
}

View file

@ -435,11 +435,32 @@ wallet (wallet_a)
else
{
show_line_error (*seed);
show_button_error (*import_seed);
if (seed->text ().toStdString ().size () != 64)
{
import_seed->setText ("Incorrect seed, length must be 64");
}
else
{
import_seed->setText ("Incorrect seed. Only HEX characters allowed");
}
this->wallet.node.alarm.add (std::chrono::system_clock::now () + std::chrono::seconds (5), [this] ()
{
show_button_ok (*import_seed);
import_seed->setText ("Import seed");
});
}
}
else
{
show_line_error (*clear_line);
show_button_error (*import_seed);
import_seed->setText ("Type words 'clear keys'");
this->wallet.node.alarm.add (std::chrono::system_clock::now () + std::chrono::seconds (5), [this] ()
{
show_button_ok (*import_seed);
import_seed->setText ("Import seed");
});
}
});
}
@ -934,51 +955,117 @@ void rai_qt::wallet::start ()
auto parse_error (account_l.decode_account (account_text_narrow));
if (!parse_error)
{
this_l->send_blocks_send->setEnabled (false);
this_l->node.background ([this_w, account_l, actual] ()
auto balance (this_l->node.balance (this_l->account));
if (actual <= balance)
{
if (auto this_l = this_w.lock ())
rai::transaction transaction (this_l->wallet_m->store.environment, nullptr, false);
if (this_l->wallet_m->store.valid_password (transaction))
{
this_l->wallet_m->send_async (this_l->account, account_l, actual, [this_w] (std::shared_ptr <rai::block> block_a)
this_l->send_blocks_send->setEnabled (false);
this_l->node.background ([this_w, account_l, actual] ()
{
if (auto this_l = this_w.lock ())
{
auto succeeded (block_a != nullptr);
this_l->application.postEvent (&this_l->processor, new eventloop_event ([this_w, succeeded] ()
this_l->wallet_m->send_async (this_l->account, account_l, actual, [this_w] (std::shared_ptr <rai::block> block_a)
{
if (auto this_l = this_w.lock ())
{
this_l->send_blocks_send->setEnabled (true);
if (succeeded)
auto succeeded (block_a != nullptr);
this_l->application.postEvent (&this_l->processor, new eventloop_event ([this_w, succeeded] ()
{
this_l->send_count->clear ();
this_l->send_account->clear ();
this_l->accounts.refresh ();
}
else
{
show_line_error (*this_l->send_count);
}
if (auto this_l = this_w.lock ())
{
this_l->send_blocks_send->setEnabled (true);
if (succeeded)
{
this_l->send_count->clear ();
this_l->send_account->clear ();
this_l->accounts.refresh ();
}
else
{
show_line_error (*this_l->send_count);
}
}
}));
}
}));
});
}
});
}
});
else
{
show_button_error (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Wallet is locked, unlock it to send");
this_l->node.alarm.add (std::chrono::system_clock::now () + std::chrono::seconds (5), [this_w] ()
{
if (auto this_l = this_w.lock ())
{
show_button_ok (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Send");
}
});
}
}
else
{
show_line_error (*this_l->send_count);
show_button_error (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Not enough balance");
this_l->node.alarm.add (std::chrono::system_clock::now () + std::chrono::seconds (5), [this_w] ()
{
if (auto this_l = this_w.lock ())
{
show_button_ok (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Send");
}
});
}
}
else
{
show_line_error (*this_l->send_account);
show_button_error (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Bad destination account");
this_l->node.alarm.add (std::chrono::system_clock::now () + std::chrono::seconds (5), [this_w] ()
{
if (auto this_l = this_w.lock ())
{
show_button_ok (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Send");
}
});
}
}
else
{
show_line_error (*this_l->send_account);
show_line_error (*this_l->send_count);
show_button_error (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Amount too big");
this_l->node.alarm.add (std::chrono::system_clock::now () + std::chrono::seconds (5), [this_w] ()
{
if (auto this_l = this_w.lock ())
{
show_line_ok (*this_l->send_account);
show_button_ok (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Send");
}
});
}
}
else
{
show_line_error (*this_l->send_count);
show_button_error (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Bad amount number");
this_l->node.alarm.add (std::chrono::system_clock::now () + std::chrono::seconds (5), [this_w] ()
{
if (auto this_l = this_w.lock ())
{
show_button_ok (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Send");
}
});
}
}
});
@ -1150,9 +1237,10 @@ void rai_qt::wallet::update_connected ()
void rai_qt::wallet::empty_password ()
{
rai::raw_key empty;
empty.data.clear ();
wallet_m->store.password.value_set (empty);
this->node.alarm.add (std::chrono::system_clock::now () + std::chrono::seconds (3), [this] ()
{
wallet_m->enter_password (std::string (""));
});
}
void rai_qt::wallet::change_rendering_ratio (rai::uint128_t const & rendering_ratio_a)

View file

@ -5,6 +5,7 @@
#include <argon2.h>
#include <boost/program_options.hpp>
#include <boost/lexical_cast.hpp>
class xorshift128
{
@ -110,17 +111,21 @@ int main (int argc, char * const * argv)
rai::add_node_options (description);
description.add_options ()
("help", "Print out options")
("daemon", "Start node daemon")
("daemon", "Start node daemon")
("debug_block_count", "Display the number of block")
("debug_bootstrap_generate", "Generate bootstrap sequence of blocks")
("debug_dump_representatives", "List representatives and weights")
("debug_frontier_count", "Display the number of accounts")
("debug_mass_activity", "Generates fake debug activity")
("debug_profile_generate", "Profile work generation")
("debug_opencl", "OpenCL work generation")
("debug_profile_verify", "Profile work verification")
("debug_profile_kdf", "Profile kdf function")
("debug_verify_profile", "Profile signature verification")
("debug_xorshift_profile", "Profile xorshift algorithms");
("debug_xorshift_profile", "Profile xorshift algorithms")
("platform", boost::program_options::value <std::string> (), "Defines the <platform> for OpenCL commands")
("device", boost::program_options::value <std::string> (), "Defines <device> for OpenCL command")
("threads", boost::program_options::value <std::string> (), "Defines <threads> count for OpenCL command");
boost::program_options::variables_map vm;
boost::program_options::store (boost::program_options::parse_command_line(argc, argv, description), vm);
boost::program_options::notify (vm);
@ -244,7 +249,7 @@ int main (int argc, char * const * argv)
for (; true;)
{
auto begin1 (std::chrono::high_resolution_clock::now ());
auto success (PHS (result.bytes.data (), result.bytes.size (), password.data (), password.size (), salt.bytes.data (), salt.bytes.size (), 1, rai::wallet_store::kdf_work));
auto success (argon2_hash (1, rai::wallet_store::kdf_work, 1, password.data (), password.size (), salt.bytes.data (), salt.bytes.size (), result.bytes.data (), result.bytes.size (), NULL, 0, Argon2_d, 0x10));
auto end1 (std::chrono::high_resolution_clock::now ());
std::cerr << boost::str (boost::format ("Derivation time: %1%us\n") % std::chrono::duration_cast <std::chrono::microseconds> (end1 - begin1).count ());
}
@ -263,6 +268,87 @@ int main (int argc, char * const * argv)
std::cerr << boost::str (boost::format ("%|1$ 12d|\n") % std::chrono::duration_cast <std::chrono::microseconds> (end1 - begin1).count ());
}
}
else if (vm.count ("debug_opencl"))
{
bool error (false);
rai::opencl_environment environment (error);
if (!error)
{
unsigned short platform (0);
if (vm.count ("platform") == 1)
{
try {
platform = boost::lexical_cast <unsigned short> (vm ["platform"].as <std::string> ());
}
catch (boost::bad_lexical_cast & e ) {
std::cerr << "Invalid platform id\n";
result = -1;
}
}
unsigned short device (0);
if (vm.count ("device") == 1)
{
try {
device = boost::lexical_cast <unsigned short> (vm ["device"].as <std::string> ());
}
catch (boost::bad_lexical_cast & e ) {
std::cerr << "Invalid device id\n";
result = -1;
}
}
unsigned threads (1024 * 1024);
if (vm.count ("threads") == 1)
{
try {
threads = boost::lexical_cast <unsigned> (vm ["threads"].as <std::string> ());
}
catch (boost::bad_lexical_cast & e ) {
std::cerr << "Invalid threads count\n";
result = -1;
}
}
if (!result)
{
error |= platform >= environment.platforms.size ();
if (!error)
{
error |= device >= environment.platforms[platform].devices.size ();
if (!error)
{
rai::logging logging;
logging.init (rai::unique_path ());
auto work (rai::opencl_work::create (true, {platform, device, threads}, logging));
rai::work_pool work_pool (std::numeric_limits <unsigned>::max (), std::move (work));
rai::change_block block (0, 0, rai::keypair ().prv, 0, 0);
std::cerr << boost::str (boost::format ("Starting OpenCL generation profiling. Platform: %1%. Device: %2%. Threads: %3%\n") % platform % device % threads);
for (uint64_t i (0); true; ++i)
{
block.hashables.previous.qwords [0] += 1;
auto begin1 (std::chrono::high_resolution_clock::now ());
block.block_work_set (work_pool.generate (block.root ()));
auto end1 (std::chrono::high_resolution_clock::now ());
std::cerr << boost::str (boost::format ("%|1$ 12d|\n") % std::chrono::duration_cast <std::chrono::microseconds> (end1 - begin1).count ());
}
}
else
{
std::cout << "Not available device id\n" << std::endl;
result = -1;
}
}
else
{
std::cout << "Not available platform id\n" << std::endl;
result = -1;
}
}
}
else
{
std::cout << "Error initializing OpenCL" << std::endl;
result = -1;
}
}
else if (vm.count ("debug_profile_verify"))
{
rai::work_pool work (std::numeric_limits <unsigned>::max (), nullptr);

View file

@ -1515,6 +1515,7 @@ receive_blocks (0),
open_blocks (0),
change_blocks (0),
pending (0),
blocks_info (0),
representation (0),
unchecked (0),
unsynced (0),
@ -1530,6 +1531,7 @@ checksum (0)
error_a |= mdb_dbi_open (transaction, "open", MDB_CREATE, &open_blocks) != 0;
error_a |= mdb_dbi_open (transaction, "change", MDB_CREATE, &change_blocks) != 0;
error_a |= mdb_dbi_open (transaction, "pending", MDB_CREATE, &pending) != 0;
error_a |= mdb_dbi_open (transaction, "blocks_info", MDB_CREATE, &blocks_info) != 0;
error_a |= mdb_dbi_open (transaction, "representation", MDB_CREATE, &representation) != 0;
error_a |= mdb_dbi_open (transaction, "unchecked", MDB_CREATE | MDB_DUPSORT, &unchecked) != 0;
error_a |= mdb_dbi_open (transaction, "unsynced", MDB_CREATE, &unsynced) != 0;
@ -1592,6 +1594,8 @@ void rai::block_store::do_upgrades (MDB_txn * transaction_a)
case 8:
upgrade_v8_to_v9 (transaction_a);
case 9:
upgrade_v9_to_v10 (transaction_a);
case 10:
break;
default:
assert (false);
@ -1801,6 +1805,31 @@ void rai::block_store::upgrade_v8_to_v9 (MDB_txn * transaction_a)
mdb_drop (transaction_a, sequence, 1);
}
void rai::block_store::upgrade_v9_to_v10 (MDB_txn * transaction_a)
{
version_put (transaction_a, 10);
for (auto i (latest_begin (transaction_a)), n (latest_end ()); i != n; ++i)
{
rai::account account (i->first);
rai::account_info info (i->second);
size_t block_count (1);
auto hash (info.open_block);
while (!hash.is_zero ())
{
if ((block_count % block_info_max) == 0)
{
rai::block_info block_info;
block_info.account = account;
rai::amount balance (block_balance (transaction_a, hash));
block_info.balance = balance;
block_info_put (transaction_a, hash, block_info);
}
hash = block_successor (transaction_a, hash);
++block_count;
}
}
}
void rai::block_store::clear (MDB_dbi db_a)
{
rai::transaction transaction (environment, nullptr, true);
@ -2304,6 +2333,110 @@ rai::mdb_val rai::pending_key::val () const
return rai::mdb_val (sizeof (*this), const_cast <rai::pending_key *> (this));
}
void rai::block_store::block_info_put (MDB_txn * transaction_a, rai::block_hash const & hash_a, rai::block_info const & block_info_a)
{
auto status (mdb_put (transaction_a, blocks_info, hash_a.val (), block_info_a.val (), 0));
assert (status == 0);
}
void rai::block_store::block_info_del (MDB_txn * transaction_a, rai::block_hash const & hash_a)
{
auto status (mdb_del (transaction_a, blocks_info, hash_a.val (), nullptr));
assert (status == 0);
}
bool rai::block_store::block_info_exists (MDB_txn * transaction_a, rai::block_hash const & hash_a)
{
auto iterator (block_info_begin (transaction_a, hash_a));
return iterator != rai::store_iterator (nullptr) && rai::block_hash (iterator->first) == hash_a;
}
bool rai::block_store::block_info_get (MDB_txn * transaction_a, rai::block_hash const & hash_a, rai::block_info & block_info_a)
{
MDB_val value;
auto status (mdb_get (transaction_a, blocks_info, hash_a.val (), &value));
assert (status == 0 || status == MDB_NOTFOUND);
bool result;
if (status == MDB_NOTFOUND)
{
result = true;
}
else
{
result = false;
assert (value.mv_size == sizeof (block_info_a.account.bytes) + sizeof (block_info_a.balance.bytes));
rai::bufferstream stream (reinterpret_cast <uint8_t const *> (value.mv_data), value.mv_size);
auto error1 (rai::read (stream, block_info_a.account));
assert (!error1);
auto error2 (rai::read (stream, block_info_a.balance));
assert (!error2);
}
return result;
}
rai::store_iterator rai::block_store::block_info_begin (MDB_txn * transaction_a, rai::block_hash const & hash_a)
{
rai::store_iterator result (transaction_a, blocks_info, hash_a.val ());
return result;
}
rai::store_iterator rai::block_store::block_info_begin (MDB_txn * transaction_a)
{
rai::store_iterator result (transaction_a, blocks_info);
return result;
}
rai::store_iterator rai::block_store::block_info_end ()
{
rai::store_iterator result (nullptr);
return result;
}
rai::block_info::block_info () :
account (0),
balance (0)
{
}
rai::block_info::block_info (MDB_val const & val_a)
{
assert(val_a.mv_size == sizeof (*this));
static_assert (sizeof (account) + sizeof (balance) == sizeof (*this), "Packed class");
std::copy (reinterpret_cast <uint8_t const *> (val_a.mv_data), reinterpret_cast <uint8_t const *> (val_a.mv_data) + sizeof (*this), reinterpret_cast <uint8_t *> (this));
}
rai::block_info::block_info (rai::account const & account_a, rai::amount const & balance_a) :
account (account_a),
balance (balance_a)
{
}
void rai::block_info::serialize (rai::stream & stream_a) const
{
rai::write (stream_a, account.bytes);
rai::write (stream_a, balance.bytes);
}
bool rai::block_info::deserialize (rai::stream & stream_a)
{
auto result (rai::read (stream_a, account.bytes));
if (!result)
{
result = rai::read (stream_a, balance.bytes);
}
return result;
}
bool rai::block_info::operator == (rai::block_info const & other_a) const
{
return account == other_a.account && balance == other_a.balance;
}
rai::mdb_val rai::block_info::val () const
{
return rai::mdb_val (sizeof (*this), const_cast <rai::block_info *> (this));
}
rai::uint128_t rai::block_store::representation_get (MDB_txn * transaction_a, rai::account const & account_a)
{
MDB_val value;
@ -2808,10 +2941,18 @@ void balance_visitor::send_block (rai::send_block const & block_a)
void balance_visitor::receive_block (rai::receive_block const & block_a)
{
amount_visitor source (transaction, store);
source.compute (block_a.hashables.source);
result += source.result;
current = block_a.hashables.previous;
amount_visitor source (transaction, store);
source.compute (block_a.hashables.source);
rai::block_info block_info;
if (!store.block_info_get (transaction, block_a.hash (), block_info))
{
result += block_info.balance.number ();
current = 0;
}
else {
result += source.result;
current = block_a.hashables.previous;
}
}
void balance_visitor::open_block (rai::open_block const & block_a)
@ -2824,7 +2965,15 @@ void balance_visitor::open_block (rai::open_block const & block_a)
void balance_visitor::change_block (rai::change_block const & block_a)
{
current = block_a.hashables.previous;
rai::block_info block_info;
if (!store.block_info_get (transaction, block_a.hash (), block_info))
{
result += block_info.balance.number ();
current = 0;
}
else {
current = block_a.hashables.previous;
}
}
// Rollback this block
@ -2855,6 +3004,10 @@ public:
ledger.store.frontier_del (transaction, hash);
ledger.store.frontier_put (transaction, block_a.hashables.previous, pending.source);
ledger.store.block_successor_clear (transaction, block_a.hashables.previous);
if (!(info.block_count % ledger.store.block_info_max))
{
ledger.store.block_info_del (transaction, hash);
}
}
void receive_block (rai::receive_block const & block_a) override
{
@ -2872,6 +3025,10 @@ public:
ledger.store.frontier_del (transaction, hash);
ledger.store.frontier_put (transaction, block_a.hashables.previous, destination_account);
ledger.store.block_successor_clear (transaction, block_a.hashables.previous);
if (!(info.block_count % ledger.store.block_info_max))
{
ledger.store.block_info_del (transaction, hash);
}
}
void open_block (rai::open_block const & block_a) override
{
@ -2901,6 +3058,10 @@ public:
ledger.store.frontier_del (transaction, hash);
ledger.store.frontier_put (transaction, block_a.hashables.previous, account);
ledger.store.block_successor_clear (transaction, block_a.hashables.previous);
if (!(info.block_count % ledger.store.block_info_max))
{
ledger.store.block_info_del (transaction, hash);
}
}
MDB_txn * transaction;
rai::ledger & ledger;
@ -2947,6 +3108,13 @@ rai::uint128_t rai::ledger::balance (MDB_txn * transaction_a, rai::block_hash co
return visitor.result;
}
rai::uint128_t rai::block_store::block_balance (MDB_txn * transaction_a, rai::block_hash const & hash_a)
{
balance_visitor visitor (transaction_a, *this);
visitor.compute (hash_a);
return visitor.result;
}
// Balance for an account by account number
rai::uint128_t rai::ledger::account_balance (MDB_txn * transaction_a, rai::account const & account_a)
{
@ -3054,7 +3222,8 @@ rai::account rai::ledger::account (MDB_txn * transaction_a, rai::block_hash cons
assert (store.block_exists (transaction_a, hash_a));
auto hash (hash_a);
rai::block_hash successor (1);
while (!successor.is_zero ())
rai::block_info block_info;
while (!successor.is_zero () && store.block_info_get (transaction_a, successor, block_info))
{
successor = store.block_successor (transaction_a, hash);
if (!successor.is_zero ())
@ -3062,7 +3231,15 @@ rai::account rai::ledger::account (MDB_txn * transaction_a, rai::block_hash cons
hash = successor;
}
}
auto result (store.frontier_get (transaction_a, hash));
rai::account result;
if (successor.is_zero ())
{
result = store.frontier_get (transaction_a, hash);
}
else
{
result = block_info.account;
}
assert (!result.is_zero ());
return result;
}
@ -3161,6 +3338,13 @@ void rai::ledger::change_latest (MDB_txn * transaction_a, rai::account const & a
info.modified = store.now ();
info.block_count = block_count_a;
store.account_put (transaction_a, account_a, info);
if (!(block_count_a % store.block_info_max))
{
rai::block_info block_info;
block_info.account = account_a;
block_info.balance = balance_a;
store.block_info_put (transaction_a, hash_a, block_info);
}
checksum_update (transaction_a, hash_a);
}
else
@ -3470,6 +3654,14 @@ rai::uint256_union rai::vote::hash () const
return result;
}
void rai::vote::serialize (rai::stream & stream_a, rai::block_type)
{
write (stream_a, account);
write (stream_a, signature);
write (stream_a, sequence);
block->serialize (stream_a);
}
void rai::vote::serialize (rai::stream & stream_a)
{
write (stream_a, account);

View file

@ -303,6 +303,19 @@ public:
rai::account account;
rai::block_hash hash;
};
class block_info
{
public:
block_info ();
block_info (MDB_val const &);
block_info (rai::account const &, rai::amount const &);
void serialize (rai::stream &) const;
bool deserialize (rai::stream &);
bool operator == (rai::block_info const &) const;
rai::mdb_val val () const;
rai::account account;
rai::amount balance;
};
class block_counts
{
public:
@ -325,6 +338,7 @@ public:
rai::uint256_union hash () const;
bool operator == (rai::vote const &) const;
bool operator != (rai::vote const &) const;
void serialize (rai::stream &, rai::block_type);
void serialize (rai::stream &);
std::string to_json () const;
// Vote round sequence number
@ -387,6 +401,16 @@ public:
rai::store_iterator pending_begin (MDB_txn *);
rai::store_iterator pending_end ();
void block_info_put (MDB_txn *, rai::block_hash const &, rai::block_info const &);
void block_info_del (MDB_txn *, rai::block_hash const &);
bool block_info_get (MDB_txn *, rai::block_hash const &, rai::block_info &);
bool block_info_exists (MDB_txn *, rai::block_hash const &);
rai::store_iterator block_info_begin (MDB_txn *, rai::block_hash const &);
rai::store_iterator block_info_begin (MDB_txn *);
rai::store_iterator block_info_end ();
rai::uint128_t block_balance (MDB_txn *, rai::block_hash const &);
static size_t const block_info_max = 32;
rai::uint128_t representation_get (MDB_txn *, rai::account const &);
void representation_put (MDB_txn *, rai::account const &, rai::uint128_t const &);
void representation_add (MDB_txn *, rai::account const &, rai::uint128_t const &);
@ -448,6 +472,7 @@ public:
void upgrade_v6_to_v7 (MDB_txn *);
void upgrade_v7_to_v8 (MDB_txn *);
void upgrade_v8_to_v9 (MDB_txn *);
void upgrade_v9_to_v10 (MDB_txn *);
void clear (MDB_dbi);
@ -466,6 +491,8 @@ public:
MDB_dbi change_blocks;
// block_hash -> sender, amount, destination // Pending blocks to sender account, amount, destination account
MDB_dbi pending;
// block_hash -> account, balance // Blocks info
MDB_dbi blocks_info;
// account -> weight // Representation
MDB_dbi representation;
// block_hash -> block // Unchecked bootstrap blocks

View file

@ -399,9 +399,11 @@ TEST (store, vote_load)
{
rai::system system (24000, 1);
auto & node (*system.nodes [0]);
auto block (std::make_shared <rai::send_block> (0, 0, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
for (auto i (0); i < 1000000; ++i)
{
rai::transaction transaction (node.store.environment, nullptr, true);
node.store.sequence_atomic_observe (transaction, 0, i);
auto vote (std::make_shared <rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, i, block));
node.store.vote_validate (transaction, vote);
}
}

View file

@ -52,11 +52,7 @@ bool rai::from_string_hex (std::string const & value_a, uint64_t & target_a)
return result;
}
rai::mdb_env::mdb_env (bool & error_a, boost::filesystem::path const & path_a) :
open_transactions (0),
transaction_iteration (0),
resizing (false),
sizing_action ([this] () { handle_environment_sizing (); })
rai::mdb_env::mdb_env (bool & error_a, boost::filesystem::path const & path_a)
{
boost::system::error_code error;
if (path_a.has_parent_path ())
@ -68,7 +64,7 @@ sizing_action ([this] () { handle_environment_sizing (); })
assert (status1 == 0);
auto status2 (mdb_env_set_maxdbs (environment, 128));
assert (status2 == 0);
auto status3 (mdb_env_set_mapsize (environment, 0));
auto status3 (mdb_env_set_mapsize (environment, 1ULL * 1024 * 1024 * 1024 * 1024)); // 1 Terabyte
assert (status3 == 0);
auto status4 (mdb_env_open (environment, path_a.string ().c_str (), MDB_NOSUBDIR, 00600));
error_a = status4 != 0;
@ -99,57 +95,6 @@ rai::mdb_env::operator MDB_env * () const
return environment;
}
void rai::mdb_env::add_transaction ()
{
// Minimize I/O from checking if we need to resive
// Too high and the enviroment might overflow
// Too low and we're making lots of trips to the disk
if ((transaction_iteration++ % rai::database_check_interval) == 0)
{
sizing_action ();
}
std::unique_lock <std::mutex> lock_l (lock);
// Wait for any resizing operations to complete
while (resizing)
{
resize_notify.wait (lock_l);
}
++open_transactions;
}
void rai::mdb_env::handle_environment_sizing ()
{
if (!resizing.exchange (true))
{
MDB_stat stats;
mdb_env_stat (environment, &stats);
MDB_envinfo info;
mdb_env_info (environment, &info);
double used_space (info.me_last_pgno * stats.ms_psize);
double needed_space (used_space * 1.25);
size_t increments_needed ((needed_space / database_size_increment) + 1);
size_t environment_size (increments_needed * database_size_increment);
if (info.me_mapsize < environment_size)
{
std::unique_lock <std::mutex> lock_l (lock);
while (open_transactions > 0)
{
open_notify.wait (lock_l);
}
mdb_env_set_mapsize (environment, environment_size);
}
resizing = false;
resize_notify.notify_all ();
}
}
void rai::mdb_env::remove_transaction ()
{
std::lock_guard <std::mutex> lock_l (lock);
--open_transactions;
open_notify.notify_all ();
}
rai::mdb_val::mdb_val (size_t size_a, void * data_a) :
value ({size_a, data_a})
{
@ -169,7 +114,6 @@ rai::mdb_val::operator MDB_val const & () const
rai::transaction::transaction (rai::mdb_env & environment_a, MDB_txn * parent_a, bool write) :
environment (environment_a)
{
environment_a.add_transaction ();
auto status (mdb_txn_begin (environment_a, parent_a, write ? 0 : MDB_RDONLY, &handle));
assert (status == 0);
}
@ -177,7 +121,6 @@ environment (environment_a)
rai::transaction::~transaction ()
{
auto status (mdb_txn_commit (handle));
environment.remove_transaction ();
assert (status == 0);
}

View file

@ -139,17 +139,7 @@ public:
mdb_env (bool &, boost::filesystem::path const &);
~mdb_env ();
operator MDB_env * () const;
void add_transaction ();
void remove_transaction ();
void handle_environment_sizing ();
MDB_env * environment;
std::mutex lock;
std::condition_variable open_notify;
unsigned open_transactions;
std::atomic_uint transaction_iteration;
std::condition_variable resize_notify;
std::atomic_bool resizing;
std::function <void ()> sizing_action;
};
class mdb_val
{