hmac.pas 6.7 KB

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