hl_sha1.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * hashlib++ - a simple hash library for C++
  3. *
  4. * Copyright (c) 2007-2010 Benjamin Grüdelbach
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1) Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * 2) Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in
  14. * the documentation and/or other materials provided with the
  15. * distribution.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  21. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  24. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  26. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. //----------------------------------------------------------------------
  29. /*
  30. * The hashlib++ SHA1 implementation is derivative from the sourcecode
  31. * published in RFC 3174
  32. *
  33. * Copyright (C) The Internet Society (2001). All Rights Reserved.
  34. *
  35. * This document and translations of it may be copied and furnished to
  36. * others, and derivative works that comment on or otherwise explain it
  37. * or assist in its implementation may be prepared, copied, published
  38. * and distributed, in whole or in part, without restriction of any
  39. * kind, provided that the above copyright notice and this paragraph are
  40. * included on all such copies and derivative works. However, this
  41. * document itself may not be modified in any way, such as by removing
  42. * the copyright notice or references to the Internet Society or other
  43. * Internet organizations, except as needed for the purpose of
  44. * developing Internet standards in which case the procedures for
  45. * copyrights defined in the Internet Standards process must be
  46. * followed, or as required to translate it into languages other than
  47. * English.
  48. *
  49. * The limited permissions granted above are perpetual and will not be
  50. * revoked by the Internet Society or its successors or assigns.
  51. *
  52. * This document and the information contained herein is provided on an
  53. * "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
  54. * TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
  55. * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
  56. * HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
  57. * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  58. */
  59. //----------------------------------------------------------------------
  60. /**
  61. * @file hl_sha1.cpp
  62. * @brief This file contains the implementation of the SHA1 class
  63. * @date Mo 17 Sep 2007
  64. */
  65. //----------------------------------------------------------------------
  66. //hashlib++ includes
  67. #include "hl_sha1.h"
  68. //----------------------------------------------------------------------
  69. //defines
  70. /*
  71. * Define the SHA1 circular left shift macro
  72. */
  73. #define SHA1CircularShift(bits,word) \
  74. (((word) << (bits)) | ((word) >> (32-(bits))))
  75. //----------------------------------------------------------------------
  76. //private member-functions
  77. /**
  78. * @brief Internal method to padd the message
  79. *
  80. * According to the standard, the message must
  81. * be padded to an even 512 bits. The first
  82. * padding bit must be a '1'. The last 64 bits
  83. * represent the length of the original message.
  84. * All bits in between should be 0.
  85. * This function will pad the message according
  86. * to those rules by filling the Message_Block array
  87. * accordingly. It will also call the
  88. * ProcessMessageBlock function provided appropriately.
  89. * When it returns, it can be assumed that the message
  90. * digest has been computed.
  91. *
  92. * @param context The context to padd
  93. *
  94. */
  95. void SHA1::SHA1PadMessage(HL_SHA1_CTX *context)
  96. {
  97. /*
  98. * Check to see if the current message block is too small to hold
  99. * the initial padding bits and length. If so, we will pad the
  100. * block, process it, and then continue padding into a second
  101. * block.
  102. */
  103. if (context->Message_Block_Index > 55)
  104. {
  105. context->Message_Block[context->Message_Block_Index++] = 0x80;
  106. while(context->Message_Block_Index < 64)
  107. {
  108. context->Message_Block[context->Message_Block_Index++] = 0;
  109. }
  110. SHA1ProcessMessageBlock(context);
  111. while(context->Message_Block_Index < 56)
  112. {
  113. context->Message_Block[context->Message_Block_Index++] = 0;
  114. }
  115. }
  116. else
  117. {
  118. context->Message_Block[context->Message_Block_Index++] = 0x80;
  119. while(context->Message_Block_Index < 56)
  120. {
  121. context->Message_Block[context->Message_Block_Index++] = 0;
  122. }
  123. }
  124. /*
  125. * Store the message length as the last 8 octets
  126. */
  127. context->Message_Block[56] = context->Length_High >> 24;
  128. context->Message_Block[57] = context->Length_High >> 16;
  129. context->Message_Block[58] = context->Length_High >> 8;
  130. context->Message_Block[59] = context->Length_High;
  131. context->Message_Block[60] = context->Length_Low >> 24;
  132. context->Message_Block[61] = context->Length_Low >> 16;
  133. context->Message_Block[62] = context->Length_Low >> 8;
  134. context->Message_Block[63] = context->Length_Low;
  135. SHA1ProcessMessageBlock(context);
  136. }
  137. /**
  138. * @brief This member-function will process the next 512 bits of the
  139. * message stored in the Message_Block array.
  140. *
  141. * Many of the variable names in this code, especially the
  142. * single character names, were used because those were the
  143. * names used in the publication.
  144. *
  145. * @param context The context to process
  146. */
  147. void SHA1::SHA1ProcessMessageBlock(HL_SHA1_CTX *context)
  148. {
  149. const hl_uint32 K[] = { /* Constants defined in SHA-1 */
  150. 0x5A827999,
  151. 0x6ED9EBA1,
  152. 0x8F1BBCDC,
  153. 0xCA62C1D6
  154. };
  155. int t; /* Loop counter */
  156. hl_uint32 temp; /* Temporary word value */
  157. hl_uint32 W[80]; /* Word sequence */
  158. hl_uint32 A, B, C, D, E; /* Word buffers */
  159. /*
  160. * Initialize the first 16 words in the array W
  161. */
  162. for(t = 0; t < 16; t++)
  163. {
  164. W[t] = context->Message_Block[t * 4] << 24;
  165. W[t] |= context->Message_Block[t * 4 + 1] << 16;
  166. W[t] |= context->Message_Block[t * 4 + 2] << 8;
  167. W[t] |= context->Message_Block[t * 4 + 3];
  168. }
  169. for(t = 16; t < 80; t++)
  170. {
  171. W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
  172. }
  173. A = context->Intermediate_Hash[0];
  174. B = context->Intermediate_Hash[1];
  175. C = context->Intermediate_Hash[2];
  176. D = context->Intermediate_Hash[3];
  177. E = context->Intermediate_Hash[4];
  178. for(t = 0; t < 20; t++)
  179. {
  180. temp = SHA1CircularShift(5,A) +
  181. ((B & C) | ((~B) & D)) + E + W[t] + K[0];
  182. E = D;
  183. D = C;
  184. C = SHA1CircularShift(30,B);
  185. B = A;
  186. A = temp;
  187. }
  188. for(t = 20; t < 40; t++)
  189. {
  190. temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
  191. E = D;
  192. D = C;
  193. C = SHA1CircularShift(30,B);
  194. B = A;
  195. A = temp;
  196. }
  197. for(t = 40; t < 60; t++)
  198. {
  199. temp = SHA1CircularShift(5,A) +
  200. ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
  201. E = D;
  202. D = C;
  203. C = SHA1CircularShift(30,B);
  204. B = A;
  205. A = temp;
  206. }
  207. for(t = 60; t < 80; t++)
  208. {
  209. temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
  210. E = D;
  211. D = C;
  212. C = SHA1CircularShift(30,B);
  213. B = A;
  214. A = temp;
  215. }
  216. context->Intermediate_Hash[0] += A;
  217. context->Intermediate_Hash[1] += B;
  218. context->Intermediate_Hash[2] += C;
  219. context->Intermediate_Hash[3] += D;
  220. context->Intermediate_Hash[4] += E;
  221. context->Message_Block_Index = 0;
  222. }
  223. //----------------------------------------------------------------------
  224. //public member-functions
  225. /**
  226. * @brief Resets the sha1 context and starts a new
  227. * hashprocess
  228. * @param context The context to reset
  229. * @return 0 on succes an error number otherwise
  230. */
  231. int SHA1::SHA1Reset(HL_SHA1_CTX *context)
  232. {
  233. if (!context)
  234. {
  235. return shaNull;
  236. }
  237. context->Length_Low = 0;
  238. context->Length_High = 0;
  239. context->Message_Block_Index = 0;
  240. context->Intermediate_Hash[0] = 0x67452301;
  241. context->Intermediate_Hash[1] = 0xEFCDAB89;
  242. context->Intermediate_Hash[2] = 0x98BADCFE;
  243. context->Intermediate_Hash[3] = 0x10325476;
  244. context->Intermediate_Hash[4] = 0xC3D2E1F0;
  245. context->Computed = 0;
  246. context->Corrupted = 0;
  247. return shaSuccess;
  248. }
  249. /**
  250. * @brief Data input.
  251. *
  252. * This memberfunction add data to the specified
  253. * context.
  254. *
  255. * @param context The context to add data to
  256. * @param message_array The data to add
  257. * @param length The length of the data to add
  258. */
  259. int SHA1::SHA1Input( HL_SHA1_CTX *context,
  260. const hl_uint8 *message_array,
  261. unsigned int length)
  262. {
  263. if (!length)
  264. {
  265. return shaSuccess;
  266. }
  267. if (!context || !message_array)
  268. {
  269. return shaNull;
  270. }
  271. if (context->Computed)
  272. {
  273. context->Corrupted = shaStateError;
  274. return shaStateError;
  275. }
  276. if (context->Corrupted)
  277. {
  278. return context->Corrupted;
  279. }
  280. while(length-- && !context->Corrupted)
  281. {
  282. context->Message_Block[context->Message_Block_Index++] =
  283. (*message_array & 0xFF);
  284. context->Length_Low += 8;
  285. if (context->Length_Low == 0)
  286. {
  287. context->Length_High++;
  288. if (context->Length_High == 0)
  289. {
  290. /* Message is too long */
  291. context->Corrupted = 1;
  292. }
  293. }
  294. if (context->Message_Block_Index == 64)
  295. {
  296. SHA1ProcessMessageBlock(context);
  297. }
  298. message_array++;
  299. }
  300. return shaSuccess;
  301. }
  302. /**
  303. * @brief This ends the sha operation, zeroizing the context
  304. * and returning the computed hash.
  305. *
  306. * @param context The context to get the hash from
  307. * @param Message_Digest This is an OUT parameter which
  308. * contains the hash after the menberfunction returns
  309. * @return 0 on succes, an error-code otherwise
  310. */
  311. int SHA1::SHA1Result( HL_SHA1_CTX *context,
  312. hl_uint8 Message_Digest[SHA1HashSize])
  313. {
  314. int i;
  315. if (!context || !Message_Digest)
  316. {
  317. return shaNull;
  318. }
  319. if (context->Corrupted)
  320. {
  321. return context->Corrupted;
  322. }
  323. if (!context->Computed)
  324. {
  325. SHA1PadMessage(context);
  326. for(i=0; i<64; ++i)
  327. {
  328. /* message may be sensitive, clear it out */
  329. context->Message_Block[i] = 0;
  330. }
  331. context->Length_Low = 0; /* and clear length */
  332. context->Length_High = 0;
  333. context->Computed = 1;
  334. }
  335. for(i = 0; i < SHA1HashSize; ++i)
  336. {
  337. Message_Digest[i] = context->Intermediate_Hash[i>>2]
  338. >> 8 * ( 3 - ( i & 0x03 ) );
  339. }
  340. return shaSuccess;
  341. }
  342. //----------------------------------------------------------------------
  343. //EOF