pw_encrypt_md5.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
  3. *
  4. * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
  5. * rights reserved.
  6. *
  7. * License to copy and use this software is granted provided that it
  8. * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
  9. * Algorithm" in all material mentioning or referencing this software
  10. * or this function.
  11. *
  12. * License is also granted to make and use derivative works provided
  13. * that such works are identified as "derived from the RSA Data
  14. * Security, Inc. MD5 Message-Digest Algorithm" in all material
  15. * mentioning or referencing the derived work.
  16. *
  17. * RSA Data Security, Inc. makes no representations concerning either
  18. * the merchantability of this software or the suitability of this
  19. * software for any particular purpose. It is provided "as is"
  20. * without express or implied warranty of any kind.
  21. *
  22. * These notices must be retained in any copies of any part of this
  23. * documentation and/or software.
  24. *
  25. * $FreeBSD: src/lib/libmd/md5c.c,v 1.9.2.1 1999/08/29 14:57:12 peter Exp $
  26. *
  27. * This code is the same as the code published by RSA Inc. It has been
  28. * edited for clarity and style only.
  29. *
  30. * ----------------------------------------------------------------------------
  31. * The md5_crypt() function was taken from freeBSD's libcrypt and contains
  32. * this license:
  33. * "THE BEER-WARE LICENSE" (Revision 42):
  34. * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
  35. * can do whatever you want with this stuff. If we meet some day, and you think
  36. * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
  37. *
  38. * $FreeBSD: src/lib/libcrypt/crypt.c,v 1.7.2.1 1999/08/29 14:56:33 peter Exp $
  39. *
  40. * ----------------------------------------------------------------------------
  41. * On April 19th, 2001 md5_crypt() was modified to make it reentrant
  42. * by Erik Andersen <andersen@uclibc.org>
  43. *
  44. *
  45. * June 28, 2001 Manuel Novoa III
  46. *
  47. * "Un-inlined" code using loops and static const tables in order to
  48. * reduce generated code size (on i386 from approx 4k to approx 2.5k).
  49. *
  50. * June 29, 2001 Manuel Novoa III
  51. *
  52. * Completely removed static PADDING array.
  53. *
  54. * Reintroduced the loop unrolling in MD5_Transform and added the
  55. * MD5_SIZE_OVER_SPEED option for configurability. Define below as:
  56. * 0 fully unrolled loops
  57. * 1 partially unrolled (4 ops per loop)
  58. * 2 no unrolling -- introduces the need to swap 4 variables (slow)
  59. * 3 no unrolling and all 4 loops merged into one with switch
  60. * in each loop (glacial)
  61. * On i386, sizes are roughly (-Os -fno-builtin):
  62. * 0: 3k 1: 2.5k 2: 2.2k 3: 2k
  63. *
  64. * Since SuSv3 does not require crypt_r, modified again August 7, 2002
  65. * by Erik Andersen to remove reentrance stuff...
  66. */
  67. /*
  68. * UNIX password
  69. *
  70. * Use MD5 for what it is best at...
  71. */
  72. #define MD5_OUT_BUFSIZE 36
  73. static char *
  74. NOINLINE
  75. md5_crypt(char result[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned char *salt)
  76. {
  77. char *p;
  78. unsigned char final[17]; /* final[16] exists only to aid in looping */
  79. int sl, pl, i, pw_len;
  80. md5_ctx_t ctx, ctx1;
  81. /* NB: in busybox, "$1$" in salt is always present */
  82. /* Refine the Salt first */
  83. /* Get the length of the salt including "$1$" */
  84. sl = 3;
  85. while (sl < (3 + 8) && salt[sl] && salt[sl] != '$')
  86. sl++;
  87. /* Hash. the password first, since that is what is most unknown */
  88. md5_begin(&ctx);
  89. pw_len = strlen((char*)pw);
  90. md5_hash(&ctx, pw, pw_len);
  91. /* Then the salt including "$1$" */
  92. md5_hash(&ctx, salt, sl);
  93. /* Copy salt to result; skip "$1$" */
  94. memcpy(result, salt, sl);
  95. result[sl] = '$';
  96. salt += 3;
  97. sl -= 3;
  98. /* Then just as many characters of the MD5(pw, salt, pw) */
  99. md5_begin(&ctx1);
  100. md5_hash(&ctx1, pw, pw_len);
  101. md5_hash(&ctx1, salt, sl);
  102. md5_hash(&ctx1, pw, pw_len);
  103. md5_end(&ctx1, final);
  104. for (pl = pw_len; pl > 0; pl -= 16)
  105. md5_hash(&ctx, final, pl > 16 ? 16 : pl);
  106. /* Then something really weird... */
  107. memset(final, 0, sizeof(final));
  108. for (i = pw_len; i; i >>= 1) {
  109. md5_hash(&ctx, ((i & 1) ? final : (const unsigned char *) pw), 1);
  110. }
  111. md5_end(&ctx, final);
  112. /* And now, just to make sure things don't run too fast.
  113. * On a 60 Mhz Pentium this takes 34 msec, so you would
  114. * need 30 seconds to build a 1000 entry dictionary...
  115. */
  116. for (i = 0; i < 1000; i++) {
  117. md5_begin(&ctx1);
  118. if (i & 1)
  119. md5_hash(&ctx1, pw, pw_len);
  120. else
  121. md5_hash(&ctx1, final, 16);
  122. if (i % 3)
  123. md5_hash(&ctx1, salt, sl);
  124. if (i % 7)
  125. md5_hash(&ctx1, pw, pw_len);
  126. if (i & 1)
  127. md5_hash(&ctx1, final, 16);
  128. else
  129. md5_hash(&ctx1, pw, pw_len);
  130. md5_end(&ctx1, final);
  131. }
  132. p = result + sl + 4; /* 12 bytes max (sl is up to 8 bytes) */
  133. /* Add 5*4+2 = 22 bytes of hash, + NUL byte. */
  134. final[16] = final[5];
  135. for (i = 0; i < 5; i++) {
  136. unsigned l = (final[i] << 16) | (final[i+6] << 8) | final[i+12];
  137. p = to64(p, l, 4);
  138. }
  139. p = to64(p, final[11], 2);
  140. *p = '\0';
  141. /* Don't leave anything around in vm they could use. */
  142. memset(final, 0, sizeof(final));
  143. return result;
  144. }