DEL: Unused unit

This commit is contained in:
Alexander Koblov 2018-06-10 15:10:02 +00:00
commit 970f0ecf59

View file

@ -1,982 +0,0 @@
unit blake2b;
{Blake2B - max 512 bit hash/MAC function}
interface
(*************************************************************************
DESCRIPTION : Blake2B - max 512 bit hash/MAC function
REQUIREMENTS : TP6/7, D1-D7/D9-D10/D12/D17-D18/D25S, FPC, VP
EXTERNAL DATA : ---
MEMORY USAGE : ---
DISPLAY MODE : ---
REFERENCES : - Saarinen et al: The BLAKE2 Cryptographic Hash and Message
Authentication Code (MAC); https://tools.ietf.org/html/rfc7693
- Aumasson et al: BLAKE2: simpler, smaller, fast as MD5;
https://blake2.net/blake2.pdf
- Official reference code: https://github.com/BLAKE2/BLAKE2
Version Date Author Modification
------- -------- ------- ------------------------------------------
0.10 06.10.17 W.Ehrhardt Initial D6 implementation (from Blake2s / RFC code)
0.11 06.10.17 we removed updatelen, max input < 2^64
0.12 06.10.17 we FPC fix
0.13 06.10.17 we blake2b_selftest
0.14 06.10.17 we used int64 instead of u64
0.15 07.10.17 we unroll compress loop for Delphi
0.16 07.10.17 we adjust/assert context size
0.17 03.11.17 we Use THashContext and internal blake2b_ctx
0.18 04.11.17 we Dummy functions for TP5-7, D1-D3, IV with longints
0.19 05.11.17 we Some commpn code for 64 and 16/32 bit
0.20 05.11.17 we 32-Bit BASM
0.21 05.11.17 we 16-Bit BASM
0.22 21.11.14 eh Faster blake2b_compress routines from EddyHawk
0.23 23.11.14 we Replace RotR(,16) with word moves for non-int64
0.24 24.11.14 we RotR63 with BASM
0.25 24.11.14 we RotR24 with byte move
0.26 24.11.14 we RotR63, Add64 for VER5X
**************************************************************************)
(*-------------------------------------------------------------------------
(C) Copyright 2017 Wolfgang Ehrhardt
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from
the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in
a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
----------------------------------------------------------------------------*)
{$i STD.INC}
uses
BTypes, Hash;
const
BLAKE2B_BlockLen = 128;
BLAKE2B_MaxDigLen = 64;
BLAKE2B_MaxKeyLen = 64;
type
TBlake2BDigest = packed array[0..BLAKE2B_MaxDigLen-1] of byte; {max. blake2b digest}
TBlake2BBlock = packed array[0..BLAKE2B_BlockLen-1] of byte;
function blake2b_Init(var ctx: THashContext; key: pointer; keylen, diglen: word): integer;
{-Initialize context for a digest of diglen bytes; keylen=0: no key}
procedure blake2b_update(var ctx: THashContext; msg: pointer; mlen: longint);
{-Add "mlen" bytes from "msg" into the hash}
procedure blake2b_Final(var ctx: THashContext; var Digest: TBlake2BDigest);
{-Finalize calculation, generate message digest, clear context}
function blake2b_full(var dig: TBlake2BDigest; diglen: word;
key: pointer; keylen: word;
msg: pointer; mlen: longint): integer;
{-Calculate hash digest of Msg with init/update/final}
function blake2b_selftest: boolean;
{-Return true, if self test is OK}
implementation
{The next comment is copy from blake2b-ref.c}
(*
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.
*)
{Initialization Vector, longints for compatibility}
const
blake2b_ivl: array[0..15] of longint = (
longint($F3BCC908), longint($6A09E667),
longint($84CAA73B), longint($BB67AE85),
longint($FE94F82B), longint($3C6EF372),
longint($5F1D36F1), longint($A54FF53A),
longint($ADE682D1), longint($510E527F),
longint($2B3E6C1F), longint($9B05688C),
longint($FB41BD6B), longint($1F83D9AB),
longint($137E2179), longint($5BE0CD19));
const
sigma: array[0..11,0..15] of byte = (
( 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 )
);
{$ifdef HAS_INT64}
type
blake2b_ctx = packed record
h: packed array[0..7] of int64;
t: packed array[0..1] of int64;
b: TBlake2BBlock;
c: longint;
outlen: longint;
fill4: packed array[217..HASHCTXSIZE] of byte;
end;
{---------------------------------------------------------------------------}
procedure blake2b_compress(var ctx: blake2b_ctx; last: boolean);
{- Compression function, "last" indicates last block}
var
v,m: array[0..15] of int64;
tem: int64;
round,k: integer;
begin
with ctx do begin
{init work variables}
move(h, v, sizeof(h));
move(blake2b_ivl, v[8], sizeof(h));
v[12] := v[12] xor t[0]; {low 64 bits of offset}
v[13] := v[13] xor t[1]; {high 64 bits}
if last then v[14] := not v[14]; {last block flag set}
{get little-endian words}
move(b, m, sizeof(m));
{do 12 rounds}
for round:=0 to 11 do begin
{** EddyHawk speed-ups **}
{use same rearrangements as blake2s' 32/64 bit code}
v[ 0] := (v[ 0] + v[ 4]) + m[sigma[round][ 0]];
v[ 1] := (v[ 1] + v[ 5]) + m[sigma[round][ 2]];
v[ 2] := (v[ 2] + v[ 6]) + m[sigma[round][ 4]];
v[ 3] := (v[ 3] + v[ 7]) + m[sigma[round][ 6]];
tem := v[12] xor v[ 0];
v[12] := (tem shr 32) or (tem shl (64-32));
tem := v[13] xor v[ 1];
v[13] := (tem shr 32) or (tem shl (64-32));
tem := v[14] xor v[ 2];
v[14] := (tem shr 32) or (tem shl (64-32));
tem := v[15] xor v[ 3];
v[15] := (tem shr 32) or (tem shl (64-32));
v[ 8] := v[ 8] + v[12];
v[ 9] := v[ 9] + v[13];
v[10] := v[10] + v[14];
v[11] := v[11] + v[15];
tem := v[ 4] xor v[ 8];
v[ 4] := (tem shr 24) or (tem shl (64-24));
tem := v[ 5] xor v[ 9];
v[ 5] := (tem shr 24) or (tem shl (64-24));
tem := v[ 6] xor v[10];
v[ 6] := (tem shr 24) or (tem shl (64-24));
tem := v[ 7] xor v[11];
v[ 7] := (tem shr 24) or (tem shl (64-24));
{---}
v[ 0] := (v[ 0] + v[ 4]) + m[sigma[round][ 1]];
v[ 1] := (v[ 1] + v[ 5]) + m[sigma[round][ 3]];
v[ 2] := (v[ 2] + v[ 6]) + m[sigma[round][ 5]];
v[ 3] := (v[ 3] + v[ 7]) + m[sigma[round][ 7]];
tem := v[12] xor v[ 0];
v[12] := (tem shr 16) or (tem shl (64-16));
tem := v[13] xor v[ 1];
v[13] := (tem shr 16) or (tem shl (64-16));
tem := v[14] xor v[ 2];
v[14] := (tem shr 16) or (tem shl (64-16));
tem := v[15] xor v[ 3];
v[15] := (tem shr 16) or (tem shl (64-16));
v[ 8] := v[ 8] + v[12];
v[ 9] := v[ 9] + v[13];
v[10] := v[10] + v[14];
v[11] := v[11] + v[15];
tem := v[ 4] xor v[ 8];
v[ 4] := (tem shr 63) or (tem shl (64-63));
tem := v[ 5] xor v[ 9];
v[ 5] := (tem shr 63) or (tem shl (64-63));
tem := v[ 6] xor v[10];
v[ 6] := (tem shr 63) or (tem shl (64-63));
tem := v[ 7] xor v[11];
v[ 7] := (tem shr 63) or (tem shl (64-63));
{---}
v[ 0] := (v[ 0] + v[ 5]) + m[sigma[round][ 8]];
v[ 1] := (v[ 1] + v[ 6]) + m[sigma[round][10]];
v[ 2] := (v[ 2] + v[ 7]) + m[sigma[round][12]];
v[ 3] := (v[ 3] + v[ 4]) + m[sigma[round][14]];
tem := v[15] xor v[ 0];
v[15] := (tem shr 32) or (tem shl (64-32));
tem := v[12] xor v[ 1];
v[12] := (tem shr 32) or (tem shl (64-32));
tem := v[13] xor v[ 2];
v[13] := (tem shr 32) or (tem shl (64-32));
tem := v[14] xor v[ 3];
v[14] := (tem shr 32) or (tem shl (64-32));
v[10] := v[10] + v[15];
v[11] := v[11] + v[12];
v[ 8] := v[ 8] + v[13];
v[ 9] := v[ 9] + v[14];
tem := v[ 5] xor v[10];
v[ 5] := (tem shr 24) or (tem shl (64-24));
tem := v[ 6] xor v[11];
v[ 6] := (tem shr 24) or (tem shl (64-24));
tem := v[ 7] xor v[ 8];
v[ 7] := (tem shr 24) or (tem shl (64-24));
tem := v[ 4] xor v[ 9];
v[ 4] := (tem shr 24) or (tem shl (64-24));
{---}
v[ 0] := (v[ 0] + v[ 5]) + m[sigma[round][ 9]];
v[ 1] := (v[ 1] + v[ 6]) + m[sigma[round][11]];
v[ 2] := (v[ 2] + v[ 7]) + m[sigma[round][13]];
v[ 3] := (v[ 3] + v[ 4]) + m[sigma[round][15]];
tem := v[15] xor v[ 0];
v[15] := (tem shr 16) or (tem shl (64-16));
tem := v[12] xor v[ 1];
v[12] := (tem shr 16) or (tem shl (64-16));
tem := v[13] xor v[ 2];
v[13] := (tem shr 16) or (tem shl (64-16));
tem := v[14] xor v[ 3];
v[14] := (tem shr 16) or (tem shl (64-16));
v[10] := v[10] + v[15];
v[11] := v[11] + v[12];
v[ 8] := v[ 8] + v[13];
v[ 9] := v[ 9] + v[14];
tem := v[ 5] xor v[10];
v[ 5] := (tem shr 63) or (tem shl (64-63));
tem := v[ 6] xor v[11];
v[ 6] := (tem shr 63) or (tem shl (64-63));
tem := v[ 7] xor v[ 8];
v[ 7] := (tem shr 63) or (tem shl (64-63));
tem := v[ 4] xor v[ 9];
v[ 4] := (tem shr 63) or (tem shl (64-63));
end;
{finalization}
for k:=0 to 7 do begin
h[k] := h[k] xor v[k] xor v[k+8];
end;
end;
end;
{---------------------------------------------------------------------------}
procedure blake2b_update(var ctx: THashContext; msg: pointer; mlen: longint);
{-Add "mlen" bytes from "msg" into the hash}
var
left,fill: integer;
begin
with blake2b_ctx(ctx) do begin
if mlen > 0 then begin
left := c;
fill := BLAKE2B_BlockLen - left;
if mlen > fill then begin
c := 0;
if fill>0 then move(msg^, b[left], fill);
t[0] := t[0] + BLAKE2B_BlockLen;
blake2b_compress(blake2b_ctx(ctx), false);
inc(Ptr2Inc(Msg),fill);
dec(mlen,fill);
while mlen > BLAKE2B_BlockLen do begin
move(msg^,b,BLAKE2B_BlockLen);
t[0] := t[0] + BLAKE2B_BlockLen;
blake2b_compress(blake2b_ctx(ctx), false); {compress (not last)}
inc(Ptr2Inc(Msg),BLAKE2B_BlockLen);
dec(mlen,BLAKE2B_BlockLen);
end;
end;
if mlen > 0 then begin
move(msg^, b[c], mlen);
c := c + mlen;
end;
end;
end;
end;
{---------------------------------------------------------------------------}
procedure blake2b_Final(var ctx: THashContext; var Digest: TBlake2BDigest);
{-Finalize calculation, generate message digest, clear context}
var
i: integer;
begin
with blake2b_ctx(ctx) do begin
t[0] := t[0] + c;
while c < BLAKE2B_BlockLen do begin {fill up with zeros}
b[c] := 0;
inc(c);
end;
blake2b_compress(blake2b_ctx(ctx), true); {final block}
{little endian convert and store}
fillchar(Digest, sizeof(Digest),0);
for i:=0 to outlen-1 do begin
Digest[i] := (h[i shr 3] shr (8*(i and 7))) and $FF;
end;
end;
end;
{$else}
type
blake2b_ctx = packed record
h: packed array[0..15] of longint;
t: packed array[0..3] of longint;
b: TBlake2BBlock;
c: longint;
outlen: longint;
fill4: packed array[217..HASHCTXSIZE] of byte;
end;
type
TW64 = packed record
L,H: longint;
end;
TW16 = packed record
w0,w1,w2,w3: word
end;
{$ifdef BIT16}
{$ifdef BASM}
{---------------------------------------------------------------------------}
procedure Add64(var z: TW64; {$ifdef CONST} const {$else} var {$endif} x: TW64); assembler;
{-Inc a 64 bit integer}
asm
les bx,[x]
db $66; mov ax,es:[bx]
db $66; mov dx,es:[bx+4]
les bx,[z]
db $66; add es:[bx],ax
db $66; adc es:[bx+4],dx
end;
{---------------------------------------------------------------------------}
procedure RotR63(var x: tw64);
{-Rotate right 63 bits = rotate left 1}
begin
asm
les bx,[x]
db $66; mov ax,es:[bx]
db $66; mov dx,es:[bx+4]
db $66; shl ax,1
db $66; rcl dx,1
adc ax,0
db $66; mov es:[bx],ax
db $66; mov es:[bx+4],dx
end;
end;
{$else}
{16-bit compilers without BASM}
{---------------------------------------------------------------------------}
procedure Add64(var Z: TW64; var X: TW64);
{-Inc a 64 bit integer}
inline(
$8C/$DF/ {mov di,ds }
$5E/ {pop si }
$1F/ {pop ds }
$8B/$04/ {mov ax,[si] }
$8B/$5C/$02/ {mov bx,[si+02]}
$8B/$4C/$04/ {mov cx,[si+04]}
$8B/$54/$06/ {mov dx,[si+06]}
$5E/ {pop si }
$1F/ {pop ds }
$01/$04/ {add [si],ax }
$11/$5C/$02/ {adc [si+02],bx}
$11/$4C/$04/ {adc [si+04],cx}
$11/$54/$06/ {adc [si+06],dx}
$8E/$DF); {mov ds,di }
{---------------------------------------------------------------------------}
procedure RotR63(var x: tw64);
{-Rotate right 63 bits = rotate left 1}
inline(
$8C/$D9/ {mov cx,ds }
$5B/ {pop bx }
$1F/ {pop ds }
$8B/$47/$06/ {mov ax,[bx+06]}
$D1/$E0/ {shl ax,1 }
$8B/$07/ {mov ax,[bx] }
$D1/$D0/ {rcl ax,1 }
$89/$07/ {mov [bx],ax }
$8B/$47/$02/ {mov ax,[bx+02]}
$D1/$D0/ {rcl ax,1 }
$89/$47/$02/ {mov [bx+02],ax}
$8B/$47/$04/ {mov ax,[bx+04]}
$D1/$D0/ {rcl ax,1 }
$89/$47/$04/ {mov [bx+04],ax}
$8B/$47/$06/ {mov ax,[bx+06]}
$D1/$D0/ {rcl ax,1 }
$89/$47/$06/ {mov [bx+06],ax}
$8E/$D9); {mov ds,cx }
{$endif}
{$else}
{---------------------------------------------------------------------------}
procedure Add64(var z: TW64; const x: TW64); assembler;
{-Inc a 64 bit integer z := z + x}
asm
{$ifdef LoadArgs}
mov eax,[z]
mov edx,[x]
{$endif}
mov ecx,[edx]
add [eax],ecx
mov ecx,[edx+4]
adc [eax+4],ecx
end;
{---------------------------------------------------------------------------}
procedure RotR63(var x: tw64); assembler;
{-Rotate right 63 bits}
asm
{$ifdef LoadArgs}
mov eax,[x]
{$endif}
mov ecx,[eax]
mov edx,[eax+4]
shl ecx,1
rcl edx,1
adc ecx,0
mov [eax],ecx
mov [eax+4],edx
end;
{$endif}
{---------------------------------------------------------------------------}
procedure RotR24(var x: tw64);
{-Rotate right 24 bits}
var
a: packed array[0..7] of byte absolute x;
b0,b1,b2: byte;
begin
b0 := a[0];
b1 := a[1];
b2 := a[2];
a[0] := a[3];
a[1] := a[4];
a[2] := a[5];
a[3] := a[6];
a[4] := a[7];
a[5] := b0;
a[6] := b1;
a[7] := b2;
end;
{---------------------------------------------------------------------------}
procedure inct01(var ctx: THashContext; cnt: longint);
{-Increment byte counter in ctx}
begin
with blake2b_ctx(ctx) do begin
if t[0] < 0 then begin
{Overflow if t[0]+cnt changes sign}
inc(t[0], cnt);
if t[0] >= 0 then inc(t[1]);
end
else inc(t[0], cnt);
end;
end;
{---------------------------------------------------------------------------}
procedure blake2b_compress(var ctx: blake2b_ctx; last: boolean);
{-Compression function, "last" indicates last block}
var
v,m: array[0..15] of tw64;
tem: longint;
round,k: integer;
tw: word;
begin
{get message}
with ctx do begin
{init work variables}
move(h, v, sizeof(h));
move(blake2b_ivl, v[8], sizeof(h));
v[12].l := v[12].l xor t[0]; {low 64 bits of offset}
v[12].h := v[12].h xor t[1];
v[13].l := v[13].l xor t[2]; {high 64 bits}
v[13].h := v[13].h xor t[3];
if last then begin
v[14].l := not v[14].l; {last block flag set}
v[14].h := not v[14].h;
end;
{get little-endian words}
move(b, m, sizeof(m));
{do 12 rounds}
for round:=0 to 11 do begin
{** EddyHawk speed-ups **}
{replaces G64 with partial unroll}
{replaces rotr64 by 32 with swap & temp var}
{ integrates xor-ing into that swapping}
{splits 1 BLAKE2b round into quarter-rounds}
{ regroups them}
{further splitting/regroupings, seems a bit better}
{moves message addition to the front, seems a bit better}
add64(v[0],m[sigma[round][2*0]]);
add64(v[1],m[sigma[round][2*1]]);
add64(v[2],m[sigma[round][2*2]]);
add64(v[3],m[sigma[round][2*3]]);
add64(v[0],v[4]);
add64(v[1],v[5]);
add64(v[2],v[6]);
add64(v[3],v[7]);
tem := v[12].L xor v[0].L;
v[12].L := v[12].H xor v[0].H;
v[12].H := tem;
tem := v[13].L xor v[1].L;
v[13].L := v[13].H xor v[1].H;
v[13].H := tem;
tem := v[14].L xor v[2].L;
v[14].L := v[14].H xor v[2].H;
v[14].H := tem;
tem := v[15].L xor v[3].L;
v[15].L := v[15].H xor v[3].H;
v[15].H := tem;
add64(v[ 8],v[12]);
add64(v[ 9],v[13]);
add64(v[10],v[14]);
add64(v[11],v[15]);
v[4].L := v[4].L xor v[ 8].L;
v[5].L := v[5].L xor v[ 9].L;
v[6].L := v[6].L xor v[10].L;
v[7].L := v[7].L xor v[11].L;
v[4].H := v[4].H xor v[ 8].H;
v[5].H := v[5].H xor v[ 9].H;
v[6].H := v[6].H xor v[10].H;
v[7].H := v[7].H xor v[11].H;
RotR24(v[4]);
RotR24(v[5]);
RotR24(v[6]);
RotR24(v[7]);
{---}
add64(v[0],m[sigma[round][2*0+1]]);
add64(v[1],m[sigma[round][2*1+1]]);
add64(v[2],m[sigma[round][2*2+1]]);
add64(v[3],m[sigma[round][2*3+1]]);
add64(v[0],v[4]);
add64(v[1],v[5]);
add64(v[2],v[6]);
add64(v[3],v[7]);
v[12].L := v[12].L xor v[ 0].L;
v[13].L := v[13].L xor v[ 1].L;
v[14].L := v[14].L xor v[ 2].L;
v[15].L := v[15].L xor v[ 3].L;
v[12].H := v[12].H xor v[ 0].H;
v[13].H := v[13].H xor v[ 1].H;
v[14].H := v[14].H xor v[ 2].H;
v[15].H := v[15].H xor v[ 3].H;
{WE V0.23: Replace RotR(,16) with word moves}
{RotR(v[12],16);}
with TW16(v[12]) do begin
tw := w0;
w0 := w1;
w1 := w2;
w2 := w3;
w3 := tw;
end;
{RotR(v[13],16);}
with TW16(v[13]) do begin
tw := w0;
w0 := w1;
w1 := w2;
w2 := w3;
w3 := tw;
end;
{RotR(v[14],16);}
with TW16(v[14]) do begin
tw := w0;
w0 := w1;
w1 := w2;
w2 := w3;
w3 := tw;
end;
{RotR(v[15],16);}
with TW16(v[15]) do begin
tw := w0;
w0 := w1;
w1 := w2;
w2 := w3;
w3 := tw;
end;
add64(v[ 8],v[12]);
add64(v[ 9],v[13]);
add64(v[10],v[14]);
add64(v[11],v[15]);
v[4].L := v[4].L xor v[ 8].L;
v[5].L := v[5].L xor v[ 9].L;
v[6].L := v[6].L xor v[10].L;
v[7].L := v[7].L xor v[11].L;
v[4].H := v[4].H xor v[ 8].H;
v[5].H := v[5].H xor v[ 9].H;
v[6].H := v[6].H xor v[10].H;
v[7].H := v[7].H xor v[11].H;
RotR63(v[4]);
RotR63(v[5]);
RotR63(v[6]);
RotR63(v[7]);
{---}
add64(v[0],m[sigma[round][2*4]]);
add64(v[1],m[sigma[round][2*5]]);
add64(v[2],m[sigma[round][2*6]]);
add64(v[3],m[sigma[round][2*7]]);
add64(v[0],v[5]);
add64(v[1],v[6]);
add64(v[2],v[7]);
add64(v[3],v[4]);
tem := v[15].L xor v[0].L;
v[15].L := v[15].H xor v[0].H;
v[15].H := tem;
tem := v[12].L xor v[1].L;
v[12].L := v[12].H xor v[1].H;
v[12].H := tem;
tem := v[13].L xor v[2].L;
v[13].L := v[13].H xor v[2].H;
v[13].H := tem;
tem := v[14].L xor v[3].L;
v[14].L := v[14].H xor v[3].H;
v[14].H := tem;
add64(v[10],v[15]);
add64(v[11],v[12]);
add64(v[ 8],v[13]);
add64(v[ 9],v[14]);
v[5].L := v[5].L xor v[10].L;
v[6].L := v[6].L xor v[11].L;
v[7].L := v[7].L xor v[ 8].L;
v[4].L := v[4].L xor v[ 9].L;
v[5].H := v[5].H xor v[10].H;
v[6].H := v[6].H xor v[11].H;
v[7].H := v[7].H xor v[ 8].H;
v[4].H := v[4].H xor v[ 9].H;
RotR24(v[5]);
RotR24(v[6]);
RotR24(v[7]);
RotR24(v[4]);
add64(v[0],m[sigma[round][2*4+1]]);
add64(v[1],m[sigma[round][2*5+1]]);
add64(v[2],m[sigma[round][2*6+1]]);
add64(v[3],m[sigma[round][2*7+1]]);
add64(v[0],v[5]);
add64(v[1],v[6]);
add64(v[2],v[7]);
add64(v[3],v[4]);
v[15].L := v[15].L xor v[ 0].L;
v[12].L := v[12].L xor v[ 1].L;
v[13].L := v[13].L xor v[ 2].L;
v[14].L := v[14].L xor v[ 3].L;
v[15].H := v[15].H xor v[ 0].H;
v[12].H := v[12].H xor v[ 1].H;
v[13].H := v[13].H xor v[ 2].H;
v[14].H := v[14].H xor v[ 3].H;
{WE V0.23: Replace RotR(,16) with word moves}
{RotR(v[15],16);}
with TW16(v[15]) do begin
tw := w0;
w0 := w1;
w1 := w2;
w2 := w3;
w3 := tw;
end;
{RotR(v[12],16);}
with TW16(v[12]) do begin
tw := w0;
w0 := w1;
w1 := w2;
w2 := w3;
w3 := tw;
end;
{RotR(v[13],16);}
with TW16(v[13]) do begin
tw := w0;
w0 := w1;
w1 := w2;
w2 := w3;
w3 := tw;
end;
{RotR(v[14],16);}
with TW16(v[14]) do begin
tw := w0;
w0 := w1;
w1 := w2;
w2 := w3;
w3 := tw;
end;
add64(v[10],v[15]);
add64(v[11],v[12]);
add64(v[ 8],v[13]);
add64(v[ 9],v[14]);
v[5].L := v[5].L xor v[10].L;
v[6].L := v[6].L xor v[11].L;
v[7].L := v[7].L xor v[ 8].L;
v[4].L := v[4].L xor v[ 9].L;
v[5].H := v[5].H xor v[10].H;
v[6].H := v[6].H xor v[11].H;
v[7].H := v[7].H xor v[ 8].H;
v[4].H := v[4].H xor v[ 9].H;
RotR63(v[5]);
RotR63(v[6]);
RotR63(v[7]);
RotR63(v[4]);
end;
{finalization}
for k:=0 to 7 do begin
h[2*k] := h[2*k] xor v[k].l xor v[k+8].l;
h[2*k+1] := h[2*k+1] xor v[k].h xor v[k+8].h;
end;
end;
end;
{---------------------------------------------------------------------------}
procedure blake2b_update(var ctx: THashContext; msg: pointer; mlen: longint);
{-Add "mlen" bytes from "msg" into the hash}
var
left,fill: integer;
begin
with blake2b_ctx(ctx) do begin
if mlen > 0 then begin
left := c;
fill := BLAKE2B_BlockLen - left;
if mlen > fill then begin
c := 0;
if fill>0 then move(msg^, b[left], fill);
inct01(ctx, BLAKE2B_BlockLen);
blake2b_compress(blake2b_ctx(ctx), false);
inc(Ptr2Inc(Msg),fill);
dec(mlen,fill);
while mlen > BLAKE2B_BlockLen do begin
move(msg^,b,BLAKE2B_BlockLen);
inct01(ctx, BLAKE2B_BlockLen);
blake2b_compress(blake2b_ctx(ctx), false); {compress (not last)}
inc(Ptr2Inc(Msg),BLAKE2B_BlockLen);
dec(mlen,BLAKE2B_BlockLen);
end;
end;
if mlen > 0 then begin
move(msg^, b[c], mlen);
c := c + mlen;
end;
end;
end;
end;
{---------------------------------------------------------------------------}
procedure blake2b_Final(var ctx: THashContext; var Digest: TBlake2BDigest);
{-Finalize calculation, generate message digest, clear context}
begin
with blake2b_ctx(ctx) do begin
inct01(ctx, c);
while c < BLAKE2B_BlockLen do begin {fill up with zeros}
b[c] := 0;
inc(c);
end;
blake2b_compress(blake2b_ctx(ctx), true); {final block}
{little endian convert and store}
fillchar(Digest, sizeof(Digest),0);
move(h, Digest, outlen);
end;
end;
{$endif}
{---------------------------------------------------------------------------}
function blake2b_Init(var ctx: THashContext; key: pointer; keylen, diglen: word): integer;
{-Initialize context for a digest of diglen bytes; keylen=0: no key}
var
tb: TBlake2BBlock;
begin
if (diglen=0) or (diglen > BLAKE2B_MaxDigLen) or (keylen > BLAKE2B_MaxKeyLen) then begin
blake2b_Init := -1; {illegal parameters}
exit;
end;
blake2b_Init := 0;
fillchar(ctx, sizeof(ctx), 0);
with blake2b_ctx(ctx) do begin
move(blake2b_ivl, h, sizeof(h));
outlen := diglen;
{Fill the lowest 32 bit of h, same for 16/32/64 bit}
h[0] := h[0] xor (($01010000) xor (keylen shl 8) xor outlen);
if keylen > 0 then begin
fillchar(tb, sizeof(tb),0);
move(key^, tb, keylen);
blake2b_update(ctx, @tb, BLAKE2B_BlockLen);
end;
end;
end;
{---------------------------------------------------------------------------}
function blake2b_full(var dig: TBlake2BDigest; diglen: word;
key: pointer; keylen: word;
msg: pointer; mlen: longint): integer;
{-Calculate hash digest of Msg with init/update/final}
var
ctx: THashContext;
begin
if blake2b_init(ctx, key, keylen, diglen) <> 0 then begin
blake2b_full := -1;
end
else begin
blake2b_update(ctx, msg, mlen);
blake2b_final(ctx, dig);
blake2b_full := 0;
end;
end;
{---------------------------------------------------------------------------}
function blake2b_selftest: boolean;
{-Return true, if self test is OK}
procedure selftest_seq(outp: pbyte; len, seed: integer);
var
t,a,b: longint;
i: integer;
begin
a := longint($DEAD4BAD) * seed;
b := 1;
for i:=1 to len do begin
t := a+b;
a := b;
b := t;
outp^ := (t shr 24) and $FF;
inc(Ptr2Inc(outp));
end;
end;
const
{Grand hash of hash results}
blake2b_res: array[0..31] of byte = (
$C2, $3A, $78, $00, $D9, $81, $23, $BD,
$10, $F5, $06, $C6, $1E, $29, $DA, $56,
$03, $D7, $63, $B8, $BB, $AD, $2E, $73,
$7F, $5E, $76, $5A, $7B, $CC, $D4, $75
);
{Parameter sets}
b2s_md_len: array[0..3] of integer = (20, 32, 48, 64);
b2s_in_len: array[0..5] of integer = (0, 3, 128, 129, 255, 1024);
var
i,j, outlen, inlen: integer;
md, key: TBlake2BDigest;
ctx: THashContext;
inb: array[0..1023] of byte;
begin
blake2b_selftest := false;
{256-bit hash for testing}
if blake2b_init(ctx, nil, 0, 32) <> 0 then exit;
for i:=0 to 3 do begin
outlen := b2s_md_len[i];
for j:=0 to 5 do begin
inlen := b2s_in_len[j];
selftest_seq(pbyte(@inb), inlen, inlen); {unkeyed hash}
if blake2b_full(md, outlen, nil, 0, @inb, inlen) <> 0 then exit;
blake2b_update(ctx, @md, outlen); {hash the hash}
selftest_seq(pbyte(@key), outlen, outlen); {keyed hash}
if blake2b_full(md, outlen, @key, outlen, @inb, inlen) <> 0 then exit;
blake2b_update(ctx, @md, outlen); {hash the hash}
end;
end;
{Compute and compare the hash of hashes.}
blake2b_final(ctx, md);
for i:=0 to 31 do begin
if md[i] <> blake2b_res[i] then exit;
end;
blake2b_selftest := true;
end;
begin
{$ifdef HAS_ASSERT}
assert(sizeof(blake2b_ctx)=HASHCTXSIZE , '** Invalid sizeof(blake2b_ctx)');
{$endif}
end.