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