1*9b943567SDavid du Colombier #include "../lib9.h" 2*9b943567SDavid du Colombier #include "../libsec/libsec.h" 3*9b943567SDavid du Colombier 4*9b943567SDavid du Colombier /* 5*9b943567SDavid du Colombier * rfc1321 requires that I include this. The code is new. The constants 6*9b943567SDavid du Colombier * all come from the rfc (hence the copyright). We trade a table for the 7*9b943567SDavid du Colombier * macros in rfc. The total size is a lot less. -- presotto 8*9b943567SDavid du Colombier * 9*9b943567SDavid du Colombier * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 10*9b943567SDavid du Colombier * rights reserved. 11*9b943567SDavid du Colombier * 12*9b943567SDavid du Colombier * License to copy and use this software is granted provided that it 13*9b943567SDavid du Colombier * is identified as the "RSA Data Security, Inc. MD5 Message-Digest 14*9b943567SDavid du Colombier * Algorithm" in all material mentioning or referencing this software 15*9b943567SDavid du Colombier * or this function. 16*9b943567SDavid du Colombier * 17*9b943567SDavid du Colombier * License is also granted to make and use derivative works provided 18*9b943567SDavid du Colombier * that such works are identified as "derived from the RSA Data 19*9b943567SDavid du Colombier * Security, Inc. MD5 Message-Digest Algorithm" in all material 20*9b943567SDavid du Colombier * mentioning or referencing the derived work. 21*9b943567SDavid du Colombier * 22*9b943567SDavid du Colombier * RSA Data Security, Inc. makes no representations concerning either 23*9b943567SDavid du Colombier * the merchantability of this software or the suitability of this 24*9b943567SDavid du Colombier * software forany particular purpose. It is provided "as is" 25*9b943567SDavid du Colombier * without express or implied warranty of any kind. 26*9b943567SDavid du Colombier * These notices must be retained in any copies of any part of this 27*9b943567SDavid du Colombier * documentation and/or software. 28*9b943567SDavid du Colombier */ 29*9b943567SDavid du Colombier 30*9b943567SDavid du Colombier static void encode(uchar*, u32int*, ulong); 31*9b943567SDavid du Colombier static void decode(u32int*, uchar*, ulong); 32*9b943567SDavid du Colombier 33*9b943567SDavid du Colombier extern void _md5block(uchar*, ulong, u32int*); 34*9b943567SDavid du Colombier 35*9b943567SDavid du Colombier MD5state* 36*9b943567SDavid du Colombier md5(uchar *p, ulong len, uchar *digest, MD5state *s) 37*9b943567SDavid du Colombier { 38*9b943567SDavid du Colombier u32int x[16]; 39*9b943567SDavid du Colombier uchar buf[128]; 40*9b943567SDavid du Colombier int i; 41*9b943567SDavid du Colombier uchar *e; 42*9b943567SDavid du Colombier 43*9b943567SDavid du Colombier if(s == nil){ 44*9b943567SDavid du Colombier s = malloc(sizeof(*s)); 45*9b943567SDavid du Colombier if(s == nil) 46*9b943567SDavid du Colombier return nil; 47*9b943567SDavid du Colombier memset(s, 0, sizeof(*s)); 48*9b943567SDavid du Colombier s->malloced = 1; 49*9b943567SDavid du Colombier } 50*9b943567SDavid du Colombier 51*9b943567SDavid du Colombier if(s->seeded == 0){ 52*9b943567SDavid du Colombier /* seed the state, these constants would look nicer big-endian */ 53*9b943567SDavid du Colombier s->state[0] = 0x67452301; 54*9b943567SDavid du Colombier s->state[1] = 0xefcdab89; 55*9b943567SDavid du Colombier s->state[2] = 0x98badcfe; 56*9b943567SDavid du Colombier s->state[3] = 0x10325476; 57*9b943567SDavid du Colombier s->seeded = 1; 58*9b943567SDavid du Colombier } 59*9b943567SDavid du Colombier 60*9b943567SDavid du Colombier /* fill out the partial 64 byte block from previous calls */ 61*9b943567SDavid du Colombier if(s->blen){ 62*9b943567SDavid du Colombier i = 64 - s->blen; 63*9b943567SDavid du Colombier if(len < i) 64*9b943567SDavid du Colombier i = len; 65*9b943567SDavid du Colombier memmove(s->buf + s->blen, p, i); 66*9b943567SDavid du Colombier len -= i; 67*9b943567SDavid du Colombier s->blen += i; 68*9b943567SDavid du Colombier p += i; 69*9b943567SDavid du Colombier if(s->blen == 64){ 70*9b943567SDavid du Colombier _md5block(s->buf, s->blen, s->state); 71*9b943567SDavid du Colombier s->len += s->blen; 72*9b943567SDavid du Colombier s->blen = 0; 73*9b943567SDavid du Colombier } 74*9b943567SDavid du Colombier } 75*9b943567SDavid du Colombier 76*9b943567SDavid du Colombier /* do 64 byte blocks */ 77*9b943567SDavid du Colombier i = len & ~0x3f; 78*9b943567SDavid du Colombier if(i){ 79*9b943567SDavid du Colombier _md5block(p, i, s->state); 80*9b943567SDavid du Colombier s->len += i; 81*9b943567SDavid du Colombier len -= i; 82*9b943567SDavid du Colombier p += i; 83*9b943567SDavid du Colombier } 84*9b943567SDavid du Colombier 85*9b943567SDavid du Colombier /* save the left overs if not last call */ 86*9b943567SDavid du Colombier if(digest == 0){ 87*9b943567SDavid du Colombier if(len){ 88*9b943567SDavid du Colombier memmove(s->buf, p, len); 89*9b943567SDavid du Colombier s->blen += len; 90*9b943567SDavid du Colombier } 91*9b943567SDavid du Colombier return s; 92*9b943567SDavid du Colombier } 93*9b943567SDavid du Colombier 94*9b943567SDavid du Colombier /* 95*9b943567SDavid du Colombier * this is the last time through, pad what's left with 0x80, 96*9b943567SDavid du Colombier * 0's, and the input count to create a multiple of 64 bytes 97*9b943567SDavid du Colombier */ 98*9b943567SDavid du Colombier if(s->blen){ 99*9b943567SDavid du Colombier p = s->buf; 100*9b943567SDavid du Colombier len = s->blen; 101*9b943567SDavid du Colombier } else { 102*9b943567SDavid du Colombier memmove(buf, p, len); 103*9b943567SDavid du Colombier p = buf; 104*9b943567SDavid du Colombier } 105*9b943567SDavid du Colombier s->len += len; 106*9b943567SDavid du Colombier e = p + len; 107*9b943567SDavid du Colombier if(len < 56) 108*9b943567SDavid du Colombier i = 56 - len; 109*9b943567SDavid du Colombier else 110*9b943567SDavid du Colombier i = 120 - len; 111*9b943567SDavid du Colombier memset(e, 0, i); 112*9b943567SDavid du Colombier *e = 0x80; 113*9b943567SDavid du Colombier len += i; 114*9b943567SDavid du Colombier 115*9b943567SDavid du Colombier /* append the count */ 116*9b943567SDavid du Colombier x[0] = s->len<<3; 117*9b943567SDavid du Colombier x[1] = s->len>>29; 118*9b943567SDavid du Colombier encode(p+len, x, 8); 119*9b943567SDavid du Colombier 120*9b943567SDavid du Colombier /* digest the last part */ 121*9b943567SDavid du Colombier _md5block(p, len+8, s->state); 122*9b943567SDavid du Colombier s->len += len; 123*9b943567SDavid du Colombier 124*9b943567SDavid du Colombier /* return result and free state */ 125*9b943567SDavid du Colombier encode(digest, s->state, MD5dlen); 126*9b943567SDavid du Colombier if(s->malloced == 1) 127*9b943567SDavid du Colombier free(s); 128*9b943567SDavid du Colombier return nil; 129*9b943567SDavid du Colombier } 130*9b943567SDavid du Colombier 131*9b943567SDavid du Colombier /* 132*9b943567SDavid du Colombier * encodes input (u32int) into output (uchar). Assumes len is 133*9b943567SDavid du Colombier * a multiple of 4. 134*9b943567SDavid du Colombier */ 135*9b943567SDavid du Colombier static void 136*9b943567SDavid du Colombier encode(uchar *output, u32int *input, ulong len) 137*9b943567SDavid du Colombier { 138*9b943567SDavid du Colombier u32int x; 139*9b943567SDavid du Colombier uchar *e; 140*9b943567SDavid du Colombier 141*9b943567SDavid du Colombier for(e = output + len; output < e;) { 142*9b943567SDavid du Colombier x = *input++; 143*9b943567SDavid du Colombier *output++ = x; 144*9b943567SDavid du Colombier *output++ = x >> 8; 145*9b943567SDavid du Colombier *output++ = x >> 16; 146*9b943567SDavid du Colombier *output++ = x >> 24; 147*9b943567SDavid du Colombier } 148*9b943567SDavid du Colombier } 149