1 unit Blaks256;
2 
3 {Blake2s-256 - 256 bit Secure Hash Function}
4 
5 
6 interface
7 
8 (*************************************************************************
9 
10  DESCRIPTION     :  Blake2s-256 - 256 bit Secure Hash Function
11 
12  REQUIREMENTS    :  TP5-7, D1-D7/D9-D10/D12/D17-D18/D25S, FPC, VP
13 
14  EXTERNAL DATA   :  ---
15 
16  MEMORY USAGE    :  ---
17 
18  DISPLAY MODE    :  ---
19 
20  REFERENCES      :  - Saarinen et al: The BLAKE2 Cryptographic Hash and Message
21                       Authentication  Code (MAC); https://tools.ietf.org/html/rfc7693
22                     - Aumasson et al: BLAKE2: simpler, smaller, fast as MD5;
23                       https://blake2.net/blake2.pdf
24                     - Official reference code: https://github.com/BLAKE2/BLAKE2
25 
26  Version  Date      Author      Modification
27  -------  --------  -------     ------------------------------------------
28  0.10     15.05.17  W.Ehrhardt  Initial BP version using SHA3-256 layout
29  0.11     16.05.17  we          Avoid warning in Blaks256Init, references, OID
30  0.12     17.05.17  we          Two additional specific tests
31  0.13     29.11.17  we          Blaks256File - fname: string
32 
33 **************************************************************************)
34 
35 (*-------------------------------------------------------------------------
36  (C) Copyright 2017 Wolfgang Ehrhardt
37 
38  This software is provided 'as-is', without any express or implied warranty.
39  In no event will the authors be held liable for any damages arising from
40  the use of this software.
41 
42  Permission is granted to anyone to use this software for any purpose,
43  including commercial applications, and to alter it and redistribute it
44  freely, subject to the following restrictions:
45 
46  1. The origin of this software must not be misrepresented; you must not
47     claim that you wrote the original software. If you use this software in
48     a product, an acknowledgment in the product documentation would be
49     appreciated but is not required.
50 
51  2. Altered source versions must be plainly marked as such, and must not be
52     misrepresented as being the original software.
53 
54  3. This notice may not be removed or altered from any source distribution.
55 ----------------------------------------------------------------------------*)
56 
57 
58 {$i STD.INC}
59 
60 uses
61   BTypes,Hash,Blake2s;
62 
63 
64 procedure Blaks256Init(var Context: THashContext);
65   {-initialize context}
66 
67 procedure Blaks256Update(var Context: THashContext; Msg: pointer; Len: word);
68   {-update context with Msg data}
69 
70 procedure Blaks256UpdateXL(var Context: THashContext; Msg: pointer; Len: longint);
71   {-update context with Msg data}
72 
73 procedure Blaks256Final(var Context: THashContext; var Digest: TBlake2S_256Digest);
74   {-finalize Blake2S-256 calculation, clear context}
75 
76 procedure Blaks256FinalEx(var Context: THashContext; var Digest: THashDigest);
77   {-finalize Blake2S-256 calculation, clear context}
78 
Blaks256SelfTestnull79 function  Blaks256SelfTest: boolean;
80   {-self test for Blake2S-256}
81 
82 procedure Blaks256Full(var Digest: TBlake2S_256Digest; Msg: pointer; Len: word);
83   {-Blake2S-256 of Msg with init/update/final}
84 
85 procedure Blaks256FullXL(var Digest: TBlake2S_256Digest; Msg: pointer; Len: longint);
86   {-Blake2S-256 of Msg with init/update/final}
87 
88 procedure Blaks256File({$ifdef CONST} const {$endif} fname: string;
89                      var Digest: TBlake2S_256Digest; var buf; bsize: word; var Err: word);
90   {-Blake2S-256 of file, buf: buffer with at least bsize bytes}
91 
92 
93 implementation
94 
95 
96 {$ifdef BIT16}
97   {$F+}
98 {$endif}
99 
100 {---------------------------------------------------------------------------}
101 procedure Blaks256FinalBitsEx(var Context: THashContext; var Digest: THashDigest; BData: byte; bitlen: integer);
102   {-finalize calculation with bitlen bits from BData, clear context}
103 begin
104   {Just ignore the final bits}
105   Blaks256FinalEx(Context, Digest);
106 end;
107 
108 
109 const
110   Blaks256_OID : TOID_Vec = (1,3,6,1,4,1,1722,12,2,2,8);  {Len=11}
111 
112 
113 {$ifndef VER5X}
114 const
115   Blaks256_Desc: THashDesc = (
116                HSig      : C_HashSig;
117                HDSize    : sizeof(THashDesc);
118                HDVersion : C_HashVers;
119                HBlockLen : BLAKE2S_BlockLen;
120                HDigestlen: sizeof(TBlake2S_256Digest);
121              {$ifdef FPC_ProcVar}
122                HInit     : @Blaks256Init;
123                HFinal    : @Blaks256FinalEx;
124                HUpdateXL : @Blaks256UpdateXL;
125              {$else}
126                HInit     : Blaks256Init;
127                HFinal    : Blaks256FinalEx;
128                HUpdateXL : Blaks256UpdateXL;
129              {$endif}
130                HAlgNum   : longint(_Blake2S_256);
131                HName     : 'Blake2S-256';
132                HPtrOID   : @Blaks256_OID;
133                HLenOID   : 11;
134                HFill     : 0;
135              {$ifdef FPC_ProcVar}
136                HFinalBit : @Blaks256FinalBitsEx;
137              {$else}
138                HFinalBit : Blaks256FinalBitsEx;
139              {$endif}
140                HReserved : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
141             );
142 {$else}
143 var
144   Blaks256_Desc: THashDesc;
145 {$endif}
146 
147 
148 {$ifdef BIT16}
149   {$F-}
150 {$endif}
151 
152 
153 {---------------------------------------------------------------------------}
154 procedure Blaks256Init(var Context: THashContext);
155   {-initialize context}
156 var
157   err: integer;
158 begin
159   {Clear context}
160   err := blake2s_Init(blake2s_ctx(Context),nil,0,sizeof(TBlake2S_256Digest));
161   if err<>0 then begin
162     {$ifdef debug}
163       {This should not happen, because and error can only be returned}
164       {if key/digest lengths are out of range, 0 and 32 are OK}
165       writeln('Blaks256Init error = ',err);
166     {$endif}
167   end;
168 end;
169 
170 
171 {---------------------------------------------------------------------------}
172 procedure Blaks256UpdateXL(var Context: THashContext; Msg: pointer; Len: longint);
173    {-update context with Msg data}
174 begin
175   blake2s_update(blake2s_ctx(Context), Msg, Len);
176 end;
177 
178 
179 {---------------------------------------------------------------------------}
180 procedure Blaks256Update(var Context: THashContext; Msg: pointer; Len: word);
181    {-update context with Msg data}
182 begin
183   blake2s_update(blake2s_ctx(Context), Msg, Len);
184 end;
185 
186 
187 {---------------------------------------------------------------------------}
188 procedure Blaks256FinalEx(var Context: THashContext; var Digest: THashDigest);
189   {-finalize Blake2S-256 calculation, clear context}
190 var
191   b2sd: TBlake2SDigest absolute Digest;
192 begin
193   fillchar(Digest, sizeof(Digest), 0);
194   Blake2s_Final(blake2s_ctx(Context), b2sd);
195 end;
196 
197 
198 {---------------------------------------------------------------------------}
199 procedure Blaks256Final(var Context: THashContext; var Digest: TBlake2S_256Digest);
200   {-finalize Blake2S-256 calculation, clear context}
201 var
202   b2sd: TBlake2SDigest;
203 begin
204   fillchar(b2sd, sizeof(b2sd), 0);
205   Blake2s_Final(blake2s_ctx(Context), b2sd);
206   move(b2sd, Digest, sizeof(Digest));
207 end;
208 
209 
210 {---------------------------------------------------------------------------}
Blaks256SelfTestnull211 function Blaks256SelfTest: boolean;
212   {-self test for Blake2S-256}
213 const
214   abc : array[0..2] of char8 = 'abc';
215   digabc: TBlake2S_256Digest = (
216             $50,$8C,$5E,$8C,$32,$7C,$14,$E2,$E1,$A7,$2B,$A3,$4E,$EB,$45,$2F,
217             $37,$45,$8B,$20,$9E,$D6,$3A,$29,$4D,$99,$9B,$4C,$86,$67,$59,$82);
218   dignil: TBlake2S_256Digest = (
219             $69,$21,$7a,$30,$79,$90,$80,$94,$e1,$11,$21,$d0,$42,$35,$4a,$7c,
220             $1f,$55,$b6,$48,$2c,$a1,$a5,$1e,$1b,$25,$0d,$fd,$1e,$d0,$ee,$f9);
221 var
222   Digest: TBlake2S_256Digest;
223 begin
224   Blaks256SelfTest := false;
225   if not blake2s_selftest then exit;
226   {from libtomcrypt-develop\src\hashes\blake2s.c}
227   Blaks256Full(Digest, nil, 0);
228   if not HashSameDigest(@Blaks256_Desc, PHashDigest(@Digest), PHashDigest(@dignil)) then exit;
229   Blaks256Full(Digest, @abc, sizeof(abc));
230   Blaks256SelfTest := HashSameDigest(@Blaks256_Desc, PHashDigest(@Digest), PHashDigest(@digabc));
231 end;
232 
233 
234 {---------------------------------------------------------------------------}
235 procedure Blaks256FullXL(var Digest: TBlake2S_256Digest; Msg: pointer; Len: longint);
236   {-Blake2S-256 of Msg with init/update/final}
237 var
238   Context: THashContext;
239 begin
240   Blaks256Init(Context);
241   Blaks256UpdateXL(Context, Msg, Len);
242   Blaks256Final(Context, Digest);
243 end;
244 
245 
246 {---------------------------------------------------------------------------}
247 procedure Blaks256Full(var Digest: TBlake2S_256Digest; Msg: pointer; Len: word);
248   {-Blake2S-256 of Msg with init/update/final}
249 begin
250   Blaks256FullXL(Digest, Msg, Len);
251 end;
252 
253 
254 {---------------------------------------------------------------------------}
255 procedure Blaks256File({$ifdef CONST} const {$endif} fname: string;
256                      var Digest: TBlake2S_256Digest; var buf; bsize: word; var Err: word);
257   {-Blake2S-256 of file, buf: buffer with at least bsize bytes}
258 var
259   tmp: THashDigest;
260 begin
261   HashFile(fname, @Blaks256_Desc, tmp, buf, bsize, Err);
262   move(tmp, Digest, sizeof(Digest));
263 end;
264 
265 
266 begin
267   {$ifdef VER5X}
268     fillchar(Blaks256_Desc, sizeof(Blaks256_Desc), 0);
269     with Blaks256_Desc do begin
270        HSig      := C_HashSig;
271        HDSize    := sizeof(THashDesc);
272        HDVersion := C_HashVers;
273        HBlockLen := BLAKE2S_BlockLen;
274        HDigestlen:= sizeof(TBlake2S_256Digest);
275        HInit     := Blaks256Init;
276        HFinal    := Blaks256FinalEx;
277        HUpdateXL := Blaks256UpdateXL;
278        HAlgNum   := longint(_Blake2S_256);
279        HName     := 'Blake2S-256';
280        HPtrOID   := @Blaks256_OID;
281        HLenOID   := 11;
282        HFinalBit := Blaks256FinalBitsEx;
283     end;
284   {$endif}
285   RegisterHash(_Blake2S_256, @Blaks256_Desc);
286 end.
287