md4.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #include "os.h"
  2. #include <libsec.h>
  3. /*
  4. * This MD4 is implemented from the description in Stinson's Cryptography,
  5. * theory and practice. -- presotto
  6. */
  7. /*
  8. * Rotate ammounts used in the algorithm
  9. */
  10. enum
  11. {
  12. S11= 3,
  13. S12= 7,
  14. S13= 11,
  15. S14= 19,
  16. S21= 3,
  17. S22= 5,
  18. S23= 9,
  19. S24= 13,
  20. S31= 3,
  21. S32= 9,
  22. S33= 11,
  23. S34= 15,
  24. };
  25. typedef struct MD4Table MD4Table;
  26. struct MD4Table
  27. {
  28. uchar x; /* index into data block */
  29. uchar rot; /* amount to rotate left by */
  30. };
  31. static MD4Table tab[] =
  32. {
  33. /* round 1 */
  34. /*[0]*/ { 0, S11},
  35. { 1, S12},
  36. { 2, S13},
  37. { 3, S14},
  38. { 4, S11},
  39. { 5, S12},
  40. { 6, S13},
  41. { 7, S14},
  42. { 8, S11},
  43. { 9, S12},
  44. { 10, S13},
  45. { 11, S14},
  46. { 12, S11},
  47. { 13, S12},
  48. { 14, S13},
  49. { 15, S14},
  50. /* round 2 */
  51. /*[16]*/{ 0, S21},
  52. { 4, S22},
  53. { 8, S23},
  54. { 12, S24},
  55. { 1, S21},
  56. { 5, S22},
  57. { 9, S23},
  58. { 13, S24},
  59. { 2, S21},
  60. { 6, S22},
  61. { 10, S23},
  62. { 14, S24},
  63. { 3, S21},
  64. { 7, S22},
  65. { 11, S23},
  66. { 15, S24},
  67. /* round 3 */
  68. /*[32]*/{ 0, S31},
  69. { 8, S32},
  70. { 4, S33},
  71. { 12, S34},
  72. { 2, S31},
  73. { 10, S32},
  74. { 6, S33},
  75. { 14, S34},
  76. { 1, S31},
  77. { 9, S32},
  78. { 5, S33},
  79. { 13, S34},
  80. { 3, S31},
  81. { 11, S32},
  82. { 7, S33},
  83. { 15, S34},
  84. };
  85. static void encode(uchar*, u32int*, ulong);
  86. static void decode(u32int*, uchar*, ulong);
  87. static void
  88. md4block(uchar *p, ulong len, MD4state *s)
  89. {
  90. int i;
  91. u32int a, b, c, d, tmp;
  92. MD4Table *t;
  93. uchar *end;
  94. u32int x[16];
  95. for(end = p+len; p < end; p += 64){
  96. a = s->state[0];
  97. b = s->state[1];
  98. c = s->state[2];
  99. d = s->state[3];
  100. decode(x, p, 64);
  101. for(i = 0; i < 48; i++){
  102. t = tab + i;
  103. switch(i>>4){
  104. case 0:
  105. a += (b & c) | (~b & d);
  106. break;
  107. case 1:
  108. a += ((b & c) | (b & d) | (c & d)) + 0x5A827999;
  109. break;
  110. case 2:
  111. a += (b ^ c ^ d) + 0x6ED9EBA1;
  112. break;
  113. }
  114. a += x[t->x];
  115. a = (a << t->rot) | (a >> (32 - t->rot));
  116. /* rotate variables */
  117. tmp = d;
  118. d = c;
  119. c = b;
  120. b = a;
  121. a = tmp;
  122. }
  123. s->state[0] += a;
  124. s->state[1] += b;
  125. s->state[2] += c;
  126. s->state[3] += d;
  127. s->len += 64;
  128. }
  129. }
  130. MD4state*
  131. md4(uchar *p, ulong len, uchar *digest, MD4state *s)
  132. {
  133. u32int x[16];
  134. uchar buf[128];
  135. int i;
  136. uchar *e;
  137. if(s == nil){
  138. s = malloc(sizeof(*s));
  139. if(s == nil)
  140. return nil;
  141. memset(s, 0, sizeof(*s));
  142. s->malloced = 1;
  143. }
  144. if(s->seeded == 0){
  145. /* seed the state, these constants would look nicer big-endian */
  146. s->state[0] = 0x67452301;
  147. s->state[1] = 0xefcdab89;
  148. s->state[2] = 0x98badcfe;
  149. s->state[3] = 0x10325476;
  150. s->seeded = 1;
  151. }
  152. /* fill out the partial 64 byte block from previous calls */
  153. if(s->blen){
  154. i = 64 - s->blen;
  155. if(len < i)
  156. i = len;
  157. memmove(s->buf + s->blen, p, i);
  158. len -= i;
  159. s->blen += i;
  160. p += i;
  161. if(s->blen == 64){
  162. md4block(s->buf, s->blen, s);
  163. s->blen = 0;
  164. }
  165. }
  166. /* do 64 byte blocks */
  167. i = len & ~0x3f;
  168. if(i){
  169. md4block(p, i, s);
  170. len -= i;
  171. p += i;
  172. }
  173. /* save the left overs if not last call */
  174. if(digest == 0){
  175. if(len){
  176. memmove(s->buf, p, len);
  177. s->blen += len;
  178. }
  179. return s;
  180. }
  181. /*
  182. * this is the last time through, pad what's left with 0x80,
  183. * 0's, and the input count to create a multiple of 64 bytes
  184. */
  185. if(s->blen){
  186. p = s->buf;
  187. len = s->blen;
  188. } else {
  189. memmove(buf, p, len);
  190. p = buf;
  191. }
  192. s->len += len;
  193. e = p + len;
  194. if(len < 56)
  195. i = 56 - len;
  196. else
  197. i = 120 - len;
  198. memset(e, 0, i);
  199. *e = 0x80;
  200. len += i;
  201. /* append the count */
  202. x[0] = s->len<<3;
  203. x[1] = s->len>>29;
  204. encode(p+len, x, 8);
  205. /* digest the last part */
  206. md4block(p, len+8, s);
  207. /* return result and free state */
  208. encode(digest, s->state, MD4dlen);
  209. if(s->malloced == 1)
  210. free(s);
  211. return nil;
  212. }
  213. /*
  214. * encodes input (u32int) into output (uchar). Assumes len is
  215. * a multiple of 4.
  216. */
  217. static void
  218. encode(uchar *output, u32int *input, ulong len)
  219. {
  220. u32int x;
  221. uchar *e;
  222. for(e = output + len; output < e;) {
  223. x = *input++;
  224. *output++ = x;
  225. *output++ = x >> 8;
  226. *output++ = x >> 16;
  227. *output++ = x >> 24;
  228. }
  229. }
  230. /*
  231. * decodes input (uchar) into output (u32int). Assumes len is
  232. * a multiple of 4.
  233. */
  234. static void
  235. decode(u32int *output, uchar *input, ulong len)
  236. {
  237. uchar *e;
  238. for(e = input+len; input < e; input += 4)
  239. *output++ = input[0] | (input[1] << 8) |
  240. (input[2] << 16) | (input[3] << 24);
  241. }