Merge remote-tracking branch 'upstream/master' into rpc_extanded_8
This commit is contained in:
commit
03094bca9a
53 changed files with 2870 additions and 3002 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
@ -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.";
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
213
blake2/blake2.h
213
blake2/blake2.h
|
@ -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
|
||||
|
||||
|
|
207
blake2/blake2b-compress-avx2.h
Normal file
207
blake2/blake2b-compress-avx2.h
Normal 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
|
54
blake2/blake2b-load-avx2-simple.h
Normal file
54
blake2/blake2b-load-avx2-simple.h
Normal 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
340
blake2/blake2b-load-avx2.h
Normal 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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
395
blake2/blake2b.c
395
blake2/blake2b.c
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
373
blake2/blake2s.c
373
blake2/blake2s.c
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
241
blake2/blake2xb.c
Normal 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
239
blake2/blake2xs.c
Normal 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
139
blake2/genkat-c.c
Normal 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
154
blake2/genkat-json.c
Normal 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;
|
||||
}
|
|
@ -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
1
phc-winner-argon2
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit ea080f9d8e560023707521b760bdc0e6d65a6d31
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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 ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
132
rai/qt/qt.cpp
132
rai/qt/qt.cpp
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
206
rai/secure.cpp
206
rai/secure.cpp
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue