hmac.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*++
  2. Copyright (c) 2015 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. hmac.c
  9. Abstract:
  10. This module computes a Hashed Message Authentication Code based on a
  11. message, key, and hash function.
  12. Author:
  13. Evan Green 13-Jan-2015
  14. Environment:
  15. Any
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include "cryptop.h"
  21. //
  22. // ---------------------------------------------------------------- Definitions
  23. //
  24. //
  25. // ------------------------------------------------------ Data Type Definitions
  26. //
  27. //
  28. // ----------------------------------------------- Internal Function Prototypes
  29. //
  30. //
  31. // -------------------------------------------------------------------- Globals
  32. //
  33. //
  34. // ------------------------------------------------------------------ Functions
  35. //
  36. CRYPTO_API
  37. VOID
  38. CySha1ComputeHmac (
  39. PUCHAR Message,
  40. ULONG Length,
  41. PUCHAR Key,
  42. ULONG KeyLength,
  43. UCHAR Digest[SHA1_HASH_SIZE]
  44. )
  45. /*++
  46. Routine Description:
  47. This routine obtains a SHA-1 HMAC signature based on the message and key.
  48. Note that the key must be no longer than the hash function's block size.
  49. Arguments:
  50. Message - Supplies a pointer to the data buffer to hash and sign.
  51. Length - Supplies the length of the message, in bytes.
  52. Key - Supplies a pointer to the secret key buffer.
  53. KeyLength - Supplies the length of the secret key, in bytes. This must be
  54. less than or equal to 64 bytes, the block size of the SHA-1 hash
  55. function.
  56. Digest - Supplies a pointer where the HMAC digest will be returned. This
  57. buffer is assumed to be 20 bytes, the size of a SHA-1 hash.
  58. Return Value:
  59. None.
  60. --*/
  61. {
  62. INT ByteIndex;
  63. SHA1_CONTEXT Context;
  64. UCHAR Ipad[64];
  65. UCHAR Opad[64];
  66. //
  67. // Copy the key into ipad and opad, and pad any remainder with zero.
  68. //
  69. if (KeyLength > sizeof(Ipad)) {
  70. KeyLength = sizeof(Ipad);
  71. }
  72. for (ByteIndex = 0; ByteIndex < KeyLength; ByteIndex += 1) {
  73. Ipad[ByteIndex] = Key[ByteIndex];
  74. Opad[ByteIndex] = Key[ByteIndex];
  75. }
  76. while (ByteIndex < sizeof(Ipad)) {
  77. Ipad[ByteIndex] = 0;
  78. Opad[ByteIndex] = 0;
  79. ByteIndex += 1;
  80. }
  81. //
  82. // XOR in the magic values to ipad and opad.
  83. //
  84. for (ByteIndex = 0; ByteIndex < sizeof(Ipad); ByteIndex += 1) {
  85. Ipad[ByteIndex] ^= 0x36;
  86. Opad[ByteIndex] ^= 0x5C;
  87. }
  88. //
  89. // Perform the double hash.
  90. //
  91. CySha1Initialize(&Context);
  92. CySha1AddContent(&Context, Ipad, sizeof(Ipad));
  93. CySha1AddContent(&Context, Message, Length);
  94. CySha1GetHash(&Context, Digest);
  95. CySha1Initialize(&Context);
  96. CySha1AddContent(&Context, Opad, sizeof(Opad));
  97. CySha1AddContent(&Context, Digest, SHA1_HASH_SIZE);
  98. CySha1GetHash(&Context, Digest);
  99. return;
  100. }
  101. CRYPTO_API
  102. VOID
  103. CySha256ComputeHmac (
  104. PUCHAR Message,
  105. ULONG Length,
  106. PUCHAR Key,
  107. ULONG KeyLength,
  108. UCHAR Digest[SHA256_HASH_SIZE]
  109. )
  110. /*++
  111. Routine Description:
  112. This routine obtains a SHA-256 HMAC signature based on the message and key.
  113. Note that the key must be no longer than the hash function's block size.
  114. Arguments:
  115. Message - Supplies a pointer to the data buffer to hash and sign.
  116. Length - Supplies the length of the message, in bytes.
  117. Key - Supplies a pointer to the secret key buffer.
  118. KeyLength - Supplies the length of the secret key, in bytes. This must be
  119. less than or equal to 64 bytes, the block size of the SHA-1 hash
  120. function.
  121. Digest - Supplies a pointer where the HMAC digest will be returned. This
  122. buffer is assumed to be 64 bytes, the size of a SHA-256 hash.
  123. Return Value:
  124. None.
  125. --*/
  126. {
  127. INT ByteIndex;
  128. SHA256_CONTEXT Context;
  129. UCHAR Ipad[64];
  130. UCHAR Opad[64];
  131. //
  132. // Copy the key into ipad and opad, and pad any remainder with zero.
  133. //
  134. if (KeyLength > sizeof(Ipad)) {
  135. KeyLength = sizeof(Ipad);
  136. }
  137. for (ByteIndex = 0; ByteIndex < KeyLength; ByteIndex += 1) {
  138. Ipad[ByteIndex] = Key[ByteIndex];
  139. Opad[ByteIndex] = Key[ByteIndex];
  140. }
  141. while (ByteIndex < sizeof(Ipad)) {
  142. Ipad[ByteIndex] = 0;
  143. Opad[ByteIndex] = 0;
  144. ByteIndex += 1;
  145. }
  146. //
  147. // XOR in the magic values to ipad and opad.
  148. //
  149. for (ByteIndex = 0; ByteIndex < sizeof(Ipad); ByteIndex += 1) {
  150. Ipad[ByteIndex] ^= 0x36;
  151. Opad[ByteIndex] ^= 0x5C;
  152. }
  153. //
  154. // Perform the double hash.
  155. //
  156. CySha256Initialize(&Context);
  157. CySha256AddContent(&Context, Ipad, sizeof(Ipad));
  158. CySha256AddContent(&Context, Message, Length);
  159. CySha256GetHash(&Context, Digest);
  160. CySha256Initialize(&Context);
  161. CySha256AddContent(&Context, Opad, sizeof(Opad));
  162. CySha256AddContent(&Context, Digest, SHA256_HASH_SIZE);
  163. CySha256GetHash(&Context, Digest);
  164. return;
  165. }
  166. CRYPTO_API
  167. VOID
  168. CyMd5ComputeHmac (
  169. PUCHAR Message,
  170. ULONG Length,
  171. PUCHAR Key,
  172. ULONG KeyLength,
  173. UCHAR Digest[MD5_HASH_SIZE]
  174. )
  175. /*++
  176. Routine Description:
  177. This routine obtains an MD5 HMAC signature based on the message and key.
  178. Note that the key must be no longer than the hash function's block size.
  179. Arguments:
  180. Message - Supplies a pointer to the data buffer to hash and sign.
  181. Length - Supplies the length of the message, in bytes.
  182. Key - Supplies a pointer to the secret key buffer.
  183. KeyLength - Supplies the length of the secret key, in bytes. This must be
  184. less than or equal to 64 bytes, the block size of the SHA-1 hash
  185. function.
  186. Digest - Supplies a pointer where the HMAC digest will be returned. This
  187. buffer is assumed to be 16 bytes, the size of an MD5 hash.
  188. Return Value:
  189. None.
  190. --*/
  191. {
  192. INT ByteIndex;
  193. MD5_CONTEXT Context;
  194. UCHAR Ipad[64];
  195. UCHAR Opad[64];
  196. //
  197. // Copy the key into ipad and opad, and pad any remainder with zero.
  198. //
  199. if (KeyLength > sizeof(Ipad)) {
  200. KeyLength = sizeof(Ipad);
  201. }
  202. for (ByteIndex = 0; ByteIndex < KeyLength; ByteIndex += 1) {
  203. Ipad[ByteIndex] = Key[ByteIndex];
  204. Opad[ByteIndex] = Key[ByteIndex];
  205. }
  206. while (ByteIndex < sizeof(Ipad)) {
  207. Ipad[ByteIndex] = 0;
  208. Opad[ByteIndex] = 0;
  209. ByteIndex += 1;
  210. }
  211. //
  212. // XOR in the magic values to ipad and opad.
  213. //
  214. for (ByteIndex = 0; ByteIndex < sizeof(Ipad); ByteIndex += 1) {
  215. Ipad[ByteIndex] ^= 0x36;
  216. Opad[ByteIndex] ^= 0x5C;
  217. }
  218. //
  219. // Perform the double hash.
  220. //
  221. CyMd5Initialize(&Context);
  222. CyMd5AddContent(&Context, Ipad, sizeof(Ipad));
  223. CyMd5AddContent(&Context, Message, Length);
  224. CyMd5GetHash(&Context, Digest);
  225. CyMd5Initialize(&Context);
  226. CyMd5AddContent(&Context, Opad, sizeof(Opad));
  227. CyMd5AddContent(&Context, Digest, MD5_HASH_SIZE);
  228. CyMd5GetHash(&Context, Digest);
  229. return;
  230. }
  231. //
  232. // --------------------------------------------------------- Internal Functions
  233. //