mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
ADD: BLAKE2BP hash function
This commit is contained in:
parent
9d22572504
commit
34632b8556
3 changed files with 498 additions and 16 deletions
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
|
||||
|
||||
Pascal tranlastion in 2014-2015 by Alexander Koblov (alexx2000@mail.ru)
|
||||
Pascal tranlastion in 2014-2018 by Alexander Koblov (alexx2000@mail.ru)
|
||||
|
||||
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
|
||||
|
|
@ -25,12 +25,20 @@ uses
|
|||
SysUtils, CTypes;
|
||||
|
||||
const
|
||||
PARALLELISM_DEGREE = 8;
|
||||
BLAKE2S_BLOCKBYTES = 64;
|
||||
BLAKE2S_OUTBYTES = 32;
|
||||
BLAKE2S_KEYBYTES = 32;
|
||||
BLAKE2S_SALTBYTES = 8;
|
||||
BLAKE2S_PERSONALBYTES = 8;
|
||||
BLAKE2S_PARALLELISM_DEGREE = 8;
|
||||
|
||||
const
|
||||
BLAKE2B_BLOCKBYTES = 128;
|
||||
BLAKE2B_OUTBYTES = 64;
|
||||
BLAKE2B_KEYBYTES = 64;
|
||||
BLAKE2B_SALTBYTES = 16;
|
||||
BLAKE2B_PERSONALBYTES = 16;
|
||||
BLAKE2B_PARALLELISM_DEGREE = 4;
|
||||
|
||||
type
|
||||
{$packrecords 1}
|
||||
|
|
@ -69,6 +77,43 @@ type
|
|||
inp: PByte;
|
||||
end;
|
||||
{$packrecords default}
|
||||
Pblake2b_state = ^blake2b_state;
|
||||
blake2b_state = record
|
||||
h: array[0..7] of cuint64;
|
||||
t: array[0..1] of cuint64;
|
||||
f: array[0..1] of cuint64;
|
||||
buf: array [0..Pred(BLAKE2B_BLOCKBYTES)] of cuint8;
|
||||
buflen: csize_t;
|
||||
outlen: csize_t;
|
||||
last_node: cuint8;
|
||||
end;
|
||||
{$packrecords 1}
|
||||
Pblake2b_param = ^blake2b_param;
|
||||
blake2b_param = record
|
||||
digest_length: uint8; // 1
|
||||
key_length: cuint8; // 2
|
||||
fanout: cuint8; // 3
|
||||
depth: cuint8; // 4
|
||||
leaf_length: cuint32; // 8
|
||||
node_offset: cuint32; // 12
|
||||
xof_length: cuint32; // 16
|
||||
node_depth: cuint8; // 17
|
||||
inner_length: cuint8; // 18
|
||||
reserved: array[0..13] of cuint8; // 32
|
||||
salt: array [0..Pred(BLAKE2B_SALTBYTES)] of cuint8; // 48
|
||||
personal: array[0..Pred(BLAKE2B_PERSONALBYTES)] of cuint8; // 64
|
||||
end;
|
||||
{$packrecords default}
|
||||
Pblake2bp_state = ^blake2bp_state;
|
||||
blake2bp_state = record
|
||||
S: array[0..3] of blake2b_state;
|
||||
R: blake2b_state;
|
||||
buf: array[0..Pred(4 * BLAKE2B_BLOCKBYTES)] of cuint8;
|
||||
buflen: csize_t;
|
||||
outlen: csize_t;
|
||||
inlen: csize_t;
|
||||
inp: PByte;
|
||||
end;
|
||||
|
||||
function blake2s_init( S: Pblake2s_state; const outlen: cuint8 ): cint;
|
||||
function blake2s_update( S: Pblake2s_state; inp: pcuint8; inlen: cuint64 ): cint;
|
||||
|
|
@ -78,6 +123,14 @@ function blake2sp_init( S: Pblake2sp_state; const outlen: cuint8 ): cint;
|
|||
function blake2sp_update( S: Pblake2sp_state; inp: pcuint8; inlen: cuint64 ): cint;
|
||||
function blake2sp_final( S: Pblake2sp_state; outp: pcuint8; const outlen: cuint8 ): cint;
|
||||
|
||||
function blake2b_init( S: Pblake2b_state; outlen: csize_t ): cint;
|
||||
function blake2b_update( S: Pblake2b_state; pin: pcuint8; inlen: csize_t ): cint;
|
||||
function blake2b_final( S: Pblake2b_state; pout: pcuint8; outlen: csize_t ): cint;
|
||||
|
||||
function blake2bp_init( S: Pblake2bp_state; outlen: csize_t ): cint;
|
||||
function blake2bp_update( S: Pblake2bp_state; inp: pcuint8; inlen: csize_t ): cint;
|
||||
function blake2bp_final( S: Pblake2bp_state; out_: PByte; outlen: csize_t ): cint;
|
||||
|
||||
implementation
|
||||
|
||||
{$IF DEFINED(USE_MTPROCS)}
|
||||
|
|
@ -94,6 +147,30 @@ const blake2s_IV: array[0..7] of cuint32 =
|
|||
$510E527F, $9B05688C, $1F83D9AB, $5BE0CD19
|
||||
);
|
||||
|
||||
const blake2b_IV: array[0..7] of cint64 =
|
||||
(
|
||||
$6a09e667f3bcc908, $bb67ae8584caa73b,
|
||||
$3c6ef372fe94f82b, $a54ff53a5f1d36f1,
|
||||
$510e527fade682d1, $9b05688c2b3e6c1f,
|
||||
$1f83d9abfb41bd6b, $5be0cd19137e2179
|
||||
);
|
||||
|
||||
const blake2b_sigma: array[0..11] of array[0..15] of cuint8 =
|
||||
(
|
||||
( 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 )
|
||||
);
|
||||
|
||||
function load32( const src: Pointer ): cuint32; inline;
|
||||
begin
|
||||
Result := NtoLE(pcuint32(src)^);
|
||||
|
|
@ -297,7 +374,7 @@ var
|
|||
begin
|
||||
P.digest_length := outlen;
|
||||
P.key_length := keylen;
|
||||
P.fanout := PARALLELISM_DEGREE;
|
||||
P.fanout := BLAKE2S_PARALLELISM_DEGREE;
|
||||
P.depth := 2;
|
||||
store32( @P.leaf_length, 0 );
|
||||
store48( @P.node_offset[0], offset );
|
||||
|
|
@ -314,7 +391,7 @@ var
|
|||
begin
|
||||
P.digest_length := outlen;
|
||||
P.key_length := keylen;
|
||||
P.fanout := PARALLELISM_DEGREE;
|
||||
P.fanout := BLAKE2S_PARALLELISM_DEGREE;
|
||||
P.depth := 2;
|
||||
store32( @P.leaf_length, 0 );
|
||||
store48( @P.node_offset[0], 0 );
|
||||
|
|
@ -336,11 +413,11 @@ begin
|
|||
|
||||
if( blake2sp_init_root( @S^.R, outlen, 0 ) < 0 ) then Exit(-1);
|
||||
|
||||
for i := 0 to PARALLELISM_DEGREE - 1 do
|
||||
for i := 0 to BLAKE2S_PARALLELISM_DEGREE - 1 do
|
||||
if ( blake2sp_init_leaf( @S^.S[i], outlen, 0, i ) < 0 ) then Exit(-1);
|
||||
|
||||
S^.R.last_node := 1;
|
||||
S^.S[PARALLELISM_DEGREE - 1].last_node := 1;
|
||||
S^.S[BLAKE2S_PARALLELISM_DEGREE - 1].last_node := 1;
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
|
|
@ -354,11 +431,11 @@ begin
|
|||
inlen__ := S^.inlen;
|
||||
in__ += id__ * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
while ( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ) do
|
||||
while ( inlen__ >= BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ) do
|
||||
begin
|
||||
blake2s_update( @S^.S[id__], in__, BLAKE2S_BLOCKBYTES );
|
||||
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
in__ += BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
inlen__ -= BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
@ -373,7 +450,7 @@ begin
|
|||
begin
|
||||
Move(inp^, S^.buf[left], fill);
|
||||
|
||||
for i := 0 to PARALLELISM_DEGREE - 1 do
|
||||
for i := 0 to BLAKE2S_PARALLELISM_DEGREE - 1 do
|
||||
blake2s_update( @S^.S[i], @S^.buf[ i * BLAKE2S_BLOCKBYTES], BLAKE2S_BLOCKBYTES );
|
||||
|
||||
inp += fill;
|
||||
|
|
@ -385,13 +462,13 @@ begin
|
|||
S^.inlen := inlen;
|
||||
|
||||
{$IF DEFINED(USE_MTPROCS)}
|
||||
ProcThreadPool.DoParallel(@MTProcedure, 0, PARALLELISM_DEGREE - 1, S);
|
||||
ProcThreadPool.DoParallel(@MTProcedure, 0, BLAKE2S_PARALLELISM_DEGREE - 1, S);
|
||||
{$ELSE}
|
||||
for i := 0 to PARALLELISM_DEGREE - 1 do MTProcedure(i, S, nil);
|
||||
{$ENDIF}
|
||||
|
||||
inp += inlen - inlen mod ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
|
||||
inlen := inlen mod (PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES);
|
||||
inp += inlen - inlen mod ( BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
|
||||
inlen := inlen mod (BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES);
|
||||
|
||||
if ( inlen > 0 ) then
|
||||
Move(inp^, S^.buf[left], inlen );
|
||||
|
|
@ -403,10 +480,10 @@ end;
|
|||
function blake2sp_final( S: Pblake2sp_state; outp: pcuint8; const outlen: cuint8 ): cint;
|
||||
var
|
||||
i, left: csize_t;
|
||||
hash: array[0..Pred(PARALLELISM_DEGREE), 0..Pred(BLAKE2S_OUTBYTES)] of cuint8;
|
||||
hash: array[0..Pred(BLAKE2S_PARALLELISM_DEGREE), 0..Pred(BLAKE2S_OUTBYTES)] of cuint8;
|
||||
begin
|
||||
|
||||
for i := 0 to PARALLELISM_DEGREE - 1 do
|
||||
for i := 0 to BLAKE2S_PARALLELISM_DEGREE - 1 do
|
||||
begin
|
||||
if ( S^.buflen > i * BLAKE2S_BLOCKBYTES ) then
|
||||
begin
|
||||
|
|
@ -420,11 +497,347 @@ begin
|
|||
blake2s_final( @S^.S[i], hash[i], BLAKE2S_OUTBYTES );
|
||||
end;
|
||||
|
||||
for i := 0 to PARALLELISM_DEGREE - 1 do
|
||||
for i := 0 to BLAKE2S_PARALLELISM_DEGREE - 1 do
|
||||
blake2s_update( @S^.R, hash[i], BLAKE2S_OUTBYTES );
|
||||
|
||||
blake2s_final( @S^.R, outp, outlen );
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
procedure blake2b_set_lastnode( S: Pblake2b_state ); inline;
|
||||
begin
|
||||
S^.f[1] := cuint64(-1);
|
||||
end;
|
||||
|
||||
//* Some helper functions, not necessarily useful */
|
||||
function blake2b_is_lastblock( S: Pblake2b_state ): cint; inline;
|
||||
begin
|
||||
Result := cint(S^.f[0] <> 0);
|
||||
end;
|
||||
|
||||
procedure blake2b_set_lastblock( S: Pblake2b_state );
|
||||
begin
|
||||
if( S^.last_node <> 0 ) then blake2b_set_lastnode( S );
|
||||
|
||||
S^.f[0] := cuint64(-1);
|
||||
end;
|
||||
|
||||
procedure blake2b_increment_counter( S: Pblake2b_state; const inc: cuint64 );
|
||||
begin
|
||||
S^.t[0] += inc;
|
||||
S^.t[1] += cuint64( S^.t[0] < inc );
|
||||
end;
|
||||
|
||||
procedure blake2b_init0( S: Pblake2b_state );
|
||||
var
|
||||
i: csize_t;
|
||||
begin
|
||||
fillchar( S^, sizeof( blake2b_state ), 0 );
|
||||
|
||||
for i := 0 to 7 do S^.h[i] := cuint64(blake2b_IV[i]);
|
||||
end;
|
||||
|
||||
//* init xors IV with input parameter block */
|
||||
function blake2b_init_param( S: Pblake2b_state; const P: Pblake2b_param ): cint;
|
||||
var
|
||||
i: csize_t;
|
||||
pp: pcuint8;
|
||||
begin
|
||||
pp := pcuint8( P );
|
||||
|
||||
blake2b_init0( S );
|
||||
|
||||
//* IV XOR ParamBlock */
|
||||
for i := 0 to 7 do
|
||||
S^.h[i] := S^.h[i] xor load64( pp + sizeof( S^.h[i] ) * i );
|
||||
|
||||
S^.outlen := P^.digest_length;
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function blake2b_init( S: Pblake2b_state; outlen: csize_t ): cint;
|
||||
var
|
||||
P: blake2b_param;
|
||||
begin
|
||||
if ( ( outlen = 0 ) or ( outlen > BLAKE2B_OUTBYTES ) ) then Exit(-1);
|
||||
|
||||
P.digest_length := cuint8(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;
|
||||
fillchar( P.reserved, sizeof( P.reserved ), 0 );
|
||||
fillchar( P.salt, sizeof( P.salt ), 0 );
|
||||
fillchar( P.personal, sizeof( P.personal ), 0 );
|
||||
Result := blake2b_init_param( S, @P );
|
||||
end;
|
||||
|
||||
procedure blake2b_compress( S: Pblake2b_state; const block: pcuint8 );
|
||||
var
|
||||
i: csize_t;
|
||||
m: array[0..15] of cuint64;
|
||||
v: array[0..15] of cuint64;
|
||||
|
||||
procedure G( r, i: cuint64; var a, b, c, d: cuint64 ); inline;
|
||||
begin
|
||||
a := a + b + m[blake2b_sigma[r][2 * i + 0]];
|
||||
d := RorQWord(d xor a, 32);
|
||||
c := c + d;
|
||||
b := RorQWord(b xor c, 24);
|
||||
a := a + b + m[blake2b_sigma[r][2 * i + 1]];
|
||||
d := RorQWord(d xor a, 16);
|
||||
c := c + d;
|
||||
b := RorQWord(b xor c, 63);
|
||||
end;
|
||||
|
||||
{$define ROUND_MACRO:=
|
||||
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]);
|
||||
}
|
||||
|
||||
begin
|
||||
for i := 0 to 15 do
|
||||
m[i] := load64( block + i * sizeof( m[i] ) );
|
||||
|
||||
for i := 0 to 7 do
|
||||
v[i] := S^.h[i];
|
||||
|
||||
v[ 8] := cuint64(blake2b_IV[0]);
|
||||
v[ 9] := cuint64(blake2b_IV[1]);
|
||||
v[10] := cuint64(blake2b_IV[2]);
|
||||
v[11] := cuint64(blake2b_IV[3]);
|
||||
v[12] := cuint64(blake2b_IV[4] xor S^.t[0]);
|
||||
v[13] := cuint64(blake2b_IV[5] xor S^.t[1]);
|
||||
v[14] := cuint64(blake2b_IV[6] xor S^.f[0]);
|
||||
v[15] := cuint64(blake2b_IV[7] xor S^.f[1]);
|
||||
|
||||
{$define r_:= 0} ROUND_MACRO;
|
||||
{$define r_:= 1} ROUND_MACRO;
|
||||
{$define r_:= 2} ROUND_MACRO;
|
||||
{$define r_:= 3} ROUND_MACRO;
|
||||
{$define r_:= 4} ROUND_MACRO;
|
||||
{$define r_:= 5} ROUND_MACRO;
|
||||
{$define r_:= 6} ROUND_MACRO;
|
||||
{$define r_:= 7} ROUND_MACRO;
|
||||
{$define r_:= 8} ROUND_MACRO;
|
||||
{$define r_:= 9} ROUND_MACRO;
|
||||
{$define r_:= 10} ROUND_MACRO;
|
||||
{$define r_:= 11} ROUND_MACRO;
|
||||
|
||||
for i := 0 to 7 do
|
||||
S^.h[i] := S^.h[i] xor v[i] xor v[i + 8];
|
||||
end;
|
||||
|
||||
function blake2b_update( S: Pblake2b_state; pin: pcuint8; inlen: csize_t ): cint;
|
||||
var
|
||||
left, fill: csize_t;
|
||||
begin
|
||||
if ( inlen > 0 ) then
|
||||
begin
|
||||
left := S^.buflen;
|
||||
fill := BLAKE2B_BLOCKBYTES - left;
|
||||
if ( inlen > fill ) then
|
||||
begin
|
||||
S^.buflen := 0;
|
||||
Move( pin^, S^.buf[left], fill ); //* Fill buffer */
|
||||
blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
|
||||
blake2b_compress( S, S^.buf ); //* Compress */
|
||||
pin += fill; inlen -= fill;
|
||||
while (inlen > BLAKE2B_BLOCKBYTES) do
|
||||
begin
|
||||
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
|
||||
blake2b_compress( S, pin );
|
||||
pin += BLAKE2B_BLOCKBYTES;
|
||||
inlen -= BLAKE2B_BLOCKBYTES;
|
||||
end
|
||||
end;
|
||||
Move( pin^, S^.buf[S^.buflen], inlen );
|
||||
S^.buflen += inlen;
|
||||
end;
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function blake2b_final( S: Pblake2b_state; pout: pcuint8; outlen: csize_t ): cint;
|
||||
var
|
||||
i: csize_t;
|
||||
buffer: array[0..Pred(BLAKE2B_OUTBYTES)] of cuint8;
|
||||
begin
|
||||
if( pout = nil) or (outlen < S^.outlen ) then
|
||||
Exit(-1);
|
||||
|
||||
if ( blake2b_is_lastblock( S ) <> 0 ) then
|
||||
Exit(-1);
|
||||
|
||||
fillchar(buffer[0], BLAKE2B_OUTBYTES, 0);
|
||||
blake2b_increment_counter( S, S^.buflen );
|
||||
blake2b_set_lastblock( S );
|
||||
fillchar( S^.buf[S^.buflen], BLAKE2B_BLOCKBYTES - S^.buflen, 0 ); //* Padding */
|
||||
blake2b_compress( S, S^.buf );
|
||||
|
||||
for i := 0 to 7 do //* Output full hash to temp buffer */
|
||||
store64( @buffer[sizeof( S^.h[i] ) * i], S^.h[i] );
|
||||
|
||||
move( buffer[0], pout^, S^.outlen );
|
||||
fillchar(buffer[0], sizeof(buffer), 0);
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function blake2bp_init_leaf_param( S: Pblake2b_state; const P: Pblake2b_param ): cint;
|
||||
begin
|
||||
Result:= blake2b_init_param(S, P);
|
||||
S^.outlen := P^.inner_length;
|
||||
end;
|
||||
|
||||
function blake2bp_init_leaf( S: Pblake2b_state; outlen, keylen: csize_t; offset: cuint64 ): cint;
|
||||
var
|
||||
P: blake2b_param;
|
||||
begin
|
||||
P.digest_length := cuint8(outlen);
|
||||
P.key_length := cuint8(keylen);
|
||||
P.fanout := BLAKE2B_PARALLELISM_DEGREE;
|
||||
P.depth := 2;
|
||||
store32( @P.leaf_length, 0 );
|
||||
store32( @P.node_offset, offset );
|
||||
store32( @P.xof_length, 0 );
|
||||
P.node_depth := 0;
|
||||
P.inner_length := BLAKE2B_OUTBYTES;
|
||||
FillChar( P.reserved[0], sizeof( P.reserved ), 0 );
|
||||
FillChar( P.salt[0], sizeof( P.salt ), 0 );
|
||||
FillChar( P.personal[0], sizeof( P.personal ), 0 );
|
||||
Result:= blake2bp_init_leaf_param( S, @P );
|
||||
end;
|
||||
|
||||
function blake2bp_init_root( S: Pblake2b_state; outlen, keylen: csize_t ): cint;
|
||||
var
|
||||
P: blake2b_param;
|
||||
begin
|
||||
P.digest_length := cuint8(outlen);
|
||||
P.key_length := cuint8(keylen);
|
||||
P.fanout := BLAKE2B_PARALLELISM_DEGREE;
|
||||
P.depth := 2;
|
||||
store32( @P.leaf_length, 0 );
|
||||
store32( @P.node_offset, 0 );
|
||||
store32( @P.xof_length, 0 );
|
||||
P.node_depth := 1;
|
||||
P.inner_length := BLAKE2B_OUTBYTES;
|
||||
FillChar( P.reserved[0], sizeof( P.reserved ), 0 );
|
||||
FillChar( P.salt[0], sizeof( P.salt ), 0 );
|
||||
FillChar( P.personal[0], sizeof( P.personal ), 0 );
|
||||
Result:= blake2b_init_param( S, @P );
|
||||
end;
|
||||
|
||||
function blake2bp_init( S: Pblake2bp_state; outlen: csize_t ): cint;
|
||||
var
|
||||
i: csize_t;
|
||||
begin
|
||||
if (outlen = 0) or (outlen > BLAKE2B_OUTBYTES) then Exit(-1);
|
||||
|
||||
FillChar( S^.buf[0], sizeof( S^.buf ), 0 );
|
||||
S^.buflen := 0;
|
||||
S^.outlen := outlen;
|
||||
|
||||
if( blake2bp_init_root( @S^.R, outlen, 0 ) < 0 ) then
|
||||
Exit(-1);
|
||||
|
||||
for i := 0 to BLAKE2B_PARALLELISM_DEGREE - 1 do
|
||||
if ( blake2bp_init_leaf( @S^.S[i], outlen, 0, i ) < 0 ) then Exit(-1);
|
||||
|
||||
S^.R.last_node := 1;
|
||||
S^.S[BLAKE2B_PARALLELISM_DEGREE - 1].last_node := 1;
|
||||
Result:= 0;
|
||||
end;
|
||||
|
||||
procedure blake2bp_MTProcedure(i: PtrInt; Data: Pointer; Item: TMultiThreadProcItem);
|
||||
var
|
||||
in__: pcuint8;
|
||||
inlen__: cuint64;
|
||||
S: Pblake2bp_state absolute Data;
|
||||
begin
|
||||
in__ := S^.inp;
|
||||
inlen__ := S^.inlen;
|
||||
in__ += i * BLAKE2B_BLOCKBYTES;
|
||||
|
||||
while ( inlen__ >= BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES ) do
|
||||
begin
|
||||
blake2b_update( @S^.S[i], in__, BLAKE2B_BLOCKBYTES );
|
||||
in__ += BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||
inlen__ -= BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||
end;
|
||||
end;
|
||||
|
||||
function blake2bp_update( S: Pblake2bp_state; inp: pcuint8; inlen: csize_t ): cint;
|
||||
var
|
||||
left, fill, i: csize_t;
|
||||
begin
|
||||
left := S^.buflen;
|
||||
fill := sizeof( S^.buf ) - left;
|
||||
|
||||
if( left > 0) and (inlen >= fill ) then
|
||||
begin
|
||||
Move( inp^, S^.buf[left], fill );
|
||||
|
||||
for i := 0 to BLAKE2B_PARALLELISM_DEGREE - 1 do
|
||||
blake2b_update( @S^.S[i], @S^.buf[i * BLAKE2B_BLOCKBYTES], BLAKE2B_BLOCKBYTES );
|
||||
|
||||
inp += fill;
|
||||
inlen -= fill;
|
||||
left := 0;
|
||||
end;
|
||||
|
||||
S^.inp := inp;
|
||||
S^.inlen := inlen;
|
||||
|
||||
{$IF DEFINED(USE_MTPROCS)}
|
||||
ProcThreadPool.DoParallel(@blake2bp_MTProcedure, 0, BLAKE2B_PARALLELISM_DEGREE - 1, S);
|
||||
{$ELSE}
|
||||
for i := 0 to BLAKE2B_PARALLELISM_DEGREE - 1 do blake2bp_MTProcedure(i, S, nil);
|
||||
{$ENDIF}
|
||||
|
||||
inp += inlen - inlen mod ( BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES );
|
||||
inlen := inlen mod (BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES);
|
||||
|
||||
if ( inlen > 0 ) then
|
||||
Move( inp^, S^.buf[left], inlen );
|
||||
|
||||
S^.buflen := left + inlen;
|
||||
Result:= 0;
|
||||
end;
|
||||
|
||||
function blake2bp_final( S: Pblake2bp_state; out_: PByte; outlen: csize_t ): cint;
|
||||
var
|
||||
i, left: csize_t;
|
||||
hash: array[0..Pred(BLAKE2B_PARALLELISM_DEGREE), 0..Pred(BLAKE2B_OUTBYTES)] of cuint8;
|
||||
begin
|
||||
if (out_ = nil) or (outlen < S^.outlen) then Exit(-1);
|
||||
|
||||
for i := 0 to BLAKE2B_PARALLELISM_DEGREE - 1 do
|
||||
begin
|
||||
if ( S^.buflen > i * BLAKE2B_BLOCKBYTES ) then
|
||||
begin
|
||||
left := S^.buflen - i * BLAKE2B_BLOCKBYTES;
|
||||
|
||||
if ( left > BLAKE2B_BLOCKBYTES ) then left := BLAKE2B_BLOCKBYTES;
|
||||
|
||||
blake2b_update( @S^.S[i], @S^.buf[i * BLAKE2B_BLOCKBYTES], left );
|
||||
end;
|
||||
|
||||
blake2b_final( @S^.S[i], hash[i], BLAKE2B_OUTBYTES );
|
||||
end;
|
||||
|
||||
for i := 0 to BLAKE2B_PARALLELISM_DEGREE -1 do
|
||||
blake2b_update( @S^.R, hash[i], BLAKE2B_OUTBYTES );
|
||||
|
||||
Result:= blake2b_final( @S^.R, out_, S^.outlen );
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -81,6 +81,22 @@ type
|
|||
procedure Final(var Digest); override;
|
||||
end;
|
||||
|
||||
{ TDCP_blake2bp }
|
||||
|
||||
TDCP_blake2bp = class(TDCP_hash)
|
||||
protected
|
||||
S: blake2bp_state;
|
||||
public
|
||||
class function GetId: integer; override;
|
||||
class function GetAlgorithm: string; override;
|
||||
class function GetHashSize: integer; override;
|
||||
class function SelfTest: boolean; override;
|
||||
procedure Init; override;
|
||||
procedure Burn; override;
|
||||
procedure Update(const Buffer; Size: longword); override;
|
||||
procedure Final(var Digest); override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TDCP_blake2s }
|
||||
|
|
@ -283,5 +299,57 @@ begin
|
|||
Burn;
|
||||
end;
|
||||
|
||||
{ TDCP_blake2bp }
|
||||
|
||||
class function TDCP_blake2bp.GetId: integer;
|
||||
begin
|
||||
Result:= DCP_blake2bp;
|
||||
end;
|
||||
|
||||
class function TDCP_blake2bp.GetAlgorithm: string;
|
||||
begin
|
||||
Result:= 'BLAKE2BP';
|
||||
end;
|
||||
|
||||
class function TDCP_blake2bp.GetHashSize: integer;
|
||||
begin
|
||||
Result:= 512;
|
||||
end;
|
||||
|
||||
class function TDCP_blake2bp.SelfTest: boolean;
|
||||
begin
|
||||
Result:= False;
|
||||
end;
|
||||
|
||||
procedure TDCP_blake2bp.Init;
|
||||
begin
|
||||
if blake2bp_init( @S, BLAKE2B_OUTBYTES ) < 0 then
|
||||
raise EDCP_hash.Create('blake2bp_init');
|
||||
fInitialized:= true;
|
||||
end;
|
||||
|
||||
procedure TDCP_blake2bp.Burn;
|
||||
begin
|
||||
fInitialized:= false;
|
||||
end;
|
||||
|
||||
procedure TDCP_blake2bp.Update(const Buffer; Size: longword);
|
||||
begin
|
||||
if blake2bp_update(@S, @Buffer, Size) < 0 then
|
||||
raise EDCP_hash.Create('blake2bp_update');
|
||||
end;
|
||||
|
||||
procedure TDCP_blake2bp.Final(var Digest);
|
||||
var
|
||||
Hash: array[0..Pred(BLAKE2B_OUTBYTES)] of cuint8;
|
||||
begin
|
||||
if not fInitialized then
|
||||
raise EDCP_hash.Create('Hash not initialized');
|
||||
if blake2bp_final(@S, Hash, SizeOf(Hash)) < 0 then
|
||||
raise EDCP_hash.Create('blake2bp_final');
|
||||
Move(Hash, Digest, Sizeof(Hash));
|
||||
Burn;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ const
|
|||
DCP_sha256 = 28;
|
||||
DCP_sha384 = 29;
|
||||
DCP_sha512 = 30;
|
||||
DCP_blake2bp = 95;
|
||||
DCP_blake2b = 96;
|
||||
DCP_blake2s = 97;
|
||||
DCP_blake2sp = 98;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue