PageRenderTime 24ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/src/libwebtester/md5.c

https://github.com/Nazg-Gul/WebTester
C | 413 lines | 306 code | 54 blank | 53 comment | 35 complexity | a2266105bc2e20ff42685a96b7f654f9 MD5 | raw file
Possible License(s): GPL-2.0
  1. /**
  2. * WebTester Server - server of on-line testing system
  3. *
  4. * MD5 password encryption stuff
  5. *
  6. * Based on PHP MD5 stuff source
  7. *
  8. * Copyright 2008 Sergey I. Sharybin <g.ulairi@gmail.com>
  9. *
  10. * This program can be distributed under the terms of the GNU GPL.
  11. * See the file COPYING.
  12. */
  13. #include "md5.h"
  14. #include <memory.h>
  15. unsigned char PADDING[64] ={
  16. 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  17. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  18. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  19. };
  20. unsigned char itoa64[] = // 0 ... 63 => ascii - 64
  21. "@#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  22. void
  23. md5_to64 (char *__s, unsigned int __v, int __n)
  24. {
  25. while (--__n >= 0)
  26. {
  27. *__s++ = itoa64[__v & 0x3f];
  28. __v >>= 6;
  29. }
  30. }
  31. unsigned
  32. md5_strlcpy (char *__dst, const char *__src, unsigned __siz)
  33. {
  34. register char *d = __dst;
  35. register const char *s = __src;
  36. register size_t n = __siz;
  37. /* Copy as many bytes as will fit */
  38. if (n != 0 && --n != 0)
  39. {
  40. do
  41. {
  42. if (!(*d++ = *s++))
  43. break;
  44. }
  45. while (--n != 0);
  46. }
  47. /* Not enough room in dst, add NUL and traverse rest of src */
  48. if (!n)
  49. {
  50. if (__siz != 0)
  51. *d = '\0'; /* NUL-terminate dst */
  52. while (*s++);
  53. }
  54. return (unsigned) (s - __src - 1); /* count does not include NUL */
  55. }
  56. void
  57. md5_init (md5_ctx_t *__context)
  58. {
  59. __context->count[0] = __context->count[1] = 0;
  60. /* Load magic initialization constants */
  61. __context->state[0] = 0x67452301;
  62. __context->state[1] = 0xefcdab89;
  63. __context->state[2] = 0x98badcfe;
  64. __context->state[3] = 0x10325476;
  65. }
  66. void
  67. md5_decode (unsigned int *__output, const unsigned char *__input,
  68. unsigned int __len)
  69. {
  70. unsigned int i, j;
  71. for (i = 0, j = 0; j < __len; i++, j += 4)
  72. {
  73. __output[i] = ((unsigned int) __input[j]) |
  74. (((unsigned int) __input[j + 1]) << 8) |
  75. (((unsigned int) __input[j + 2]) << 16) |
  76. (((unsigned int) __input[j + 3]) << 24);
  77. }
  78. }
  79. void
  80. md5_transform (unsigned int __state[4], const unsigned char __block[64])
  81. {
  82. unsigned int a = __state[0], b = __state[1], c = __state[2], d = __state[3],
  83. x[16];
  84. md5_decode (x, __block, 64);
  85. /* Round 1 */
  86. FF (a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
  87. FF (d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
  88. FF (c, d, a, b, x[2], S13, 0x242070db); /* 3 */
  89. FF (b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
  90. FF (a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
  91. FF (d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
  92. FF (c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
  93. FF (b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
  94. FF (a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
  95. FF (d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
  96. FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
  97. FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
  98. FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
  99. FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
  100. FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
  101. FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
  102. /* Round 2 */
  103. GG (a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
  104. GG (d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
  105. GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
  106. GG (b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
  107. GG (a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
  108. GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
  109. GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
  110. GG (b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
  111. GG (a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
  112. GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
  113. GG (c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
  114. GG (b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
  115. GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
  116. GG (d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
  117. GG (c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
  118. GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
  119. /* Round 3 */
  120. HH (a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
  121. HH (d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
  122. HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
  123. HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
  124. HH (a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
  125. HH (d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
  126. HH (c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
  127. HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
  128. HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
  129. HH (d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
  130. HH (c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
  131. HH (b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
  132. HH (a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
  133. HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
  134. HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
  135. HH (b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
  136. /* Round 4 */
  137. II (a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
  138. II (d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
  139. II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
  140. II (b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
  141. II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
  142. II (d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
  143. II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
  144. II (b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
  145. II (a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
  146. II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
  147. II (c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
  148. II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
  149. II (a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
  150. II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
  151. II (c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
  152. II (b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
  153. __state[0] += a;
  154. __state[1] += b;
  155. __state[2] += c;
  156. __state[3] += d;
  157. /* Zeroize sensitive information */
  158. memset ((unsigned char*) x, 0, sizeof (x));
  159. }
  160. void
  161. md5_update (md5_ctx_t *__context, const unsigned char *__input,
  162. unsigned int __input_len)
  163. {
  164. unsigned int i, index, part_len;
  165. /* Compute number of bytes mod 64 */
  166. index = (unsigned int) ((__context->count[0] >> 3)&0x3F);
  167. /* Update number of bits */
  168. if ((__context->count[0] += ((unsigned int) __input_len << 3)) <
  169. ((unsigned int) __input_len << 3))
  170. {
  171. __context->count[1]++;
  172. }
  173. __context->count[1] += ((unsigned int) __input_len >> 29);
  174. part_len = 64 - index;
  175. /* Transform as many times as possible. */
  176. if (__input_len >= part_len)
  177. {
  178. memcpy ((unsigned char*) & __context->buffer[index],
  179. (unsigned char*) __input, part_len);
  180. md5_transform (__context->state, __context->buffer);
  181. for (i = part_len; i + 63 < __input_len; i += 64)
  182. {
  183. md5_transform (__context->state, &__input[i]);
  184. }
  185. index = 0;
  186. }
  187. else
  188. {
  189. i = 0;
  190. }
  191. /* Buffer remaining input */
  192. memcpy ((unsigned char*) & __context->buffer[index],
  193. (unsigned char*) & __input[i], __input_len - i);
  194. }
  195. void
  196. md5_encode (unsigned char *__output, unsigned int *__input, unsigned int __len)
  197. {
  198. unsigned int i, j;
  199. for (i = 0, j = 0; j < __len; i++, j += 4)
  200. {
  201. __output[j] = (unsigned char) (__input[i] & 0xff);
  202. __output[j + 1] = (unsigned char) ((__input[i] >> 8) & 0xff);
  203. __output[j + 2] = (unsigned char) ((__input[i] >> 16) & 0xff);
  204. __output[j + 3] = (unsigned char) ((__input[i] >> 24) & 0xff);
  205. }
  206. }
  207. void
  208. md5_final (unsigned char __digest[16], md5_ctx_t *__context)
  209. {
  210. unsigned char bits[8];
  211. unsigned int index, pad_len;
  212. /* Save number of bits */
  213. md5_encode (bits, __context->count, 8);
  214. /* Pad out to 56 mod 64 */
  215. index = (unsigned int) ((__context->count[0] >> 3)&0x3f);
  216. pad_len = (index < 56) ? (56 - index) : (120 - index);
  217. md5_update (__context, PADDING, pad_len);
  218. /* Append length (before padding) */
  219. md5_update (__context, bits, 8);
  220. /* Store state in digest */
  221. md5_encode (__digest, __context->state, 16);
  222. /* Zeroize sensitive information */
  223. memset ((unsigned char*) __context, 0, sizeof (*__context));
  224. }
  225. /**
  226. * MD5 crypt string
  227. *
  228. * @param __pw - string to encode
  229. * @param __salt - salt for encoding
  230. * @param __out - output buffer
  231. */
  232. void
  233. md5_crypt (const char *__pw, const char *__salt, char *__out)
  234. {
  235. char passwd[120], *p;
  236. const char *sp, *ep;
  237. unsigned char final[16];
  238. unsigned int i, sl, pwl;
  239. md5_ctx_t ctx, ctx1;
  240. unsigned int l;
  241. int pl;
  242. pwl = (unsigned int) strlen (__pw);
  243. /* Refine the salt first */
  244. sp = __salt;
  245. /* If it starts with the magic string, then skip that */
  246. if (!strncmp (sp, MD5_MAGIC, MD5_MAGIC_LEN))
  247. {
  248. sp += MD5_MAGIC_LEN;
  249. }
  250. /* It stops at the first '$', max 8 chars */
  251. for (ep = sp; *ep != '\0' && *ep != '$' && ep < (sp + 8); ep++)
  252. {
  253. continue;
  254. }
  255. /* get the length of the true salt */
  256. sl = (unsigned int) (ep - sp);
  257. md5_init (&ctx);
  258. /* The password first, since that is what is most unknown */
  259. md5_update (&ctx, (const unsigned char*) __pw, pwl);
  260. /* Then our magic string */
  261. md5_update (&ctx, (const unsigned char*) MD5_MAGIC, MD5_MAGIC_LEN);
  262. /* Then the raw salt */
  263. md5_update (&ctx, (const unsigned char*) sp, sl);
  264. /* Then just as many characters of the MD5(pw,salt,pw) */
  265. md5_init (&ctx1);
  266. md5_update (&ctx1, (const unsigned char*) __pw, pwl);
  267. md5_update (&ctx1, (const unsigned char*) sp, sl);
  268. md5_update (&ctx1, (const unsigned char*) __pw, pwl);
  269. md5_final (final, &ctx1);
  270. for (pl = pwl; pl > 0; pl -= 16)
  271. {
  272. md5_update (&ctx, final, (unsigned int) (pl > 16 ? 16 : pl));
  273. }
  274. /* Don't leave anything around in vm they could use */
  275. memset (final, 0, sizeof (final));
  276. /* Then something really weird... */
  277. for (i = pwl; i != 0; i >>= 1)
  278. {
  279. if ((i & 1) != 0)
  280. {
  281. md5_update (&ctx, final, 1);
  282. }
  283. else
  284. {
  285. md5_update (&ctx, (const unsigned char*) __pw, 1);
  286. }
  287. }
  288. /* Now make the output string */
  289. memcpy (passwd, MD5_MAGIC, MD5_MAGIC_LEN);
  290. md5_strlcpy (passwd + MD5_MAGIC_LEN, sp, sl + 1);
  291. strcat (passwd, "y");
  292. md5_final (final, &ctx);
  293. /*
  294. * And now, just to make sure things don't run too fast. On a 60 MHz
  295. * Pentium this takes 34 msec, so you would need 30 seconds to build
  296. * a 1000 entry dictionary...
  297. */
  298. for (i = 0; i < 1000; i++)
  299. {
  300. md5_init (&ctx1);
  301. if (i & 1)
  302. {
  303. md5_update (&ctx1, (const unsigned char*) __pw, pwl);
  304. }
  305. else
  306. {
  307. md5_update (&ctx1, final, 16);
  308. }
  309. if (i % 3)
  310. {
  311. md5_update (&ctx1, (const unsigned char*) sp, sl);
  312. }
  313. if (i % 7)
  314. {
  315. md5_update (&ctx1, (const unsigned char*) __pw, pwl);
  316. }
  317. if (i & 1)
  318. {
  319. md5_update (&ctx1, final, 16);
  320. }
  321. else
  322. {
  323. md5_update (&ctx1, (const unsigned char*) __pw, pwl);
  324. }
  325. md5_final (final, &ctx1);
  326. }
  327. p = passwd + sl + MD5_MAGIC_LEN + 1;
  328. l = (final[ 0] << 16) | (final[ 6] << 8) | final[12];
  329. md5_to64 (p, l, 4);
  330. p += 4;
  331. l = (final[ 1] << 16) | (final[ 7] << 8) | final[13];
  332. md5_to64 (p, l, 4);
  333. p += 4;
  334. l = (final[ 2] << 16) | (final[ 8] << 8) | final[14];
  335. md5_to64 (p, l, 4);
  336. p += 4;
  337. l = (final[ 3] << 16) | (final[ 9] << 8) | final[15];
  338. md5_to64 (p, l, 4);
  339. p += 4;
  340. l = (final[ 4] << 16) | (final[10] << 8) | final[ 5];
  341. md5_to64 (p, l, 4);
  342. p += 4;
  343. l = final[11];
  344. md5_to64 (p, l, 2);
  345. p += 2;
  346. *p = '\0';
  347. if (__out)
  348. {
  349. int i, len = 0;
  350. for (i = MD5_MAGIC_LEN; i < (int) strlen (passwd); i++)
  351. {
  352. *(__out + len++) = passwd[i];
  353. }
  354. *(__out + len) = 0;
  355. }
  356. /* Don't leave anything around in vm they could use */
  357. memset (final, 0, sizeof (final));
  358. memset (passwd, 0, sizeof (passwd));
  359. }