1 unit SHA3_256;
2 
3 {SHA3-256 - 256 bit Secure Hash Function}
4 
5 
6 interface
7 
8 (*************************************************************************
9 
10  DESCRIPTION     :  SHA3-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      :  - FIPS 202 SHA-3 Standard: 'Permutation-Based Hash and
21                       Extendable-Output Functions' available from
22                       http://csrc.nist.gov/publications/PubsFIPS.html or
23                       http://dx.doi.org/10.6028/NIST.FIPS.202 or
24                       http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
25                     - Test vectors and intermediate values:
26                       http://csrc.nist.gov/groups/ST/toolkit/examples.html
27 
28  Version  Date      Author      Modification
29  -------  --------  -------     ------------------------------------------
30  0.10     08.08.15  W.Ehrhardt  Initial BP version using SHA5-256 layout
31  0.11     09.08.15  we          SHA3_256FinalBits_LSB
32  0.12     17.08.15  we          Updated references
33  0.13     15.05.17  we          adjust OID to new MaxOIDLen
34  0.14     29.11.17  we          SHA3_256File - fname: string
35 
36 **************************************************************************)
37 
38 (*-------------------------------------------------------------------------
39  (C) Copyright 2015-2017 Wolfgang Ehrhardt
40 
41  This software is provided 'as-is', without any express or implied warranty.
42  In no event will the authors be held liable for any damages arising from
43  the use of this software.
44 
45  Permission is granted to anyone to use this software for any purpose,
46  including commercial applications, and to alter it and redistribute it
47  freely, subject to the following restrictions:
48 
49  1. The origin of this software must not be misrepresented; you must not
50     claim that you wrote the original software. If you use this software in
51     a product, an acknowledgment in the product documentation would be
52     appreciated but is not required.
53 
54  2. Altered source versions must be plainly marked as such, and must not be
55     misrepresented as being the original software.
56 
57  3. This notice may not be removed or altered from any source distribution.
58 ----------------------------------------------------------------------------*)
59 
60 
61 {$i STD.INC}
62 
63 uses
64   BTypes,Hash,SHA3;
65 
66 
67 procedure SHA3_256Init(var Context: THashContext);
68   {-initialize context}
69 
70 procedure SHA3_256Update(var Context: THashContext; Msg: pointer; Len: word);
71   {-update context with Msg data}
72 
73 procedure SHA3_256UpdateXL(var Context: THashContext; Msg: pointer; Len: longint);
74   {-update context with Msg data}
75 
76 procedure SHA3_256Final(var Context: THashContext; var Digest: TSHA3_256Digest);
77   {-finalize SHA3-256 calculation, clear context}
78 
79 procedure SHA3_256FinalEx(var Context: THashContext; var Digest: THashDigest);
80   {-finalize SHA3-256 calculation, clear context}
81 
82 procedure SHA3_256FinalBitsEx(var Context: THashContext; var Digest: THashDigest; BData: byte; bitlen: integer);
83   {-finalize SHA3-256 calculation with bitlen bits from BData (big-endian), clear context}
84 
85 procedure SHA3_256FinalBits(var Context: THashContext; var Digest: TSHA3_256Digest; BData: byte; bitlen: integer);
86   {-finalize SHA3-256 calculation with bitlen bits from BData (big-endian), clear context}
87 
88 procedure SHA3_256FinalBits_LSB(var Context: THashContext; var Digest: TSHA3_256Digest; BData: byte; bitlen: integer);
89   {-finalize SHA3-256 calculation with bitlen bits from BData (LSB format), clear context}
90 
SHA3_256SelfTestnull91 function  SHA3_256SelfTest: boolean;
92   {-self test for string from SHA3-256 documents}
93 
94 procedure SHA3_256Full(var Digest: TSHA3_256Digest; Msg: pointer; Len: word);
95   {-SHA3-256 of Msg with init/update/final}
96 
97 procedure SHA3_256FullXL(var Digest: TSHA3_256Digest; Msg: pointer; Len: longint);
98   {-SHA3-256 of Msg with init/update/final}
99 
100 procedure SHA3_256File({$ifdef CONST} const {$endif} fname: string;
101                      var Digest: TSHA3_256Digest; var buf; bsize: word; var Err: word);
102   {-SHA3-256 of file, buf: buffer with at least bsize bytes}
103 
104 
105 implementation
106 
107 
108 const
109   SHA3_256_BlockLen = 136;  {Rate / 8, used only for HMAC} {FIPS202, Tab.3}
110 
111 {http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html}
112 {2.16.840.1.101.3.4.2.8}
113 {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) SHA3-256(8)}
114 
115 const
116   SHA3_256_OID : TOID_Vec = (2,16,840,1,101,3,4,2,8,-1,-1); {Len=9}
117 
118 
119 {$ifndef VER5X}
120 const
121   SHA3_256_Desc: THashDesc = (
122                HSig      : C_HashSig;
123                HDSize    : sizeof(THashDesc);
124                HDVersion : C_HashVers;
125                HBlockLen : SHA3_256_BlockLen;
126                HDigestlen: sizeof(TSHA3_256Digest);
127              {$ifdef FPC_ProcVar}
128                HInit     : @SHA3_256Init;
129                HFinal    : @SHA3_256FinalEx;
130                HUpdateXL : @SHA3_256UpdateXL;
131              {$else}
132                HInit     : SHA3_256Init;
133                HFinal    : SHA3_256FinalEx;
134                HUpdateXL : SHA3_256UpdateXL;
135              {$endif}
136                HAlgNum   : longint(_SHA3_256);
137                HName     : 'SHA3-256';
138                HPtrOID   : @SHA3_256_OID;
139                HLenOID   : 9;
140                HFill     : 0;
141              {$ifdef FPC_ProcVar}
142                HFinalBit : @SHA3_256FinalBitsEx;
143              {$else}
144                HFinalBit : SHA3_256FinalBitsEx;
145              {$endif}
146                HReserved : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
147             );
148 {$else}
149 var
150   SHA3_256_Desc: THashDesc;
151 {$endif}
152 
153 
154 {$ifdef BIT16}
155   {$F-}
156 {$endif}
157 
158 
159 {---------------------------------------------------------------------------}
160 procedure SHA3_256Init(var Context: THashContext);
161   {-initialize context}
162 begin
163   {Clear context}
164   SHA3_LastError := SHA3_Init(TSHA3State(Context),__SHA3_256);
165 end;
166 
167 
168 {---------------------------------------------------------------------------}
169 procedure SHA3_256UpdateXL(var Context: THashContext; Msg: pointer; Len: longint);
170    {-update context with Msg data}
171 begin
172   SHA3_LastError := SHA3_UpdateXL(TSHA3State(Context), Msg, Len);
173 end;
174 
175 
176 {---------------------------------------------------------------------------}
177 procedure SHA3_256Update(var Context: THashContext; Msg: pointer; Len: word);
178    {-update context with Msg data}
179 begin
180   SHA3_LastError := SHA3_UpdateXL(TSHA3State(Context), Msg, Len);
181 end;
182 
183 
184 {---------------------------------------------------------------------------}
185 procedure SHA3_256FinalBitsEx(var Context: THashContext; var Digest: THashDigest; BData: byte; bitlen: integer);
186   {-finalize SHA3-256 calculation with bitlen bits from BData (big-endian), clear context}
187 begin
188   SHA3_LastError := SHA3_FinalBit(TSHA3State(Context), BData, bitlen, @Digest[0], 8*sizeof(Digest));
189 end;
190 
191 
192 {---------------------------------------------------------------------------}
193 procedure SHA3_256FinalBits(var Context: THashContext; var Digest: TSHA3_256Digest; BData: byte; bitlen: integer);
194   {-finalize SHA3-256 calculation with bitlen bits from BData (big-endian), clear context}
195 begin
196   SHA3_LastError := SHA3_FinalBit(TSHA3State(Context), BData, bitlen, @Digest[0], 8*sizeof(Digest));
197 end;
198 
199 
200 {---------------------------------------------------------------------------}
201 procedure SHA3_256FinalBits_LSB(var Context: THashContext; var Digest: TSHA3_256Digest; BData: byte; bitlen: integer);
202   {-finalize SHA3-256 calculation with bitlen bits from BData (LSB format), clear context}
203 begin
204   SHA3_LastError := SHA3_FinalBit_LSB(TSHA3State(Context), BData, bitlen, @Digest[0], 8*sizeof(Digest));
205 end;
206 
207 
208 {---------------------------------------------------------------------------}
209 procedure SHA3_256FinalEx(var Context: THashContext; var Digest: THashDigest);
210   {-finalize SHA3-256 calculation, clear context}
211 begin
212   SHA3_LastError := SHA3_FinalHash(TSHA3State(Context), @Digest[0]);
213 end;
214 
215 
216 {---------------------------------------------------------------------------}
217 procedure SHA3_256Final(var Context: THashContext; var Digest: TSHA3_256Digest);
218   {-finalize SHA3-256 calculation, clear context}
219 begin
220   SHA3_LastError := SHA3_FinalHash(TSHA3State(Context), @Digest[0]);
221 end;
222 
223 
224 {---------------------------------------------------------------------------}
SHA3_256SelfTestnull225 function SHA3_256SelfTest: boolean;
226   {-self test for string from SHA3-256 documents}
227 const
228   Bl1 = 0;
229   dig1: TSHA3_256Digest      = ($A7,$FF,$C6,$F8,$BF,$1E,$D7,$66,
230                                 $51,$C1,$47,$56,$A0,$61,$D6,$62,
231                                 $F5,$80,$FF,$4D,$E4,$3B,$49,$FA,
232                                 $82,$D8,$0A,$4B,$80,$F8,$43,$4A);
233   BL2 = 5;
234   msg2: array[0..0] of byte  = ($13);
235   dig2: TSHA3_256Digest      = ($7B,$00,$47,$CF,$5A,$45,$68,$82,
236                                 $36,$3C,$BF,$0F,$B0,$53,$22,$CF,
237                                 $65,$F4,$B7,$05,$9A,$46,$36,$5E,
238                                 $83,$01,$32,$E3,$B5,$D9,$57,$AF);
239   BL3 = 30;
240   msg3: array[0..3] of byte  = ($53,$58,$7B,$19);
241   dig3: TSHA3_256Digest      = ($C8,$24,$2F,$EF,$40,$9E,$5A,$E9,
242                                 $D1,$F1,$C8,$57,$AE,$4D,$C6,$24,
243                                 $B9,$2B,$19,$80,$9F,$62,$AA,$8C,
244                                 $07,$41,$1C,$54,$A0,$78,$B1,$D0);
245 
246   {https://github.com/gvanas/KeccakCodePackage, SKat len=200}
247   BL4 = 200;
248   msg4: array[0..24] of byte = ($aa,$fd,$c9,$24,$3d,$3d,$4a,$09,
249                                 $65,$58,$a3,$60,$cc,$27,$c8,$d8,
250                                 $62,$f0,$be,$73,$db,$5e,$88,$aa,$55);
251   dig4: TSHA3_256Digest      = ($c6,$4b,$ec,$f7,$b7,$5f,$c8,$85,
252                                 $d5,$85,$39,$24,$f2,$b7,$d3,$7a,
253                                 $bc,$ef,$d3,$da,$12,$6b,$b8,$17,
254                                 $69,$7e,$1a,$09,$15,$2b,$1e,$be);
255 var
256   Context: THashContext;
257   Digest : TSHA3_256Digest;
258 
SingleTestnull259   function SingleTest(Msg: pointer; BL: word; TDig: TSHA3_256Digest): boolean;
260   var
261     bytes: word;
262   begin
263     SingleTest := false;
264     SHA3_256Init(Context);
265     if SHA3_LastError<>0 then exit;
266     if BL=0 then SHA3_256Final(Context,Digest)
267     else begin
268       if BL>7 then begin
269         bytes := BL shr 3;
270         SHA3_256Update(Context, Msg, BL shr 3);
271         if SHA3_LastError<>0 then exit;
272         inc(Ptr2Inc(Msg), bytes);
273       end;
274       SHA3_256FinalBits_LSB(Context, Digest, pByte(Msg)^, BL and 7);
275     end;
276     if SHA3_LastError<>0 then exit;
277     SingleTest := HashSameDigest(@SHA3_256_Desc, PHashDigest(@TDig), PHashDigest(@Digest));
278   end;
279 
280 begin
281   SHA3_256SelfTest := SingleTest(nil, BL1, dig1)   and
282                       SingleTest(@msg2, BL2, dig2) and
283                       SingleTest(@msg3, BL3, dig3) and
284                       SingleTest(@msg4, BL4, dig4);
285 end;
286 
287 
288 {---------------------------------------------------------------------------}
289 procedure SHA3_256FullXL(var Digest: TSHA3_256Digest; Msg: pointer; Len: longint);
290   {-SHA3-256 of Msg with init/update/final}
291 var
292   Context: THashContext;
293 begin
294   SHA3_256Init(Context);
295   if SHA3_LastError=0 then SHA3_256UpdateXL(Context, Msg, Len);
296   SHA3_256Final(Context, Digest);
297 end;
298 
299 
300 {---------------------------------------------------------------------------}
301 procedure SHA3_256Full(var Digest: TSHA3_256Digest; Msg: pointer; Len: word);
302   {-SHA3-256 of Msg with init/update/final}
303 begin
304   SHA3_256FullXL(Digest, Msg, Len);
305 end;
306 
307 
308 {---------------------------------------------------------------------------}
309 procedure SHA3_256File({$ifdef CONST} const {$endif} fname: string;
310                      var Digest: TSHA3_256Digest; var buf; bsize: word; var Err: word);
311   {-SHA3-256 of file, buf: buffer with at least bsize bytes}
312 var
313   tmp: THashDigest;
314 begin
315   HashFile(fname, @SHA3_256_Desc, tmp, buf, bsize, Err);
316   move(tmp, Digest, sizeof(Digest));
317 end;
318 
319 
320 begin
321   {$ifdef VER5X}
322     fillchar(SHA3_256_Desc, sizeof(SHA3_256_Desc), 0);
323     with SHA3_256_Desc do begin
324        HSig      := C_HashSig;
325        HDSize    := sizeof(THashDesc);
326        HDVersion := C_HashVers;
327        HBlockLen := SHA3_256_BlockLen;
328        HDigestlen:= sizeof(TSHA3_256Digest);
329        HInit     := SHA3_256Init;
330        HFinal    := SHA3_256FinalEx;
331        HUpdateXL := SHA3_256UpdateXL;
332        HAlgNum   := longint(_SHA3_256);
333        HName     := 'SHA3-256';
334        HPtrOID   := @SHA3_256_OID;
335        HLenOID   := 9;
336        HFinalBit := SHA3_256FinalBitsEx;
337     end;
338   {$endif}
339   RegisterHash(_SHA3_256, @SHA3_256_Desc);
340 end.
341