xref: /plan9/sys/src/libsec/port/md5block.c (revision 80ee5cbfe36716af62da8896207e9763b8e3d760)
1*80ee5cbfSDavid du Colombier #include "os.h"
2*80ee5cbfSDavid du Colombier #include <libsec.h>
3*80ee5cbfSDavid du Colombier 
4*80ee5cbfSDavid du Colombier /*
5*80ee5cbfSDavid du Colombier  *  rfc1321 requires that I include this.  The code is new.  The constants
6*80ee5cbfSDavid du Colombier  *  all come from the rfc (hence the copyright).  We trade a table for the
7*80ee5cbfSDavid du Colombier  *  macros in rfc.  The total size is a lot less. -- presotto
8*80ee5cbfSDavid du Colombier  *
9*80ee5cbfSDavid du Colombier  *	Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
10*80ee5cbfSDavid du Colombier  *	rights reserved.
11*80ee5cbfSDavid du Colombier  *
12*80ee5cbfSDavid du Colombier  *	License to copy and use this software is granted provided that it
13*80ee5cbfSDavid du Colombier  *	is identified as the "RSA Data Security, Inc. MD5 Message-Digest
14*80ee5cbfSDavid du Colombier  *	Algorithm" in all material mentioning or referencing this software
15*80ee5cbfSDavid du Colombier  *	or this function.
16*80ee5cbfSDavid du Colombier  *
17*80ee5cbfSDavid du Colombier  *	License is also granted to make and use derivative works provided
18*80ee5cbfSDavid du Colombier  *	that such works are identified as "derived from the RSA Data
19*80ee5cbfSDavid du Colombier  *	Security, Inc. MD5 Message-Digest Algorithm" in all material
20*80ee5cbfSDavid du Colombier  *	mentioning or referencing the derived work.
21*80ee5cbfSDavid du Colombier  *
22*80ee5cbfSDavid du Colombier  *	RSA Data Security, Inc. makes no representations concerning either
23*80ee5cbfSDavid du Colombier  *	the merchantability of this software or the suitability of this
24*80ee5cbfSDavid du Colombier  *	software forany particular purpose. It is provided "as is"
25*80ee5cbfSDavid du Colombier  *	without express or implied warranty of any kind.
26*80ee5cbfSDavid du Colombier  *	These notices must be retained in any copies of any part of this
27*80ee5cbfSDavid du Colombier  *	documentation and/or software.
28*80ee5cbfSDavid du Colombier  */
29*80ee5cbfSDavid du Colombier 
30*80ee5cbfSDavid du Colombier /*
31*80ee5cbfSDavid du Colombier  *	Rotate ammounts used in the algorithm
32*80ee5cbfSDavid du Colombier  */
33*80ee5cbfSDavid du Colombier enum
34*80ee5cbfSDavid du Colombier {
35*80ee5cbfSDavid du Colombier 	S11=	7,
36*80ee5cbfSDavid du Colombier 	S12=	12,
37*80ee5cbfSDavid du Colombier 	S13=	17,
38*80ee5cbfSDavid du Colombier 	S14=	22,
39*80ee5cbfSDavid du Colombier 
40*80ee5cbfSDavid du Colombier 	S21=	5,
41*80ee5cbfSDavid du Colombier 	S22=	9,
42*80ee5cbfSDavid du Colombier 	S23=	14,
43*80ee5cbfSDavid du Colombier 	S24=	20,
44*80ee5cbfSDavid du Colombier 
45*80ee5cbfSDavid du Colombier 	S31=	4,
46*80ee5cbfSDavid du Colombier 	S32=	11,
47*80ee5cbfSDavid du Colombier 	S33=	16,
48*80ee5cbfSDavid du Colombier 	S34=	23,
49*80ee5cbfSDavid du Colombier 
50*80ee5cbfSDavid du Colombier 	S41=	6,
51*80ee5cbfSDavid du Colombier 	S42=	10,
52*80ee5cbfSDavid du Colombier 	S43=	15,
53*80ee5cbfSDavid du Colombier 	S44=	21,
54*80ee5cbfSDavid du Colombier };
55*80ee5cbfSDavid du Colombier 
56*80ee5cbfSDavid du Colombier static u32int md5tab[] =
57*80ee5cbfSDavid du Colombier {
58*80ee5cbfSDavid du Colombier 	/* round 1 */
59*80ee5cbfSDavid du Colombier /*[0]*/	0xd76aa478,
60*80ee5cbfSDavid du Colombier 	0xe8c7b756,
61*80ee5cbfSDavid du Colombier 	0x242070db,
62*80ee5cbfSDavid du Colombier 	0xc1bdceee,
63*80ee5cbfSDavid du Colombier 	0xf57c0faf,
64*80ee5cbfSDavid du Colombier 	0x4787c62a,
65*80ee5cbfSDavid du Colombier 	0xa8304613,
66*80ee5cbfSDavid du Colombier 	0xfd469501,
67*80ee5cbfSDavid du Colombier 	0x698098d8,
68*80ee5cbfSDavid du Colombier 	0x8b44f7af,
69*80ee5cbfSDavid du Colombier 	0xffff5bb1,
70*80ee5cbfSDavid du Colombier 	0x895cd7be,
71*80ee5cbfSDavid du Colombier 	0x6b901122,
72*80ee5cbfSDavid du Colombier 	0xfd987193,
73*80ee5cbfSDavid du Colombier 	0xa679438e,
74*80ee5cbfSDavid du Colombier 	0x49b40821,
75*80ee5cbfSDavid du Colombier 
76*80ee5cbfSDavid du Colombier 	/* round 2 */
77*80ee5cbfSDavid du Colombier /*[16]*/0xf61e2562,
78*80ee5cbfSDavid du Colombier 	0xc040b340,
79*80ee5cbfSDavid du Colombier 	0x265e5a51,
80*80ee5cbfSDavid du Colombier 	0xe9b6c7aa,
81*80ee5cbfSDavid du Colombier 	0xd62f105d,
82*80ee5cbfSDavid du Colombier 	 0x2441453,
83*80ee5cbfSDavid du Colombier 	0xd8a1e681,
84*80ee5cbfSDavid du Colombier 	0xe7d3fbc8,
85*80ee5cbfSDavid du Colombier 	0x21e1cde6,
86*80ee5cbfSDavid du Colombier 	0xc33707d6,
87*80ee5cbfSDavid du Colombier 	0xf4d50d87,
88*80ee5cbfSDavid du Colombier 	0x455a14ed,
89*80ee5cbfSDavid du Colombier 	0xa9e3e905,
90*80ee5cbfSDavid du Colombier 	0xfcefa3f8,
91*80ee5cbfSDavid du Colombier 	0x676f02d9,
92*80ee5cbfSDavid du Colombier 	0x8d2a4c8a,
93*80ee5cbfSDavid du Colombier 
94*80ee5cbfSDavid du Colombier 	/* round 3 */
95*80ee5cbfSDavid du Colombier /*[32]*/0xfffa3942,
96*80ee5cbfSDavid du Colombier 	0x8771f681,
97*80ee5cbfSDavid du Colombier 	0x6d9d6122,
98*80ee5cbfSDavid du Colombier 	0xfde5380c,
99*80ee5cbfSDavid du Colombier 	0xa4beea44,
100*80ee5cbfSDavid du Colombier 	0x4bdecfa9,
101*80ee5cbfSDavid du Colombier 	0xf6bb4b60,
102*80ee5cbfSDavid du Colombier 	0xbebfbc70,
103*80ee5cbfSDavid du Colombier 	0x289b7ec6,
104*80ee5cbfSDavid du Colombier 	0xeaa127fa,
105*80ee5cbfSDavid du Colombier 	0xd4ef3085,
106*80ee5cbfSDavid du Colombier 	 0x4881d05,
107*80ee5cbfSDavid du Colombier 	0xd9d4d039,
108*80ee5cbfSDavid du Colombier 	0xe6db99e5,
109*80ee5cbfSDavid du Colombier 	0x1fa27cf8,
110*80ee5cbfSDavid du Colombier 	0xc4ac5665,
111*80ee5cbfSDavid du Colombier 
112*80ee5cbfSDavid du Colombier 	/* round 4 */
113*80ee5cbfSDavid du Colombier /*[48]*/0xf4292244,
114*80ee5cbfSDavid du Colombier 	0x432aff97,
115*80ee5cbfSDavid du Colombier 	0xab9423a7,
116*80ee5cbfSDavid du Colombier 	0xfc93a039,
117*80ee5cbfSDavid du Colombier 	0x655b59c3,
118*80ee5cbfSDavid du Colombier 	0x8f0ccc92,
119*80ee5cbfSDavid du Colombier 	0xffeff47d,
120*80ee5cbfSDavid du Colombier 	0x85845dd1,
121*80ee5cbfSDavid du Colombier 	0x6fa87e4f,
122*80ee5cbfSDavid du Colombier 	0xfe2ce6e0,
123*80ee5cbfSDavid du Colombier 	0xa3014314,
124*80ee5cbfSDavid du Colombier 	0x4e0811a1,
125*80ee5cbfSDavid du Colombier 	0xf7537e82,
126*80ee5cbfSDavid du Colombier 	0xbd3af235,
127*80ee5cbfSDavid du Colombier 	0x2ad7d2bb,
128*80ee5cbfSDavid du Colombier 	0xeb86d391,
129*80ee5cbfSDavid du Colombier };
130*80ee5cbfSDavid du Colombier 
131*80ee5cbfSDavid du Colombier static void decode(u32int*, uchar*, ulong);
132*80ee5cbfSDavid du Colombier extern void _md5block(uchar *p, ulong len, u32int *s);
133*80ee5cbfSDavid du Colombier 
134*80ee5cbfSDavid du Colombier void
_md5block(uchar * p,ulong len,u32int * s)135*80ee5cbfSDavid du Colombier _md5block(uchar *p, ulong len, u32int *s)
136*80ee5cbfSDavid du Colombier {
137*80ee5cbfSDavid du Colombier 	u32int a, b, c, d, sh;
138*80ee5cbfSDavid du Colombier 	u32int *t;
139*80ee5cbfSDavid du Colombier 	uchar *end;
140*80ee5cbfSDavid du Colombier 	u32int x[16];
141*80ee5cbfSDavid du Colombier 
142*80ee5cbfSDavid du Colombier 	for(end = p+len; p < end; p += 64){
143*80ee5cbfSDavid du Colombier 		a = s[0];
144*80ee5cbfSDavid du Colombier 		b = s[1];
145*80ee5cbfSDavid du Colombier 		c = s[2];
146*80ee5cbfSDavid du Colombier 		d = s[3];
147*80ee5cbfSDavid du Colombier 
148*80ee5cbfSDavid du Colombier 		decode(x, p, 64);
149*80ee5cbfSDavid du Colombier 
150*80ee5cbfSDavid du Colombier 		t = md5tab;
151*80ee5cbfSDavid du Colombier 		sh = 0;
152*80ee5cbfSDavid du Colombier 		for(; sh != 16; t += 4){
153*80ee5cbfSDavid du Colombier 			a += ((c ^ d) & b) ^ d;
154*80ee5cbfSDavid du Colombier 			a += x[sh] + t[0];
155*80ee5cbfSDavid du Colombier 			a = (a << S11) | (a >> (32 - S11));
156*80ee5cbfSDavid du Colombier 			a += b;
157*80ee5cbfSDavid du Colombier 
158*80ee5cbfSDavid du Colombier 			d += ((b ^ c) & a) ^ c;
159*80ee5cbfSDavid du Colombier 			d += x[sh + 1] + t[1];
160*80ee5cbfSDavid du Colombier 			d = (d << S12) | (d >> (32 - S12));
161*80ee5cbfSDavid du Colombier 			d += a;
162*80ee5cbfSDavid du Colombier 
163*80ee5cbfSDavid du Colombier 			c += ((a ^ b) & d) ^ b;
164*80ee5cbfSDavid du Colombier 			c += x[sh + 2] + t[2];
165*80ee5cbfSDavid du Colombier 			c = (c << S13) | (c >> (32 - S13));
166*80ee5cbfSDavid du Colombier 			c += d;
167*80ee5cbfSDavid du Colombier 
168*80ee5cbfSDavid du Colombier 			b += ((d ^ a) & c) ^ a;
169*80ee5cbfSDavid du Colombier 			b += x[sh + 3] + t[3];
170*80ee5cbfSDavid du Colombier 			b = (b << S14) | (b >> (32 - S14));
171*80ee5cbfSDavid du Colombier 			b += c;
172*80ee5cbfSDavid du Colombier 
173*80ee5cbfSDavid du Colombier 			sh += 4;
174*80ee5cbfSDavid du Colombier 		}
175*80ee5cbfSDavid du Colombier 		sh = 1;
176*80ee5cbfSDavid du Colombier 		for(; sh != 1+20*4; t += 4){
177*80ee5cbfSDavid du Colombier 			a += ((b ^ c) & d) ^ c;
178*80ee5cbfSDavid du Colombier 			a += x[sh & 0xf] + t[0];
179*80ee5cbfSDavid du Colombier 			a = (a << S21) | (a >> (32 - S21));
180*80ee5cbfSDavid du Colombier 			a += b;
181*80ee5cbfSDavid du Colombier 
182*80ee5cbfSDavid du Colombier 			d += ((a ^ b) & c) ^ b;
183*80ee5cbfSDavid du Colombier 			d += x[(sh + 5) & 0xf] + t[1];
184*80ee5cbfSDavid du Colombier 			d = (d << S22) | (d >> (32 - S22));
185*80ee5cbfSDavid du Colombier 			d += a;
186*80ee5cbfSDavid du Colombier 
187*80ee5cbfSDavid du Colombier 			c += ((d ^ a) & b) ^ a;
188*80ee5cbfSDavid du Colombier 			c += x[(sh + 10) & 0xf] + t[2];
189*80ee5cbfSDavid du Colombier 			c = (c << S23) | (c >> (32 - S23));
190*80ee5cbfSDavid du Colombier 			c += d;
191*80ee5cbfSDavid du Colombier 
192*80ee5cbfSDavid du Colombier 			b += ((c ^ d) & a) ^ d;
193*80ee5cbfSDavid du Colombier 			b += x[(sh + 15) & 0xf] + t[3];
194*80ee5cbfSDavid du Colombier 			b = (b << S24) | (b >> (32 - S24));
195*80ee5cbfSDavid du Colombier 			b += c;
196*80ee5cbfSDavid du Colombier 
197*80ee5cbfSDavid du Colombier 			sh += 20;
198*80ee5cbfSDavid du Colombier 		}
199*80ee5cbfSDavid du Colombier 		sh = 5;
200*80ee5cbfSDavid du Colombier 		for(; sh != 5+12*4; t += 4){
201*80ee5cbfSDavid du Colombier 			a += b ^ c ^ d;
202*80ee5cbfSDavid du Colombier 			a += x[sh & 0xf] + t[0];
203*80ee5cbfSDavid du Colombier 			a = (a << S31) | (a >> (32 - S31));
204*80ee5cbfSDavid du Colombier 			a += b;
205*80ee5cbfSDavid du Colombier 
206*80ee5cbfSDavid du Colombier 			d += a ^ b ^ c;
207*80ee5cbfSDavid du Colombier 			d += x[(sh + 3) & 0xf] + t[1];
208*80ee5cbfSDavid du Colombier 			d = (d << S32) | (d >> (32 - S32));
209*80ee5cbfSDavid du Colombier 			d += a;
210*80ee5cbfSDavid du Colombier 
211*80ee5cbfSDavid du Colombier 			c += d ^ a ^ b;
212*80ee5cbfSDavid du Colombier 			c += x[(sh + 6) & 0xf] + t[2];
213*80ee5cbfSDavid du Colombier 			c = (c << S33) | (c >> (32 - S33));
214*80ee5cbfSDavid du Colombier 			c += d;
215*80ee5cbfSDavid du Colombier 
216*80ee5cbfSDavid du Colombier 			b += c ^ d ^ a;
217*80ee5cbfSDavid du Colombier 			b += x[(sh + 9) & 0xf] + t[3];
218*80ee5cbfSDavid du Colombier 			b = (b << S34) | (b >> (32 - S34));
219*80ee5cbfSDavid du Colombier 			b += c;
220*80ee5cbfSDavid du Colombier 
221*80ee5cbfSDavid du Colombier 			sh += 12;
222*80ee5cbfSDavid du Colombier 		}
223*80ee5cbfSDavid du Colombier 		sh = 0;
224*80ee5cbfSDavid du Colombier 		for(; sh != 28*4; t += 4){
225*80ee5cbfSDavid du Colombier 			a += c ^ (b | ~d);
226*80ee5cbfSDavid du Colombier 			a += x[sh & 0xf] + t[0];
227*80ee5cbfSDavid du Colombier 			a = (a << S41) | (a >> (32 - S41));
228*80ee5cbfSDavid du Colombier 			a += b;
229*80ee5cbfSDavid du Colombier 
230*80ee5cbfSDavid du Colombier 			d += b ^ (a | ~c);
231*80ee5cbfSDavid du Colombier 			d += x[(sh + 7) & 0xf] + t[1];
232*80ee5cbfSDavid du Colombier 			d = (d << S42) | (d >> (32 - S42));
233*80ee5cbfSDavid du Colombier 			d += a;
234*80ee5cbfSDavid du Colombier 
235*80ee5cbfSDavid du Colombier 			c += a ^ (d | ~b);
236*80ee5cbfSDavid du Colombier 			c += x[(sh + 14) & 0xf] + t[2];
237*80ee5cbfSDavid du Colombier 			c = (c << S43) | (c >> (32 - S43));
238*80ee5cbfSDavid du Colombier 			c += d;
239*80ee5cbfSDavid du Colombier 
240*80ee5cbfSDavid du Colombier 			b += d ^ (c | ~a);
241*80ee5cbfSDavid du Colombier 			b += x[(sh + 21) & 0xf] + t[3];
242*80ee5cbfSDavid du Colombier 			b = (b << S44) | (b >> (32 - S44));
243*80ee5cbfSDavid du Colombier 			b += c;
244*80ee5cbfSDavid du Colombier 
245*80ee5cbfSDavid du Colombier 			sh += 28;
246*80ee5cbfSDavid du Colombier 		}
247*80ee5cbfSDavid du Colombier 
248*80ee5cbfSDavid du Colombier 		s[0] += a;
249*80ee5cbfSDavid du Colombier 		s[1] += b;
250*80ee5cbfSDavid du Colombier 		s[2] += c;
251*80ee5cbfSDavid du Colombier 		s[3] += d;
252*80ee5cbfSDavid du Colombier 	}
253*80ee5cbfSDavid du Colombier }
254*80ee5cbfSDavid du Colombier 
255*80ee5cbfSDavid du Colombier /*
256*80ee5cbfSDavid du Colombier  *	decodes input (uchar) into output (u32int). Assumes len is
257*80ee5cbfSDavid du Colombier  *	a multiple of 4.
258*80ee5cbfSDavid du Colombier  */
259*80ee5cbfSDavid du Colombier static void
decode(u32int * output,uchar * input,ulong len)260*80ee5cbfSDavid du Colombier decode(u32int *output, uchar *input, ulong len)
261*80ee5cbfSDavid du Colombier {
262*80ee5cbfSDavid du Colombier 	uchar *e;
263*80ee5cbfSDavid du Colombier 
264*80ee5cbfSDavid du Colombier 	for(e = input+len; input < e; input += 4)
265*80ee5cbfSDavid du Colombier 		*output++ = input[0] | (input[1] << 8) |
266*80ee5cbfSDavid du Colombier 			(input[2] << 16) | (input[3] << 24);
267*80ee5cbfSDavid du Colombier }
268