sha1.c 8.8 KB

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