|  | #include "os.h" | 
|  | #include <libsec.h> | 
|  |  | 
|  | /* | 
|  | *  rfc1321 requires that I include this.  The code is new.  The constants | 
|  | *  all come from the rfc (hence the copyright).  We trade a table for the | 
|  | *  macros in rfc.  The total size is a lot less. -- presotto | 
|  | * | 
|  | *	Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All | 
|  | *	rights reserved. | 
|  | * | 
|  | *	License to copy and use this software is granted provided that it | 
|  | *	is identified as the "RSA Data Security, Inc. MD5 Message-Digest | 
|  | *	Algorithm" in all material mentioning or referencing this software | 
|  | *	or this function. | 
|  | * | 
|  | *	License is also granted to make and use derivative works provided | 
|  | *	that such works are identified as "derived from the RSA Data | 
|  | *	Security, Inc. MD5 Message-Digest Algorithm" in all material | 
|  | *	mentioning or referencing the derived work. | 
|  | * | 
|  | *	RSA Data Security, Inc. makes no representations concerning either | 
|  | *	the merchantability of this software or the suitability of this | 
|  | *	software forany particular purpose. It is provided "as is" | 
|  | *	without express or implied warranty of any kind. | 
|  | *	These notices must be retained in any copies of any part of this | 
|  | *	documentation and/or software. | 
|  | */ | 
|  |  | 
|  | static void encode(uchar*, u32int*, ulong); | 
|  |  | 
|  | extern void _md5block(uchar*, ulong, u32int*); | 
|  |  | 
|  | MD5state* | 
|  | md5(uchar *p, ulong len, uchar *digest, MD5state *s) | 
|  | { | 
|  | u32int x[16]; | 
|  | uchar buf[128]; | 
|  | int i; | 
|  | uchar *e; | 
|  |  | 
|  | if(s == nil){ | 
|  | s = malloc(sizeof(*s)); | 
|  | if(s == nil) | 
|  | return nil; | 
|  | memset(s, 0, sizeof(*s)); | 
|  | s->malloced = 1; | 
|  | } | 
|  |  | 
|  | if(s->seeded == 0){ | 
|  | /* seed the state, these constants would look nicer big-endian */ | 
|  | s->state[0] = 0x67452301; | 
|  | s->state[1] = 0xefcdab89; | 
|  | s->state[2] = 0x98badcfe; | 
|  | s->state[3] = 0x10325476; | 
|  | s->seeded = 1; | 
|  | } | 
|  |  | 
|  | /* fill out the partial 64 byte block from previous calls */ | 
|  | if(s->blen){ | 
|  | i = 64 - s->blen; | 
|  | if(len < i) | 
|  | i = len; | 
|  | memmove(s->buf + s->blen, p, i); | 
|  | len -= i; | 
|  | s->blen += i; | 
|  | p += i; | 
|  | if(s->blen == 64){ | 
|  | _md5block(s->buf, s->blen, s->state); | 
|  | s->len += s->blen; | 
|  | s->blen = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* do 64 byte blocks */ | 
|  | i = len & ~0x3f; | 
|  | if(i){ | 
|  | _md5block(p, i, s->state); | 
|  | s->len += i; | 
|  | len -= i; | 
|  | p += i; | 
|  | } | 
|  |  | 
|  | /* save the left overs if not last call */ | 
|  | if(digest == 0){ | 
|  | if(len){ | 
|  | memmove(s->buf, p, len); | 
|  | s->blen += len; | 
|  | } | 
|  | return s; | 
|  | } | 
|  |  | 
|  | /* | 
|  | *  this is the last time through, pad what's left with 0x80, | 
|  | *  0's, and the input count to create a multiple of 64 bytes | 
|  | */ | 
|  | if(s->blen){ | 
|  | p = s->buf; | 
|  | len = s->blen; | 
|  | } else { | 
|  | memmove(buf, p, len); | 
|  | p = buf; | 
|  | } | 
|  | s->len += len; | 
|  | e = p + len; | 
|  | if(len < 56) | 
|  | i = 56 - len; | 
|  | else | 
|  | i = 120 - len; | 
|  | memset(e, 0, i); | 
|  | *e = 0x80; | 
|  | len += i; | 
|  |  | 
|  | /* append the count */ | 
|  | x[0] = s->len<<3; | 
|  | x[1] = s->len>>29; | 
|  | encode(p+len, x, 8); | 
|  |  | 
|  | /* digest the last part */ | 
|  | _md5block(p, len+8, s->state); | 
|  | s->len += len; | 
|  |  | 
|  | /* return result and free state */ | 
|  | encode(digest, s->state, MD5dlen); | 
|  | if(s->malloced == 1) | 
|  | free(s); | 
|  | return nil; | 
|  | } | 
|  |  | 
|  | /* | 
|  | *	encodes input (u32int) into output (uchar). Assumes len is | 
|  | *	a multiple of 4. | 
|  | */ | 
|  | static void | 
|  | encode(uchar *output, u32int *input, ulong len) | 
|  | { | 
|  | u32int x; | 
|  | uchar *e; | 
|  |  | 
|  | for(e = output + len; output < e;) { | 
|  | x = *input++; | 
|  | *output++ = x; | 
|  | *output++ = x >> 8; | 
|  | *output++ = x >> 16; | 
|  | *output++ = x >> 24; | 
|  | } | 
|  | } |