Imported Debian patch 0.63.0-6
[hcoop/debian/courier-authlib.git] / md5 / md5.c
CommitLineData
d9898ee8 1/*
2** Copyright 1998 - 2000 Double Precision, Inc.
3** See COPYING for distribution information.
4*/
5
6#define MD5_INTERNAL
7#include "md5.h"
8#include <string.h>
9#include <stdlib.h>
10
11static const char rcsid[]="$Id: md5.c,v 1.7 2000/07/30 01:08:09 mrsam Exp $";
12
13#define MD5_BYTE unsigned char
14
15#define MD5_ROL(w,n) \
16 ( (w) << (n) | ( (w) >> (32-(n)) ) )
17
18static MD5_WORD T[64]={
190xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
200xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
210x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
220x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
230xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
240xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
250x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
260xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
270xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
280xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
290x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
300xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
310xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
320x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
330x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
340xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391};
35
36void md5_context_init(struct MD5_CONTEXT *c)
37{
38 if (sizeof(MD5_WORD) != 4) abort();
39
40 c->A=0x67452301;
41 c->B=0xefcdab89;
42 c->C=0x98badcfe;
43 c->D=0x10325476;
44
45 c->blk_ptr=0;
46}
47
48void md5_context_hash(struct MD5_CONTEXT *c,
49 const unsigned char blk[MD5_BLOCK_SIZE])
50{
51MD5_WORD x[16];
52unsigned i, j;
53MD5_WORD A, B, C, D;
54MD5_WORD zz;
55
56 for (i=j=0; i<16; i++)
57 {
58 MD5_WORD w=(MD5_WORD)blk[j++];
59
60 w |= (MD5_WORD)blk[j++] << 8;
61 w |= (MD5_WORD)blk[j++] << 16;
62 w |= (MD5_WORD)blk[j++] << 24;
63 x[i]= w;
64 }
65
66#define F(X,Y,Z) ( ((X) & (Y)) | ( (~(X)) & (Z)))
67#define G(X,Y,Z) ( ((X) & (Z)) | ( (Y) & (~(Z))))
68#define H(X,Y,Z) ( (X) ^ (Y) ^ (Z) )
69#define I(X,Y,Z) ( (Y) ^ ( (X) | (~(Z))))
70
71 A=c->A;
72 B=c->B;
73 C=c->C;
74 D=c->D;
75
76#define ROUND1(a,b,c,d,k,s,i) \
77 { zz=(a + F(b,c,d) + x[k] + T[i]); a=b+MD5_ROL(zz,s); }
78
79 ROUND1(A,B,C,D,0,7,0);
80 ROUND1(D,A,B,C,1,12,1);
81 ROUND1(C,D,A,B,2,17,2);
82 ROUND1(B,C,D,A,3,22,3);
83 ROUND1(A,B,C,D,4,7,4);
84 ROUND1(D,A,B,C,5,12,5);
85 ROUND1(C,D,A,B,6,17,6);
86 ROUND1(B,C,D,A,7,22,7);
87 ROUND1(A,B,C,D,8,7,8);
88 ROUND1(D,A,B,C,9,12,9);
89 ROUND1(C,D,A,B,10,17,10);
90 ROUND1(B,C,D,A,11,22,11);
91 ROUND1(A,B,C,D,12,7,12);
92 ROUND1(D,A,B,C,13,12,13);
93 ROUND1(C,D,A,B,14,17,14);
94 ROUND1(B,C,D,A,15,22,15);
95
96#define ROUND2(a,b,c,d,k,s,i) \
97 { zz=(a + G(b,c,d) + x[k] + T[i]); a = b + MD5_ROL(zz,s); }
98
99 ROUND2(A,B,C,D,1,5,16);
100 ROUND2(D,A,B,C,6,9,17);
101 ROUND2(C,D,A,B,11,14,18);
102 ROUND2(B,C,D,A,0,20,19);
103 ROUND2(A,B,C,D,5,5,20);
104 ROUND2(D,A,B,C,10,9,21);
105 ROUND2(C,D,A,B,15,14,22);
106 ROUND2(B,C,D,A,4,20,23);
107 ROUND2(A,B,C,D,9,5,24);
108 ROUND2(D,A,B,C,14,9,25);
109 ROUND2(C,D,A,B,3,14,26);
110 ROUND2(B,C,D,A,8,20,27);
111 ROUND2(A,B,C,D,13,5,28);
112 ROUND2(D,A,B,C,2,9,29);
113 ROUND2(C,D,A,B,7,14,30);
114 ROUND2(B,C,D,A,12,20,31);
115
116#define ROUND3(a,b,c,d,k,s,i) \
117 { zz=(a + H(b,c,d) + x[k] + T[i]); a = b + MD5_ROL(zz,s); }
118
119 ROUND3(A,B,C,D,5,4,32);
120 ROUND3(D,A,B,C,8,11,33);
121 ROUND3(C,D,A,B,11,16,34);
122 ROUND3(B,C,D,A,14,23,35);
123 ROUND3(A,B,C,D,1,4,36);
124 ROUND3(D,A,B,C,4,11,37);
125 ROUND3(C,D,A,B,7,16,38);
126 ROUND3(B,C,D,A,10,23,39);
127 ROUND3(A,B,C,D,13,4,40);
128 ROUND3(D,A,B,C,0,11,41);
129 ROUND3(C,D,A,B,3,16,42);
130 ROUND3(B,C,D,A,6,23,43);
131 ROUND3(A,B,C,D,9,4,44);
132 ROUND3(D,A,B,C,12,11,45);
133 ROUND3(C,D,A,B,15,16,46);
134 ROUND3(B,C,D,A,2,23,47);
135
136#define ROUND4(a,b,c,d,k,s,i) \
137 { zz=(a + I(b,c,d) + x[k] + T[i]); a = b + MD5_ROL(zz,s); }
138
139 ROUND4(A,B,C,D,0,6,48);
140 ROUND4(D,A,B,C,7,10,49);
141 ROUND4(C,D,A,B,14,15,50);
142 ROUND4(B,C,D,A,5,21,51);
143 ROUND4(A,B,C,D,12,6,52);
144 ROUND4(D,A,B,C,3,10,53);
145 ROUND4(C,D,A,B,10,15,54);
146 ROUND4(B,C,D,A,1,21,55);
147 ROUND4(A,B,C,D,8,6,56);
148 ROUND4(D,A,B,C,15,10,57);
149 ROUND4(C,D,A,B,6,15,58);
150 ROUND4(B,C,D,A,13,21,59);
151 ROUND4(A,B,C,D,4,6,60);
152 ROUND4(D,A,B,C,11,10,61);
153 ROUND4(C,D,A,B,2,15,62);
154 ROUND4(B,C,D,A,9,21,63);
155
156 c->A += A;
157 c->B += B;
158 c->C += C;
159 c->D += D;
160}
161
162void md5_context_hashstream(struct MD5_CONTEXT *c, const void *p, unsigned l)
163{
164const unsigned char *cp=(const unsigned char *)p;
165unsigned ll;
166
167 while (l)
168 {
169 if (c->blk_ptr == 0 && l >= MD5_BLOCK_SIZE)
170 {
171 md5_context_hash(c, cp);
172 cp += MD5_BLOCK_SIZE;
173 l -= MD5_BLOCK_SIZE;
174 continue;
175 }
176
177 ll=l;
178 if (ll > MD5_BLOCK_SIZE - c->blk_ptr)
179 ll=MD5_BLOCK_SIZE - c->blk_ptr;
180 memcpy(c->blk + c->blk_ptr, cp, ll);
181 c->blk_ptr += ll;
182 cp += ll;
183 l -= ll;
184 if (c->blk_ptr >= MD5_BLOCK_SIZE)
185 {
186 md5_context_hash(c, c->blk);
187 c->blk_ptr=0;
188 }
189 }
190}
191
192void md5_context_endstream(struct MD5_CONTEXT *c, unsigned long ll)
193{
194unsigned char buf[8];
195
196static unsigned char zero[MD5_BLOCK_SIZE-8];
197MD5_WORD l;
198
199 buf[0]=0x80;
200 md5_context_hashstream(c, buf, 1);
201 while (c->blk_ptr != MD5_BLOCK_SIZE - 8)
202 {
203 if (c->blk_ptr > MD5_BLOCK_SIZE - 8)
204 {
205 md5_context_hashstream(c, zero,
206 MD5_BLOCK_SIZE - c->blk_ptr);
207 continue;
208 }
209 md5_context_hashstream(c, zero,
210 MD5_BLOCK_SIZE - 8 - c->blk_ptr);
211 }
212
213 l= ll;
214
215 l <<= 3;
216
217 buf[0]=l;
218 l >>= 8;
219 buf[1]=l;
220 l >>= 8;
221 buf[2]=l;
222 l >>= 8;
223 buf[3]=l;
224
225 l= ll;
226 l >>= 29;
227 buf[4]=l;
228 l >>= 8;
229 buf[5]=l;
230 l >>= 8;
231 buf[6]=l;
232 l >>= 8;
233 buf[7]=l;
234
235 md5_context_hashstream(c, buf, 8);
236}
237
238void md5_context_digest(struct MD5_CONTEXT *c, MD5_DIGEST d)
239{
240unsigned char *dp=d;
241MD5_WORD w;
242
243#define PUT(c) (w=(c), *dp++ = w, w >>= 8, *dp++ = w, w >>= 8, *dp++ = w, w >>= 8, *dp++ = w)
244
245 PUT(c->A);
246 PUT(c->B);
247 PUT(c->C);
248 PUT(c->D);
249#undef PUT
250}
251
252void md5_context_restore(struct MD5_CONTEXT *c, const MD5_DIGEST d)
253{
254const unsigned char *dp=(unsigned char *)d+MD5_DIGEST_SIZE;
255MD5_WORD w;
256
257#define GET \
258 w=*--dp; w=(w << 8) | *--dp; w=(w << 8) | *--dp; w=(w << 8) | *--dp;
259
260 GET
261 c->D=w;
262 GET
263 c->C=w;
264 GET
265 c->B=w;
266 GET
267 c->A=w;
268 c->blk_ptr=0;
269}
270
271void md5_digest(const void *msg, unsigned int len, MD5_DIGEST d)
272{
273struct MD5_CONTEXT c;
274
275 md5_context_init(&c);
276 md5_context_hashstream(&c, msg, len);
277 md5_context_endstream(&c, len);
278 md5_context_digest(&c, d);
279}