1 unit HMAC;
2 
3 {General HMAC unit}
4 
5 
6 interface
7 
8 (*************************************************************************
9 
10  DESCRIPTION     :  General HMAC (hash message authentication) unit
11 
12  REQUIREMENTS    :  TP5-7, D1-D7/D9-D10/D12/D17-D18, FPC, VP
13 
14  EXTERNAL DATA   :  ---
15 
16  MEMORY USAGE    :  ---
17 
18  DISPLAY MODE    :  ---
19 
20  REFERENCES      :  - HMAC: Keyed-Hashing for Message Authentication
21                       (http://tools.ietf.org/html/rfc2104)
22                     - The Keyed-Hash Message Authentication Code (HMAC)
23                       http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
24                     - US Secure Hash Algorithms (SHA and HMAC-SHA)
25                       (http://tools.ietf.org/html/rfc4634)
26 
27  REMARKS         :  Trailing bits in SHA3-LSB format must be converted to MSB
28 
29  Version  Date      Author      Modification
30  -------  --------  -------     ------------------------------------------
31  0.10     15.01.06  W.Ehrhardt  Initial version based on HMACWHIR
32  0.11     07.05.08  we          hmac_final_bits
33  0.12     12.11.08  we          Uses BTypes, THMAC_string replaced by Str255
34  0.13     25.04.09  we          updated RFC URL(s)
35 
36  0.14     08.08.15  we          type of hmacbuf changed to THMacBuffer
37  0.15     16.08.15  we          Removed $ifdef DLL / stdcall
38 
39 **************************************************************************)
40 
41 (*-------------------------------------------------------------------------
42  (C) Copyright 2006-2015 Wolfgang Ehrhardt
43 
44  This software is provided 'as-is', without any express or implied warranty.
45  In no event will the authors be held liable for any damages arising from
46  the use of this software.
47 
48  Permission is granted to anyone to use this software for any purpose,
49  including commercial applications, and to alter it and redistribute it
50  freely, subject to the following restrictions:
51 
52  1. The origin of this software must not be misrepresented; you must not
53     claim that you wrote the original software. If you use this software in
54     a product, an acknowledgment in the product documentation would be
55     appreciated but is not required.
56 
57  2. Altered source versions must be plainly marked as such, and must not be
58     misrepresented as being the original software.
59 
60  3. This notice may not be removed or altered from any source distribution.
61 ----------------------------------------------------------------------------*)
62 
63 uses
64   BTypes,hash;
65 
66 type
67   THMAC_Context = record
68                     hashctx: THashContext;
69                     hmacbuf: THMacBuffer;
70                     phashd : PHashDesc;
71                   end;
72 
73 procedure hmac_init(var ctx: THMAC_Context; phash: PHashDesc; key: pointer; klen: word);
74   {-initialize HMAC context with hash descr phash^ and key}
75 
76 procedure hmac_inits(var ctx: THMAC_Context; phash: PHashDesc; skey: Str255);
77   {-initialize HMAC context with hash descr phash^ and skey}
78 
79 procedure hmac_update(var ctx: THMAC_Context; data: pointer; dlen: word);
80   {-HMAC data input, may be called more than once}
81 
82 procedure hmac_updateXL(var ctx: THMAC_Context; data: pointer; dlen: longint);
83   {-HMAC data input, may be called more than once}
84 
85 procedure hmac_final(var ctx: THMAC_Context; var mac: THashDigest);
86   {-end data input, calculate HMAC digest}
87 
88 procedure hmac_final_bits(var ctx: THMAC_Context; var mac: THashDigest; BData: byte; bitlen: integer);
89   {-end data input with bitlen bits (MSB format) from BData, calculate HMAC digest}
90 
91 
92 implementation
93 
94 
95 {---------------------------------------------------------------------------}
96 procedure hmac_init(var ctx: THMAC_Context; phash: PHashDesc; key: pointer; klen: word);
97   {-initialize HMAC context with hash descr phash^ and key}
98 var
99   i,lk,bl: word;
100   kb: THashDigest;
101 begin
102   fillchar(ctx, sizeof(ctx),0);
103   if phash<>nil then with ctx do begin
104     phashd := phash;
105     lk := klen;
106     bl := phash^.HBlockLen;
107     if lk > bl then begin
108       {Hash if key length > block length}
109       HashFullXL(phash, kb, key, lk);
110       lk := phash^.HDigestLen;
111       move(kb, hmacbuf, lk);
112     end
113     else move(key^, hmacbuf, lk);
114     {XOR with ipad}
115     for i:=0 to bl-1 do hmacbuf[i] := hmacbuf[i] xor $36;
116     {start inner hash}
117     phash^.HInit(hashctx);
118     phash^.HUpdateXL(hashctx, @hmacbuf, bl);
119   end;
120 end;
121 
122 
123 {---------------------------------------------------------------------------}
124 procedure hmac_inits(var ctx: THMAC_Context; phash: PHashDesc; skey: Str255);
125   {-initialize HMAC context with hash descr phash^ and skey}
126 begin
127   if phash<>nil then hmac_init(ctx, phash, @skey[1], length(skey));
128 end;
129 
130 
131 {---------------------------------------------------------------------------}
132 procedure hmac_update(var ctx: THMAC_Context; data: pointer; dlen: word);
133   {-HMAC data input, may be called more than once}
134 begin
135   with ctx do begin
136     if phashd<>nil then phashd^.HUpdateXL(hashctx, data, dlen);
137   end;
138 end;
139 
140 
141 {---------------------------------------------------------------------------}
142 procedure hmac_updateXL(var ctx: THMAC_Context; data: pointer; dlen: longint);
143   {-HMAC data input, may be called more than once}
144 begin
145   with ctx do begin
146     if phashd<>nil then phashd^.HUpdateXL(hashctx, data, dlen);
147   end;
148 end;
149 
150 
151 {---------------------------------------------------------------------------}
152 procedure hmac_final(var ctx: THMAC_Context; var mac: THashDigest);
153   {-end data input, calculate HMAC digest}
154 var
155   i: integer;
156   bl: word;
157 begin
158   with ctx do if phashd<>nil then begin
159     bl := phashd^.HBlockLen;
160     {complete inner hash}
161     phashd^.HFinal(hashctx, mac);
162     {remove ipad from buf, XOR opad}
163     for i:=0 to bl-1 do hmacbuf[i] := hmacbuf[i] xor ($36 xor $5c);
164     {outer hash}
165     phashd^.HInit(hashctx);
166     phashd^.HUpdateXL(hashctx, @hmacbuf, bl);
167     phashd^.HUpdateXL(hashctx, @mac, phashd^.HDigestLen);
168     phashd^.HFinal(hashctx, mac);
169   end;
170 end;
171 
172 
173 {---------------------------------------------------------------------------}
174 procedure hmac_final_bits(var ctx: THMAC_Context; var mac: THashDigest; BData: byte; bitlen: integer);
175   {-end data input with bitlen bits (MSB format) from BData, calculate HMAC digest}
176 var
177   i: integer;
178   bl: word;
179 begin
180   with ctx do if phashd<>nil then begin
181     bl := phashd^.HBlockLen;
182     {complete inner hash}
183     phashd^.HFinalBit(hashctx, mac, BData, bitlen);
184     {remove ipad from buf, XOR opad}
185     for i:=0 to bl-1 do hmacbuf[i] := hmacbuf[i] xor ($36 xor $5c);
186     {outer hash}
187     phashd^.HInit(hashctx);
188     phashd^.HUpdateXL(hashctx, @hmacbuf, bl);
189     phashd^.HUpdateXL(hashctx, @mac, phashd^.HDigestLen);
190     phashd^.HFinal(hashctx, mac);
191   end;
192 end;
193 
194 end.
195