1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
#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;
}
}
|