sha1.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*++
  2. Copyright (c) 2015 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. sha1.c
  5. Abstract:
  6. This module implements the SHA-1 hash function.
  7. Author:
  8. Evan Green 13-Jan-2015
  9. Environment:
  10. Any
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "cryptop.h"
  16. //
  17. // --------------------------------------------------------------------- Macros
  18. //
  19. //
  20. // This macro rotates a 32-bit value left by the given number of bits.
  21. //
  22. #define SHA1_ROTATE32(_Value, _ShiftCount) \
  23. (((_Value) << (_ShiftCount)) | ((_Value) >> (32 - (_ShiftCount))))
  24. //
  25. // ---------------------------------------------------------------- Definitions
  26. //
  27. //
  28. // ------------------------------------------------------ Data Type Definitions
  29. //
  30. //
  31. // ----------------------------------------------- Internal Function Prototypes
  32. //
  33. VOID
  34. CypSha1ProcessMessage (
  35. PSHA1_CONTEXT Context
  36. );
  37. VOID
  38. CypSha1PadMessage (
  39. PSHA1_CONTEXT Context
  40. );
  41. //
  42. // -------------------------------------------------------------------- Globals
  43. //
  44. const ULONG CySha1KConstants[4] = {
  45. 0x5A827999UL,
  46. 0x6ED9EBA1UL,
  47. 0x8F1BBCDCUL,
  48. 0xCA62C1D6UL
  49. };
  50. //
  51. // ------------------------------------------------------------------ Functions
  52. //
  53. CRYPTO_API
  54. VOID
  55. CySha1Initialize (
  56. PSHA1_CONTEXT Context
  57. )
  58. /*++
  59. Routine Description:
  60. This routine initializes a SHA-1 context structure, preparing it to accept
  61. and hash data.
  62. Arguments:
  63. Context - Supplies a pointer to the context to initialize.
  64. Return Value:
  65. None.
  66. --*/
  67. {
  68. Context->Length = 0;
  69. Context->BlockIndex = 0;
  70. Context->IntermediateHash[0] = 0x67452301UL;
  71. Context->IntermediateHash[1] = 0xEFCDAB89UL;
  72. Context->IntermediateHash[2] = 0x98BADCFEUL;
  73. Context->IntermediateHash[3] = 0x10325476UL;
  74. Context->IntermediateHash[4] = 0xC3D2E1F0UL;
  75. return;
  76. }
  77. CRYPTO_API
  78. VOID
  79. CySha1AddContent (
  80. PSHA1_CONTEXT Context,
  81. PUCHAR Message,
  82. UINTN Length
  83. )
  84. /*++
  85. Routine Description:
  86. This routine adds data to a SHA-1 digest.
  87. Arguments:
  88. Context - Supplies a pointer to the initialized SHA-1 context.
  89. Message - Supplies a pointer to the buffer containing the bytes.
  90. Length - Supplies the length of the message buffer, in bytes.
  91. Return Value:
  92. None.
  93. --*/
  94. {
  95. while (Length != 0) {
  96. Context->MessageBlock[Context->BlockIndex] = *Message;
  97. Context->BlockIndex += 1;
  98. Context->Length += BITS_PER_BYTE;
  99. if (Context->BlockIndex == sizeof(Context->MessageBlock)) {
  100. CypSha1ProcessMessage(Context);
  101. }
  102. Message += 1;
  103. Length -= 1;
  104. }
  105. return;
  106. }
  107. CRYPTO_API
  108. VOID
  109. CySha1GetHash (
  110. PSHA1_CONTEXT Context,
  111. UCHAR Hash[SHA1_HASH_SIZE]
  112. )
  113. /*++
  114. Routine Description:
  115. This routine computes and returns the final SHA-1 hash value for the
  116. messages that have been previously entered.
  117. Arguments:
  118. Context - Supplies a pointer to the initialized SHA-1 context.
  119. Hash - Supplies a pointer where the final hash value will be returned. This
  120. buffer must be SHA1_HASH_SIZE length in bytes.
  121. Return Value:
  122. None.
  123. --*/
  124. {
  125. INT DigestIndex;
  126. INT ShiftAmount;
  127. CypSha1PadMessage(Context);
  128. Context->Length = 0;
  129. for (DigestIndex = 0; DigestIndex < SHA1_HASH_SIZE; DigestIndex += 1) {
  130. ShiftAmount = (sizeof(ULONG) - 1 - (DigestIndex % sizeof(ULONG))) *
  131. BITS_PER_BYTE;
  132. Hash[DigestIndex] =
  133. Context->IntermediateHash[DigestIndex / sizeof(ULONG)] >>
  134. ShiftAmount;
  135. }
  136. return;
  137. }
  138. //
  139. // --------------------------------------------------------- Internal Functions
  140. //
  141. VOID
  142. CypSha1ProcessMessage (
  143. PSHA1_CONTEXT Context
  144. )
  145. /*++
  146. Routine Description:
  147. This routine processes the 512 bits in the current message block and adds
  148. them to the digest.
  149. Arguments:
  150. Context - Supplies a pointer to the initialized SHA-1 context with a full
  151. message block.
  152. Return Value:
  153. None.
  154. --*/
  155. {
  156. ULONG Block[80];
  157. ULONG BlockA;
  158. ULONG BlockB;
  159. ULONG BlockC;
  160. ULONG BlockD;
  161. ULONG BlockE;
  162. INT Index;
  163. ULONG Value;
  164. //
  165. // Initialize the first 16 words in the block array.
  166. //
  167. for (Index = 0; Index < 16; Index += 1) {
  168. Block[Index] = ((ULONG)Context->MessageBlock[Index * 4] << 24) |
  169. ((ULONG)Context->MessageBlock[(Index * 4) + 1] << 16) |
  170. ((ULONG)Context->MessageBlock[(Index * 4) + 2] << 8) |
  171. (Context->MessageBlock[(Index * 4) + 3]);
  172. }
  173. for (Index = 16; Index < 80; Index += 1) {
  174. Value = Block[Index - 3] ^ Block[Index - 8] ^ Block[Index - 14] ^
  175. Block[Index - 16];
  176. Block[Index] = SHA1_ROTATE32(Value, 1);
  177. }
  178. BlockA = Context->IntermediateHash[0];
  179. BlockB = Context->IntermediateHash[1];
  180. BlockC = Context->IntermediateHash[2];
  181. BlockD = Context->IntermediateHash[3];
  182. BlockE = Context->IntermediateHash[4];
  183. for (Index = 0; Index < 20; Index += 1) {
  184. Value = SHA1_ROTATE32(BlockA, 5) +
  185. ((BlockB & BlockC) | ((~BlockB) & BlockD)) +
  186. BlockE + Block[Index] + CySha1KConstants[0];
  187. BlockE = BlockD;
  188. BlockD = BlockC;
  189. BlockC = SHA1_ROTATE32(BlockB, 30);
  190. BlockB = BlockA;
  191. BlockA = Value;
  192. }
  193. for (Index = 20; Index < 40; Index += 1) {
  194. Value = SHA1_ROTATE32(BlockA, 5) + (BlockB ^ BlockC ^ BlockD) +
  195. BlockE + Block[Index] + CySha1KConstants[1];
  196. BlockE = BlockD;
  197. BlockD = BlockC;
  198. BlockC = SHA1_ROTATE32(BlockB, 30);
  199. BlockB = BlockA;
  200. BlockA = Value;
  201. }
  202. for (Index = 40; Index < 60; Index += 1) {
  203. Value = SHA1_ROTATE32(BlockA, 5) +
  204. ((BlockB & BlockC) | (BlockB & BlockD) | (BlockC & BlockD)) +
  205. BlockE + Block[Index] + CySha1KConstants[2];
  206. BlockE = BlockD;
  207. BlockD = BlockC;
  208. BlockC = SHA1_ROTATE32(BlockB, 30);
  209. BlockB = BlockA;
  210. BlockA = Value;
  211. }
  212. for (Index = 60; Index < 80; Index += 1) {
  213. Value = SHA1_ROTATE32(BlockA, 5) + (BlockB ^ BlockC ^ BlockD) +
  214. BlockE + Block[Index] + CySha1KConstants[3];
  215. BlockE = BlockD;
  216. BlockD = BlockC;
  217. BlockC = SHA1_ROTATE32(BlockB, 30);
  218. BlockB = BlockA;
  219. BlockA = Value;
  220. }
  221. Context->IntermediateHash[0] += BlockA;
  222. Context->IntermediateHash[1] += BlockB;
  223. Context->IntermediateHash[2] += BlockC;
  224. Context->IntermediateHash[3] += BlockD;
  225. Context->IntermediateHash[4] += BlockE;
  226. Context->BlockIndex = 0;
  227. return;
  228. }
  229. VOID
  230. CypSha1PadMessage (
  231. PSHA1_CONTEXT Context
  232. )
  233. /*++
  234. Routine Description:
  235. This routine pads the message out to an even multiple of 512 bits.
  236. The standard specifies that the first padding bit must be a 1, and then the
  237. last 64 bits represent the length of the original message.
  238. Arguments:
  239. Context - Supplies a pointer to the initialized SHA-1 context with a full
  240. message block.
  241. Return Value:
  242. None.
  243. --*/
  244. {
  245. //
  246. // Check to see if the current message block is too small to hold the
  247. // initial padding bits and length. If so, process teh block, then continue
  248. // padding onto a second block.
  249. //
  250. if (Context->BlockIndex > 55) {
  251. Context->MessageBlock[Context->BlockIndex] = 0x80;
  252. Context->BlockIndex += 1;
  253. while (Context->BlockIndex < sizeof(Context->MessageBlock)) {
  254. Context->MessageBlock[Context->BlockIndex] = 0;
  255. Context->BlockIndex += 1;
  256. }
  257. CypSha1ProcessMessage(Context);
  258. while (Context->BlockIndex < 56) {
  259. Context->MessageBlock[Context->BlockIndex] = 0;
  260. Context->BlockIndex += 1;
  261. }
  262. } else {
  263. Context->MessageBlock[Context->BlockIndex] = 0x80;
  264. Context->BlockIndex += 1;
  265. while (Context->BlockIndex < 56) {
  266. Context->MessageBlock[Context->BlockIndex] = 0;
  267. Context->BlockIndex += 1;
  268. }
  269. }
  270. //
  271. // Store the message length in the last 8 octets.
  272. //
  273. Context->MessageBlock[56] = (UCHAR)(Context->Length >> (32 + 24));
  274. Context->MessageBlock[57] = (UCHAR)(Context->Length >> (32 + 16));
  275. Context->MessageBlock[58] = (UCHAR)(Context->Length >> (32 + 8));
  276. Context->MessageBlock[59] = (UCHAR)(Context->Length >> 32);
  277. Context->MessageBlock[60] = (UCHAR)(Context->Length >> 24);
  278. Context->MessageBlock[61] = (UCHAR)(Context->Length >> 16);
  279. Context->MessageBlock[62] = (UCHAR)(Context->Length >> 8);
  280. Context->MessageBlock[63] = (UCHAR)(Context->Length);
  281. CypSha1ProcessMessage(Context);
  282. return;
  283. }