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