1 unit SHA5_256;
2 
3 {SHA512/256 - 256 bit Secure Hash Function}
4 
5 
6 interface
7 
8 (*************************************************************************
9 
10  DESCRIPTION     :  SHA512/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      :  - Latest specification of Secure Hash Standard:
21                       http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
22                     - Test vectors and intermediate values:
23                       http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
24 
25  Version  Date      Author      Modification
26  -------  --------  -------     ------------------------------------------
27  0.10     14.02.11  W.Ehrhardt  Initial BP version using SHA384 layout
28  0.11     15.02.11  we          Updated OID
29  0.12     16.02.11  we          function pSHA5_256_Desc
30  0.13     08.03.12  we          RegisterHash(_SHA512_256...)
31  0.14     08.03.12  we          Changed HName to 'SHA512/256', updates URLs
32  0.15     08.03.12  we          removed pSHA5_256_Desc
33  0.16     16.08.15  we          Removed $ifdef DLL / stdcall
34  0.17     15.05.17  we          adjust OID to new MaxOIDLen
35  0.18     29.11.17  we          SHA5_256File - fname: string
36 
37 **************************************************************************)
38 
39 (*-------------------------------------------------------------------------
40  (C) Copyright 2011-2017 Wolfgang Ehrhardt
41 
42  This software is provided 'as-is', without any express or implied warranty.
43  In no event will the authors be held liable for any damages arising from
44  the use of this software.
45 
46  Permission is granted to anyone to use this software for any purpose,
47  including commercial applications, and to alter it and redistribute it
48  freely, subject to the following restrictions:
49 
50  1. The origin of this software must not be misrepresented; you must not
51     claim that you wrote the original software. If you use this software in
52     a product, an acknowledgment in the product documentation would be
53     appreciated but is not required.
54 
55  2. Altered source versions must be plainly marked as such, and must not be
56     misrepresented as being the original software.
57 
58  3. This notice may not be removed or altered from any source distribution.
59 ----------------------------------------------------------------------------*)
60 
61 
62 {$i STD.INC}
63 
64 uses
65   BTypes,Hash,SHA512;
66 
67 
68 procedure SHA5_256Init(var Context: THashContext);
69   {-initialize context}
70 
71 procedure SHA5_256Update(var Context: THashContext; Msg: pointer; Len: word);
72   {-update context with Msg data}
73 
74 procedure SHA5_256UpdateXL(var Context: THashContext; Msg: pointer; Len: longint);
75   {-update context with Msg data}
76 
77 procedure SHA5_256Final(var Context: THashContext; var Digest: TSHA5_256Digest);
78   {-finalize SHA512/256 calculation, clear context}
79 
80 procedure SHA5_256FinalEx(var Context: THashContext; var Digest: THashDigest);
81   {-finalize SHA512/256 calculation, clear context}
82 
83 procedure SHA5_256FinalBitsEx(var Context: THashContext; var Digest: THashDigest; BData: byte; bitlen: integer);
84   {-finalize SHA512/256 calculation with bitlen bits from BData (big-endian), clear context}
85 
86 procedure SHA5_256FinalBits(var Context: THashContext; var Digest: TSHA5_256Digest; BData: byte; bitlen: integer);
87   {-finalize SHA512/256 calculation with bitlen bits from BData (big-endian), clear context}
88 
SHA5_256SelfTestnull89 function  SHA5_256SelfTest: boolean;
90   {-self test for string from SHA512/256 document}
91 
92 procedure SHA5_256Full(var Digest: TSHA5_256Digest; Msg: pointer; Len: word);
93   {-SHA512/256 of Msg with init/update/final}
94 
95 procedure SHA5_256FullXL(var Digest: TSHA5_256Digest; Msg: pointer; Len: longint);
96   {-SHA512/256 of Msg with init/update/final}
97 
98 procedure SHA5_256File({$ifdef CONST} const {$endif} fname: string;
99                      var Digest: TSHA5_256Digest; var buf; bsize: word; var Err: word);
100   {-SHA512/256 of file, buf: buffer with at least bsize bytes}
101 
102 
103 implementation
104 
105 
106 const
107   SHA5_256_BlockLen = 128;
108 
109 {http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html}
110 {2.16.840.1.101.3.4.2.6}
111 {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) SHA512/256(6)}
112 
113 const
114   SHA5_256_OID : TOID_Vec = (2,16,840,1,101,3,4,2,6,-1,-1); {Len=9}
115 
116 
117 {$ifndef VER5X}
118 const
119   SHA5_256_Desc: THashDesc = (
120                HSig      : C_HashSig;
121                HDSize    : sizeof(THashDesc);
122                HDVersion : C_HashVers;
123                HBlockLen : SHA5_256_BlockLen;
124                HDigestlen: sizeof(TSHA5_256Digest);
125              {$ifdef FPC_ProcVar}
126                HInit     : @SHA5_256Init;
127                HFinal    : @SHA5_256FinalEx;
128                HUpdateXL : @SHA5_256UpdateXL;
129              {$else}
130                HInit     : SHA5_256Init;
131                HFinal    : SHA5_256FinalEx;
132                HUpdateXL : SHA5_256UpdateXL;
133              {$endif}
134                HAlgNum   : longint(_SHA512_256);
135                HName     : 'SHA512/256';
136                HPtrOID   : @SHA5_256_OID;
137                HLenOID   : 9;
138                HFill     : 0;
139              {$ifdef FPC_ProcVar}
140                HFinalBit : @SHA5_256FinalBitsEx;
141              {$else}
142                HFinalBit : SHA5_256FinalBitsEx;
143              {$endif}
144                HReserved : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
145             );
146 {$else}
147 var
148   SHA5_256_Desc: THashDesc;
149 {$endif}
150 
151 
152 {$ifdef BIT16}
153   {$F-}
154 {$endif}
155 
156 
157 {---------------------------------------------------------------------------}
158 procedure SHA5_256Init(var Context: THashContext);
159   {-initialize context}
160 {$ifdef StrictLong}
161   {$warnings off}
162   {$R-} {avoid D9 errors!}
163 {$endif}
164 const
165   SIV: THashState = ($fc2bf72c,$22312194,$c84c64c2,$9f555fa3,
166                      $6f53b151,$2393b86b,$5940eabd,$96387719,
167                      $a88effe3,$96283ee2,$53863992,$be5e1e25,
168                      $2c85b8aa,$2b0199fc,$81c52ca2,$0eb72ddc);
169 {$ifdef StrictLong}
170   {$warnings on}
171   {$ifdef RangeChecks_on}
172     {$R+}
173   {$endif}
174 {$endif}
175 begin
176   {Clear context}
177   fillchar(Context,sizeof(Context),0);
178   Context.Hash := SIV;
179 end;
180 
181 
182 {---------------------------------------------------------------------------}
183 procedure SHA5_256UpdateXL(var Context: THashContext; Msg: pointer; Len: longint);
184    {-update context with Msg data}
185 begin
186   SHA512UpdateXL(THashContext(Context), Msg, Len);
187 end;
188 
189 
190 {---------------------------------------------------------------------------}
191 procedure SHA5_256Update(var Context: THashContext; Msg: pointer; Len: word);
192    {-update context with Msg data}
193 begin
194   SHA512UpdateXL(THashContext(Context), Msg, Len);
195 end;
196 
197 
198 {---------------------------------------------------------------------------}
199 procedure SHA5_256FinalBitsEx(var Context: THashContext; var Digest: THashDigest; BData: byte; bitlen: integer);
200   {-finalize SHA512/256 calculation with bitlen bits from BData (big-endian), clear context}
201 begin
202   SHA512FinalBitsEx(Context, Digest, BData, bitlen);
203 end;
204 
205 
206 {---------------------------------------------------------------------------}
207 procedure SHA5_256FinalBits(var Context: THashContext; var Digest: TSHA5_256Digest; BData: byte; bitlen: integer);
208   {-finalize SHA512/256 calculation with bitlen bits from BData (big-endian), clear context}
209 var
210   tmp: THashDigest;
211 begin
212   SHA512FinalBitsEx(Context, tmp, BData, bitlen);
213   move(tmp, Digest, sizeof(Digest));
214 end;
215 
216 
217 {---------------------------------------------------------------------------}
218 procedure SHA5_256FinalEx(var Context: THashContext; var Digest: THashDigest);
219   {-finalize SHA512/256 calculation, clear context}
220 begin
221   SHA512FinalBitsEx(Context, Digest,0,0);
222 end;
223 
224 
225 {---------------------------------------------------------------------------}
226 procedure SHA5_256Final(var Context: THashContext; var Digest: TSHA5_256Digest);
227   {-finalize SHA512/256 calculation, clear context}
228 var
229   tmp: THashDigest;
230 begin
231   SHA512FinalBitsEx(Context, tmp, 0, 0);
232   move(tmp, Digest, sizeof(Digest));
233 end;
234 
235 
236 {---------------------------------------------------------------------------}
SHA5_256SelfTestnull237 function SHA5_256SelfTest: boolean;
238   {-self test for string from SHA512/256 document}
239 const
240   s1: string[3] = 'abc';
241   s2: string[112] = 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn'
242                    +'hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu';
243 
244   D1: TSHA5_256Digest = ($53,$04,$8e,$26,$81,$94,$1e,$f9,
245                          $9b,$2e,$29,$b7,$6b,$4c,$7d,$ab,
246                          $e4,$c2,$d0,$c6,$34,$fc,$6d,$46,
247                          $e0,$e2,$f1,$31,$07,$e7,$af,$23);
248 
249   D2: TSHA5_256Digest = ($39,$28,$e1,$84,$fb,$86,$90,$f8,
250                          $40,$da,$39,$88,$12,$1d,$31,$be,
251                          $65,$cb,$9d,$3e,$f8,$3e,$e6,$14,
252                          $6f,$ea,$c8,$61,$e1,$9b,$56,$3a);
253 
254 var
255   Context: THashContext;
256   Digest : TSHA5_256Digest;
257 
SingleTestnull258   function SingleTest(s: Str127; TDig: TSHA5_256Digest): boolean;
259     {-do a single test, const not allowed for VER<7}
260     { Two sub tests: 1. whole string, 2. one update per char}
261   var
262     i: integer;
263   begin
264     SingleTest := false;
265     {1. Hash complete string}
266     SHA5_256Full(Digest, @s[1],length(s));
267     {Compare with known value}
268     if not HashSameDigest(@SHA5_256_Desc, PHashDigest(@Digest), PHashDigest(@TDig)) then exit;
269     {2. one update call for all chars}
270     SHA5_256Init(Context);
271     for i:=1 to length(s) do SHA5_256Update(Context,@s[i],1);
272     SHA5_256Final(Context,Digest);
273     {Compare with known value}
274     if not HashSameDigest(@SHA5_256_Desc, PHashDigest(@Digest), PHashDigest(@TDig)) then exit;
275     SingleTest := true;
276   end;
277 
278 begin
279   {strings from SHA512/256 document}
280   SHA5_256SelfTest := SingleTest(s1, D1) and SingleTest(s2, D2)
281 end;
282 
283 
284 {---------------------------------------------------------------------------}
285 procedure SHA5_256FullXL(var Digest: TSHA5_256Digest; Msg: pointer; Len: longint);
286   {-SHA512/256 of Msg with init/update/final}
287 var
288   Context: THashContext;
289 begin
290   SHA5_256Init(Context);
291   SHA5_256UpdateXL(Context, Msg, Len);
292   SHA5_256Final(Context, Digest);
293 end;
294 
295 
296 {---------------------------------------------------------------------------}
297 procedure SHA5_256Full(var Digest: TSHA5_256Digest; Msg: pointer; Len: word);
298   {-SHA512/256 of Msg with init/update/final}
299 begin
300   SHA5_256FullXL(Digest, Msg, Len);
301 end;
302 
303 
304 {---------------------------------------------------------------------------}
305 procedure SHA5_256File({$ifdef CONST} const {$endif} fname: string;
306                      var Digest: TSHA5_256Digest; var buf; bsize: word; var Err: word);
307   {-SHA512/256 of file, buf: buffer with at least bsize bytes}
308 var
309   tmp: THashDigest;
310 begin
311   HashFile(fname, @SHA5_256_Desc, tmp, buf, bsize, Err);
312   move(tmp, Digest, sizeof(Digest));
313 end;
314 
315 
316 begin
317   {$ifdef VER5X}
318     fillchar(SHA5_256_Desc, sizeof(SHA5_256_Desc), 0);
319     with SHA5_256_Desc do begin
320        HSig      := C_HashSig;
321        HDSize    := sizeof(THashDesc);
322        HDVersion := C_HashVers;
323        HBlockLen := SHA5_256_BlockLen;
324        HDigestlen:= sizeof(TSHA5_256Digest);
325        HInit     := SHA5_256Init;
326        HFinal    := SHA5_256FinalEx;
327        HUpdateXL := SHA5_256UpdateXL;
328        HAlgNum   := longint(_SHA512_256);
329        HName     := 'SHA512/256';
330        HPtrOID   := @SHA5_256_OID;
331        HLenOID   := 9;
332        HFinalBit := SHA5_256FinalBitsEx;
333     end;
334   {$endif}
335   RegisterHash(_SHA512_256, @SHA5_256_Desc);
336 end.
337