hmac.c 6.9 KB

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