vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

md4.c (4260B)


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