xref: /plan9-contrib/sys/src/cmd/unix/drawterm/libsec/md5.c (revision 9b943567965ba040fd275927fbe088656eb8ce4f)
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