PageRenderTime 80ms CodeModel.GetById 28ms RepoModel.GetById 6ms app.codeStats 0ms

/src/runtime/md5sum.c

https://github.com/bluegnu/mosml
C | 447 lines | 350 code | 46 blank | 51 comment | 28 complexity | 0346bc1a4f1f1a12408e1224d6e73844 MD5 | raw file
Possible License(s): GPL-2.0
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include "mlvalues.h"
  5. #include "alloc.h"
  6. #include "str.h"
  7. #include "md5sum.h"
  8. #ifdef __MWERKS__
  9. #undef nil
  10. #endif
  11. typedef unsigned int my_uint; /* To avoid collision with predefined */
  12. typedef unsigned char byte;
  13. int enc64(byte*,byte*,int);
  14. /* Modified from md5sum.c, obtained from Netlib */
  15. /*
  16. * rfc1321 requires that I include this. The code is new. The constants
  17. * all come from the rfc (hence the copyright). We trade a table for the
  18. * macros in rfc. The total size is a lot less.
  19. * presotto@plan9.bell-labs.com (with tweaks by ehg@netlib.bell-labs.com)
  20. *
  21. * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
  22. * rights reserved.
  23. *
  24. * License to copy and use this software is granted provided that it
  25. * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
  26. * Algorithm" in all material mentioning or referencing this software
  27. * or this function.
  28. *
  29. * License is also granted to make and use derivative works provided
  30. * that such works are identified as "derived from the RSA Data
  31. * Security, Inc. MD5 Message-Digest Algorithm" in all material
  32. * mentioning or referencing the derived work.
  33. *
  34. * RSA Data Security, Inc. makes no representations concerning either
  35. * the merchantability of this software or the suitability of this
  36. * software forany particular purpose. It is provided "as is"
  37. * without express or implied warranty of any kind.
  38. * These notices must be retained in any copies of any part of this
  39. * documentation and/or software.
  40. */
  41. /*
  42. * Rotate amounts used in the algorithm
  43. */
  44. enum
  45. {
  46. S11= 7,
  47. S12= 12,
  48. S13= 17,
  49. S14= 22,
  50. S21= 5,
  51. S22= 9,
  52. S23= 14,
  53. S24= 20,
  54. S31= 4,
  55. S32= 11,
  56. S33= 16,
  57. S34= 23,
  58. S41= 6,
  59. S42= 10,
  60. S43= 15,
  61. S44= 21
  62. };
  63. typedef struct Table
  64. {
  65. my_uint sin; /* integer part of 4294967296 times abs(sin(i)) */
  66. byte x; /* index into data block */
  67. byte rot; /* amount to rotate left by */
  68. }Table;
  69. Table tab[] =
  70. {
  71. /* round 1 */
  72. { 0xd76aa478, 0, S11},
  73. { 0xe8c7b756, 1, S12},
  74. { 0x242070db, 2, S13},
  75. { 0xc1bdceee, 3, S14},
  76. { 0xf57c0faf, 4, S11},
  77. { 0x4787c62a, 5, S12},
  78. { 0xa8304613, 6, S13},
  79. { 0xfd469501, 7, S14},
  80. { 0x698098d8, 8, S11},
  81. { 0x8b44f7af, 9, S12},
  82. { 0xffff5bb1, 10, S13},
  83. { 0x895cd7be, 11, S14},
  84. { 0x6b901122, 12, S11},
  85. { 0xfd987193, 13, S12},
  86. { 0xa679438e, 14, S13},
  87. { 0x49b40821, 15, S14},
  88. /* round 2 */
  89. { 0xf61e2562, 1, S21},
  90. { 0xc040b340, 6, S22},
  91. { 0x265e5a51, 11, S23},
  92. { 0xe9b6c7aa, 0, S24},
  93. { 0xd62f105d, 5, S21},
  94. { 0x2441453, 10, S22},
  95. { 0xd8a1e681, 15, S23},
  96. { 0xe7d3fbc8, 4, S24},
  97. { 0x21e1cde6, 9, S21},
  98. { 0xc33707d6, 14, S22},
  99. { 0xf4d50d87, 3, S23},
  100. { 0x455a14ed, 8, S24},
  101. { 0xa9e3e905, 13, S21},
  102. { 0xfcefa3f8, 2, S22},
  103. { 0x676f02d9, 7, S23},
  104. { 0x8d2a4c8a, 12, S24},
  105. /* round 3 */
  106. { 0xfffa3942, 5, S31},
  107. { 0x8771f681, 8, S32},
  108. { 0x6d9d6122, 11, S33},
  109. { 0xfde5380c, 14, S34},
  110. { 0xa4beea44, 1, S31},
  111. { 0x4bdecfa9, 4, S32},
  112. { 0xf6bb4b60, 7, S33},
  113. { 0xbebfbc70, 10, S34},
  114. { 0x289b7ec6, 13, S31},
  115. { 0xeaa127fa, 0, S32},
  116. { 0xd4ef3085, 3, S33},
  117. { 0x4881d05, 6, S34},
  118. { 0xd9d4d039, 9, S31},
  119. { 0xe6db99e5, 12, S32},
  120. { 0x1fa27cf8, 15, S33},
  121. { 0xc4ac5665, 2, S34},
  122. /* round 4 */
  123. { 0xf4292244, 0, S41},
  124. { 0x432aff97, 7, S42},
  125. { 0xab9423a7, 14, S43},
  126. { 0xfc93a039, 5, S44},
  127. { 0x655b59c3, 12, S41},
  128. { 0x8f0ccc92, 3, S42},
  129. { 0xffeff47d, 10, S43},
  130. { 0x85845dd1, 1, S44},
  131. { 0x6fa87e4f, 8, S41},
  132. { 0xfe2ce6e0, 15, S42},
  133. { 0xa3014314, 6, S43},
  134. { 0x4e0811a1, 13, S44},
  135. { 0xf7537e82, 4, S41},
  136. { 0xbd3af235, 11, S42},
  137. { 0x2ad7d2bb, 2, S43},
  138. { 0xeb86d391, 9, S44},
  139. };
  140. typedef struct MD5state
  141. {
  142. my_uint len;
  143. my_uint state[4];
  144. }MD5state;
  145. MD5state *nil;
  146. void encode(byte*, my_uint*, my_uint);
  147. void decode(my_uint*, byte*, my_uint);
  148. MD5state* md5(byte*, my_uint, byte*, MD5state*);
  149. EXTERN value md5sum(value str) /* ML */
  150. {
  151. byte *buf;
  152. byte digest[16], pr64[25];
  153. int n, len, start;
  154. MD5state *s;
  155. s = nil;
  156. len = string_length(str);
  157. start = 0;
  158. buf = calloc(256,64);
  159. for(;;){
  160. if (len - start < 128*64)
  161. n = len - start;
  162. else
  163. n = 128*64;
  164. bcopy(&Byte(str, start), buf, n);
  165. start += n;
  166. if(n <= 0 || n & 0x3f)
  167. break;
  168. s = md5(buf, n, 0, s);
  169. }
  170. md5(buf, n, digest, s);
  171. enc64(pr64,digest,sizeof(digest));
  172. pr64[22] = '\0'; /* chop trailing == */
  173. free(buf);
  174. return copy_string((char *)pr64);
  175. }
  176. /*
  177. * I require len to be a multiple of 64 for all but
  178. * the last call
  179. */
  180. MD5state*
  181. md5(byte *p, my_uint len, byte *digest, MD5state *s)
  182. {
  183. my_uint a, b, c, d, tmp;
  184. my_uint i, done;
  185. Table *t;
  186. byte *end;
  187. my_uint x[16];
  188. if(s == nil){
  189. s = calloc(sizeof(*s),1);
  190. if(s == nil)
  191. return nil;
  192. /* seed the state, these constants would look nicer big-endian */
  193. s->state[0] = 0x67452301;
  194. s->state[1] = 0xefcdab89;
  195. s->state[2] = 0x98badcfe;
  196. s->state[3] = 0x10325476;
  197. }
  198. s->len += len;
  199. i = len & 0x3f;
  200. if(i || len == 0){
  201. done = 1;
  202. /* pad the input, assume there's room */
  203. if(i < 56)
  204. i = 56 - i;
  205. else
  206. i = 120 - i;
  207. if(i > 0){
  208. memset(p + len, 0, i);
  209. p[len] = 0x80;
  210. }
  211. len += i;
  212. /* append the count */
  213. x[0] = s->len<<3;
  214. x[1] = s->len>>29;
  215. encode(p+len, x, 8);
  216. } else
  217. done = 0;
  218. for(end = p+len; p < end; p += 64){
  219. a = s->state[0];
  220. b = s->state[1];
  221. c = s->state[2];
  222. d = s->state[3];
  223. decode(x, p, 64);
  224. for(i = 0; i < 64; i++){
  225. t = tab + i;
  226. switch(i>>4){
  227. case 0:
  228. a += (b & c) | (~b & d);
  229. break;
  230. case 1:
  231. a += (b & d) | (c & ~d);
  232. break;
  233. case 2:
  234. a += b ^ c ^ d;
  235. break;
  236. case 3:
  237. a += c ^ (b | ~d);
  238. break;
  239. }
  240. a += x[t->x] + t->sin;
  241. a = (a << t->rot) | (a >> (32 - t->rot));
  242. a += b;
  243. /* rotate variables */
  244. tmp = d;
  245. d = c;
  246. c = b;
  247. b = a;
  248. a = tmp;
  249. }
  250. s->state[0] += a;
  251. s->state[1] += b;
  252. s->state[2] += c;
  253. s->state[3] += d;
  254. }
  255. /* return result */
  256. if(done){
  257. encode(digest, s->state, 16);
  258. free(s);
  259. return nil;
  260. }
  261. return s;
  262. }
  263. /*
  264. * encodes input (my_uint) into output (byte). Assumes len is
  265. * a multiple of 4.
  266. */
  267. void
  268. encode(byte *output, my_uint *input, my_uint len)
  269. {
  270. my_uint x;
  271. byte *e;
  272. for(e = output + len; output < e;) {
  273. x = *input++;
  274. *output++ = x;
  275. *output++ = x >> 8;
  276. *output++ = x >> 16;
  277. *output++ = x >> 24;
  278. }
  279. }
  280. /*
  281. * decodes input (byte) into output (my_uint). Assumes len is
  282. * a multiple of 4.
  283. */
  284. void
  285. decode(my_uint *output, byte *input, my_uint len)
  286. {
  287. byte *e;
  288. for(e = input+len; input < e; input += 4)
  289. *output++ = input[0] | (input[1] << 8) |
  290. (input[2] << 16) | (input[3] << 24);
  291. }
  292. typedef unsigned long my_ulong; /* To avoid collision with predefined */
  293. typedef unsigned char my_uchar; /* To avoid collision with predefined */
  294. static my_uchar t64d[256];
  295. static char t64e[64];
  296. static void
  297. init64(void)
  298. {
  299. int c, i;
  300. memset(t64d, 255, 256);
  301. memset(t64e, '=', 64);
  302. i = 0;
  303. for(c = 'A'; c <= 'Z'; c++){
  304. t64e[i] = c;
  305. t64d[c] = i++;
  306. }
  307. for(c = 'a'; c <= 'z'; c++){
  308. t64e[i] = c;
  309. t64d[c] = i++;
  310. }
  311. for(c = '0'; c <= '9'; c++){
  312. t64e[i] = c;
  313. t64d[c] = i++;
  314. }
  315. t64e[i] = '+';
  316. t64d['+'] = i++;
  317. t64e[i] = '/';
  318. t64d['/'] = i;
  319. }
  320. int
  321. dec64(my_uchar *out, char *in, int n)
  322. {
  323. my_ulong b24;
  324. my_uchar *start = out;
  325. int i, c;
  326. if(t64e[0] == 0)
  327. init64();
  328. b24 = 0;
  329. i = 0;
  330. while(n-- > 0){
  331. c = t64d[(int)(unsigned char)(*in++)];
  332. if(c == 255)
  333. continue;
  334. switch(i){
  335. case 0:
  336. b24 = c<<18;
  337. break;
  338. case 1:
  339. b24 |= c<<12;
  340. break;
  341. case 2:
  342. b24 |= c<<6;
  343. break;
  344. case 3:
  345. b24 |= c;
  346. *out++ = b24>>16;
  347. *out++ = b24>>8;
  348. *out++ = b24;
  349. i = -1;
  350. break;
  351. }
  352. i++;
  353. }
  354. switch(i){
  355. case 2:
  356. *out++ = b24>>16;
  357. break;
  358. case 3:
  359. *out++ = b24>>16;
  360. *out++ = b24>>8;
  361. break;
  362. }
  363. *out = 0;
  364. return out - start;
  365. }
  366. int
  367. enc64(byte *out, my_uchar *in, int n)
  368. {
  369. int i;
  370. my_ulong b24;
  371. byte *start = out;
  372. if(t64e[0] == 0)
  373. init64();
  374. for(i = n/3; i > 0; i--){
  375. b24 = (*in++)<<16;
  376. b24 |= (*in++)<<8;
  377. b24 |= *in++;
  378. *out++ = t64e[(b24>>18)];
  379. *out++ = t64e[(b24>>12)&0x3f];
  380. *out++ = t64e[(b24>>6)&0x3f];
  381. *out++ = t64e[(b24)&0x3f];
  382. }
  383. switch(n%3){
  384. case 2:
  385. b24 = (*in++)<<16;
  386. b24 |= (*in)<<8;
  387. *out++ = t64e[(b24>>18)];
  388. *out++ = t64e[(b24>>12)&0x3f];
  389. *out++ = t64e[(b24>>6)&0x3f];
  390. break;
  391. case 1:
  392. b24 = (*in)<<16;
  393. *out++ = t64e[(b24>>18)];
  394. *out++ = t64e[(b24>>12)&0x3f];
  395. *out++ = '=';
  396. break;
  397. }
  398. *out++ = '=';
  399. *out = 0;
  400. return out - start;
  401. }