245 lines
5.7 KiB
C
245 lines
5.7 KiB
C
|
/* Blake2s.c -- BLAKE2s and BLAKE2sp Hash
|
||
|
2015-06-30 : Igor Pavlov : Public domain
|
||
|
2015 : Samuel Neves : Public domain */
|
||
|
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "Blake2.h"
|
||
|
#include "CpuArch.h"
|
||
|
#include "RotateDefs.h"
|
||
|
|
||
|
#define rotr32 rotrFixed
|
||
|
|
||
|
#define BLAKE2S_NUM_ROUNDS 10
|
||
|
#define BLAKE2S_FINAL_FLAG (~(UInt32)0)
|
||
|
|
||
|
static const UInt32 k_Blake2s_IV[8] =
|
||
|
{
|
||
|
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
|
||
|
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
|
||
|
};
|
||
|
|
||
|
static const Byte k_Blake2s_Sigma[BLAKE2S_NUM_ROUNDS][16] =
|
||
|
{
|
||
|
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||
|
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
|
||
|
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
|
||
|
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
|
||
|
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
|
||
|
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
|
||
|
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
|
||
|
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
|
||
|
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
|
||
|
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
|
||
|
};
|
||
|
|
||
|
|
||
|
void Blake2s_Init0(CBlake2s *p)
|
||
|
{
|
||
|
unsigned i;
|
||
|
for (i = 0; i < 8; i++)
|
||
|
p->h[i] = k_Blake2s_IV[i];
|
||
|
p->t[0] = 0;
|
||
|
p->t[1] = 0;
|
||
|
p->f[0] = 0;
|
||
|
p->f[1] = 0;
|
||
|
p->bufPos = 0;
|
||
|
p->lastNode_f1 = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
static void Blake2s_Compress(CBlake2s *p)
|
||
|
{
|
||
|
UInt32 m[16];
|
||
|
UInt32 v[16];
|
||
|
|
||
|
{
|
||
|
unsigned i;
|
||
|
|
||
|
for (i = 0; i < 16; i++)
|
||
|
m[i] = GetUi32(p->buf + i * sizeof(m[i]));
|
||
|
|
||
|
for (i = 0; i < 8; i++)
|
||
|
v[i] = p->h[i];
|
||
|
}
|
||
|
|
||
|
v[ 8] = k_Blake2s_IV[0];
|
||
|
v[ 9] = k_Blake2s_IV[1];
|
||
|
v[10] = k_Blake2s_IV[2];
|
||
|
v[11] = k_Blake2s_IV[3];
|
||
|
|
||
|
v[12] = p->t[0] ^ k_Blake2s_IV[4];
|
||
|
v[13] = p->t[1] ^ k_Blake2s_IV[5];
|
||
|
v[14] = p->f[0] ^ k_Blake2s_IV[6];
|
||
|
v[15] = p->f[1] ^ k_Blake2s_IV[7];
|
||
|
|
||
|
#define G(r,i,a,b,c,d) \
|
||
|
a += b + m[sigma[2*i+0]]; d ^= a; d = rotr32(d, 16); c += d; b ^= c; b = rotr32(b, 12); \
|
||
|
a += b + m[sigma[2*i+1]]; d ^= a; d = rotr32(d, 8); c += d; b ^= c; b = rotr32(b, 7); \
|
||
|
|
||
|
#define R(r) \
|
||
|
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
|
||
|
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
|
||
|
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
|
||
|
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
|
||
|
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
|
||
|
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
|
||
|
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
|
||
|
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
|
||
|
|
||
|
{
|
||
|
unsigned r;
|
||
|
for (r = 0; r < BLAKE2S_NUM_ROUNDS; r++)
|
||
|
{
|
||
|
const Byte *sigma = k_Blake2s_Sigma[r];
|
||
|
R(r);
|
||
|
}
|
||
|
/* R(0); R(1); R(2); R(3); R(4); R(5); R(6); R(7); R(8); R(9); */
|
||
|
}
|
||
|
|
||
|
#undef G
|
||
|
#undef R
|
||
|
|
||
|
{
|
||
|
unsigned i;
|
||
|
for (i = 0; i < 8; i++)
|
||
|
p->h[i] ^= v[i] ^ v[i + 8];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#define Blake2s_Increment_Counter(S, inc) \
|
||
|
{ p->t[0] += (inc); p->t[1] += (p->t[0] < (inc)); }
|
||
|
|
||
|
#define Blake2s_Set_LastBlock(p) \
|
||
|
{ p->f[0] = BLAKE2S_FINAL_FLAG; p->f[1] = p->lastNode_f1; }
|
||
|
|
||
|
|
||
|
static void Blake2s_Update(CBlake2s *p, const Byte *data, size_t size)
|
||
|
{
|
||
|
while (size != 0)
|
||
|
{
|
||
|
unsigned pos = (unsigned)p->bufPos;
|
||
|
unsigned rem = BLAKE2S_BLOCK_SIZE - pos;
|
||
|
|
||
|
if (size <= rem)
|
||
|
{
|
||
|
memcpy(p->buf + pos, data, size);
|
||
|
p->bufPos += (UInt32)size;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
memcpy(p->buf + pos, data, rem);
|
||
|
Blake2s_Increment_Counter(S, BLAKE2S_BLOCK_SIZE);
|
||
|
Blake2s_Compress(p);
|
||
|
p->bufPos = 0;
|
||
|
data += rem;
|
||
|
size -= rem;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
static void Blake2s_Final(CBlake2s *p, Byte *digest)
|
||
|
{
|
||
|
unsigned i;
|
||
|
|
||
|
Blake2s_Increment_Counter(S, (UInt32)p->bufPos);
|
||
|
Blake2s_Set_LastBlock(p);
|
||
|
memset(p->buf + p->bufPos, 0, BLAKE2S_BLOCK_SIZE - p->bufPos);
|
||
|
Blake2s_Compress(p);
|
||
|
|
||
|
for (i = 0; i < 8; i++)
|
||
|
SetUi32(digest + sizeof(p->h[i]) * i, p->h[i]);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* ---------- BLAKE2s ---------- */
|
||
|
|
||
|
/* we need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0() */
|
||
|
/*
|
||
|
typedef struct
|
||
|
{
|
||
|
Byte digest_length;
|
||
|
Byte key_length;
|
||
|
Byte fanout;
|
||
|
Byte depth;
|
||
|
UInt32 leaf_length;
|
||
|
Byte node_offset[6];
|
||
|
Byte node_depth;
|
||
|
Byte inner_length;
|
||
|
Byte salt[BLAKE2S_SALTBYTES];
|
||
|
Byte personal[BLAKE2S_PERSONALBYTES];
|
||
|
} CBlake2sParam;
|
||
|
*/
|
||
|
|
||
|
|
||
|
static void Blake2sp_Init_Spec(CBlake2s *p, unsigned node_offset, unsigned node_depth)
|
||
|
{
|
||
|
Blake2s_Init0(p);
|
||
|
|
||
|
p->h[0] ^= (BLAKE2S_DIGEST_SIZE | ((UInt32)BLAKE2SP_PARALLEL_DEGREE << 16) | ((UInt32)2 << 24));
|
||
|
p->h[2] ^= ((UInt32)node_offset);
|
||
|
p->h[3] ^= ((UInt32)node_depth << 16) | ((UInt32)BLAKE2S_DIGEST_SIZE << 24);
|
||
|
/*
|
||
|
P->digest_length = BLAKE2S_DIGEST_SIZE;
|
||
|
P->key_length = 0;
|
||
|
P->fanout = BLAKE2SP_PARALLEL_DEGREE;
|
||
|
P->depth = 2;
|
||
|
P->leaf_length = 0;
|
||
|
store48(P->node_offset, node_offset);
|
||
|
P->node_depth = node_depth;
|
||
|
P->inner_length = BLAKE2S_DIGEST_SIZE;
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
|
||
|
void Blake2sp_Init(CBlake2sp *p)
|
||
|
{
|
||
|
unsigned i;
|
||
|
|
||
|
p->bufPos = 0;
|
||
|
|
||
|
for (i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++)
|
||
|
Blake2sp_Init_Spec(&p->S[i], i, 0);
|
||
|
|
||
|
p->S[BLAKE2SP_PARALLEL_DEGREE - 1].lastNode_f1 = BLAKE2S_FINAL_FLAG;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size)
|
||
|
{
|
||
|
unsigned pos = p->bufPos;
|
||
|
while (size != 0)
|
||
|
{
|
||
|
unsigned index = pos / BLAKE2S_BLOCK_SIZE;
|
||
|
unsigned rem = BLAKE2S_BLOCK_SIZE - (pos & (BLAKE2S_BLOCK_SIZE - 1));
|
||
|
if (rem > size)
|
||
|
rem = (unsigned)size;
|
||
|
Blake2s_Update(&p->S[index], data, rem);
|
||
|
size -= rem;
|
||
|
data += rem;
|
||
|
pos += rem;
|
||
|
pos &= (BLAKE2S_BLOCK_SIZE * BLAKE2SP_PARALLEL_DEGREE - 1);
|
||
|
}
|
||
|
p->bufPos = pos;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Blake2sp_Final(CBlake2sp *p, Byte *digest)
|
||
|
{
|
||
|
CBlake2s R;
|
||
|
unsigned i;
|
||
|
|
||
|
Blake2sp_Init_Spec(&R, 0, 1);
|
||
|
R.lastNode_f1 = BLAKE2S_FINAL_FLAG;
|
||
|
|
||
|
for (i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++)
|
||
|
{
|
||
|
Byte hash[BLAKE2S_DIGEST_SIZE];
|
||
|
Blake2s_Final(&p->S[i], hash);
|
||
|
Blake2s_Update(&R, hash, BLAKE2S_DIGEST_SIZE);
|
||
|
}
|
||
|
|
||
|
Blake2s_Final(&R, digest);
|
||
|
}
|