dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libsum / common / sum-md5.c
blobffe49bdc3b12c1569631f60560158b51631b5414
1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1996-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
23 * md5
26 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
27 rights reserved.
29 License to copy and use this software is granted provided that it
30 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
31 Method" in all material mentioning or referencing this software
32 or this function.
34 License is also granted to make and use derivative works provided
35 that such works are identified as "derived from the RSA Data
36 Security, Inc. MD5 Message-Digest Method" in all material
37 mentioning or referencing the derived work.
39 RSA Data Security, Inc. makes no representations concerning either
40 the merchantability of this software or the suitability of this
41 software for any particular purpose. It is provided "as is"
42 without express or implied warranty of any kind.
44 These notices must be retained in any copies of any part of this
45 documentation and/or software.
48 #define md5_description \
49 "The RSA Data Security, Inc. MD5 Message-Digest Method, 1991-2, \
50 used with permission. The block count is not printed."
51 #define md5_options "[+(version)?md5 (RSA Data Security, Inc. MD5 Message-Digest, 1991-2) 1996-02-29]"
52 #define md5_match "md5|MD5"
53 #define md5_scale 0
55 typedef uint32_t UINT4;
57 typedef struct Md5_s
59 _SUM_PUBLIC_
60 _SUM_PRIVATE_
61 UINT4 state[4]; /* state (ABCD) */
62 UINT4 count[2]; /* # bits handled mod 2^64 (lsb)*/
63 unsigned char buffer[64]; /* input buffer */
64 unsigned char digest[16]; /* final digest */
65 unsigned char digest_sum[16]; /* sum of all digests */
66 } Md5_t;
68 static const unsigned char md5_pad[] =
70 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
81 * encode input into output
82 * len must be a multiple of 4
85 static void
86 md5_encode(register unsigned char* output, register UINT4* input, unsigned int len)
88 register unsigned int i;
89 register unsigned int j;
91 for (i = j = 0; j < len; i++, j += 4)
93 output[j] = (unsigned char)(input[i] & 0xff);
94 output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
95 output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
96 output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
101 * decode input into output
102 * len must be a multiple of 4
105 static void
106 md5_decode(register UINT4* output, register unsigned char* input, unsigned int len)
108 unsigned int i;
109 unsigned int j;
111 for (i = j = 0; j < len; i++, j += 4)
112 output[i] = ((UINT4)input[j]) |
113 (((UINT4)input[j+1]) << 8) |
114 (((UINT4)input[j+2]) << 16) |
115 (((UINT4)input[j+3]) << 24);
118 static int
119 md5_init(Sum_t* p)
121 register Md5_t* context = (Md5_t*)p;
123 context->count[0] = context->count[1] = 0;
124 context->state[0] = 0x67452301;
125 context->state[1] = 0xefcdab89;
126 context->state[2] = 0x98badcfe;
127 context->state[3] = 0x10325476;
128 return 0;
131 static Sum_t*
132 md5_open(const Method_t* method, const char* name)
134 Md5_t* p;
136 if (p = newof(0, Md5_t, 1, 0))
138 p->method = (Method_t*)method;
139 p->name = name;
140 md5_init((Sum_t*)p);
142 return (Sum_t*)p;
146 * basic MD5 step -- transforms buf based on in
149 #define S11 7
150 #define S12 12
151 #define S13 17
152 #define S14 22
153 #define S21 5
154 #define S22 9
155 #define S23 14
156 #define S24 20
157 #define S31 4
158 #define S32 11
159 #define S33 16
160 #define S34 23
161 #define S41 6
162 #define S42 10
163 #define S43 15
164 #define S44 21
166 /* F, G, H and I are basic MD5 functions */
167 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
168 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
169 #define H(x, y, z) ((x) ^ (y) ^ (z))
170 #define I(x, y, z) ((y) ^ ((x) | (~z)))
172 /* ROTATE_LEFT rotates x left n bits */
173 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
175 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
176 /* Rotation is separate from addition to prevent recomputation */
177 #define FF(a, b, c, d, x, s, ac) { \
178 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
179 (a) = ROTATE_LEFT ((a), (s)); \
180 (a) += (b); \
182 #define GG(a, b, c, d, x, s, ac) { \
183 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
184 (a) = ROTATE_LEFT ((a), (s)); \
185 (a) += (b); \
187 #define HH(a, b, c, d, x, s, ac) { \
188 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
189 (a) = ROTATE_LEFT ((a), (s)); \
190 (a) += (b); \
192 #define II(a, b, c, d, x, s, ac) { \
193 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
194 (a) = ROTATE_LEFT ((a), (s)); \
195 (a) += (b); \
198 static void
199 md5_transform(UINT4 state[4], unsigned char block[64])
201 UINT4 a = state[0];
202 UINT4 b = state[1];
203 UINT4 c = state[2];
204 UINT4 d = state[3];
205 UINT4 x[16];
207 md5_decode(x, block, 64);
209 /* round 1 */
210 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
211 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
212 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
213 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
214 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
215 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
216 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
217 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
218 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
219 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
220 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
221 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
222 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
223 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
224 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
225 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
227 /* round 2 */
228 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
229 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
230 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
231 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
232 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
233 GG (d, a, b, c, x[10], S22, 0x02441453); /* 22 */
234 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
235 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
236 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
237 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
238 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
239 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
240 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
241 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
242 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
243 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
245 /* round 3 */
246 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
247 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
248 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
249 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
250 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
251 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
252 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
253 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
254 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
255 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
256 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
257 HH (b, c, d, a, x[ 6], S34, 0x04881d05); /* 44 */
258 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
259 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
260 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
261 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
263 /* round 4 */
264 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
265 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
266 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
267 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
268 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
269 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
270 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
271 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
272 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
273 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
274 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
275 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
276 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
277 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
278 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
279 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
281 state[0] += a;
282 state[1] += b;
283 state[2] += c;
284 state[3] += d;
287 static int
288 md5_block(Sum_t* p, const void* s, size_t inputLen)
290 register Md5_t* context = (Md5_t*)p;
291 unsigned char* input = (unsigned char*)s;
292 unsigned int i;
293 unsigned int index;
294 unsigned int partLen;
296 /* compute number of bytes mod 64 */
297 index = (unsigned int)((context->count[0] >> 3) & 0x3f);
299 /* update number of bits */
300 if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3))
301 context->count[1]++;
302 context->count[1] += ((UINT4)inputLen >> 29);
303 partLen = 64 - index;
305 /* transform as many times as possible */
306 if (inputLen >= partLen)
308 memcpy(&context->buffer[index], input, partLen);
309 md5_transform(context->state, context->buffer);
310 for (i = partLen; i + 63 < inputLen; i += 64)
311 md5_transform(context->state, &input[i]);
312 index = 0;
314 else
315 i = 0;
317 /* buffer remaining input */
318 memcpy(&context->buffer[index], &input[i], inputLen - i);
320 return 0;
323 static int
324 md5_done(Sum_t* p)
326 register Md5_t* context = (Md5_t*)p;
327 unsigned char bits[8];
328 unsigned int index;
329 unsigned int padLen;
331 /* save number of bits */
332 md5_encode(bits, context->count, sizeof(bits));
334 /* pad out to 56 mod 64 */
335 index = (unsigned int)((context->count[0] >> 3) & 0x3f);
336 padLen = (index < 56) ? (56 - index) : (120 - index);
337 md5_block(p, md5_pad, padLen);
339 /* append length (before padding) */
340 md5_block(p, bits, sizeof(bits));
342 /* store state in digest */
343 md5_encode(context->digest, context->state, sizeof(context->digest));
345 /* accumulate the digests */
346 for (index = 0; index < elementsof(context->digest); index++)
347 context->digest_sum[index] ^= context->digest[index];
349 return 0;
352 static int
353 md5_print(Sum_t* p, Sfio_t* sp, register int flags, size_t scale)
355 register Md5_t* x = (Md5_t*)p;
356 register unsigned char* d;
357 register int n;
359 d = (flags & SUM_TOTAL) ? x->digest_sum : x->digest;
360 for (n = 0; n < elementsof(x->digest); n++)
361 sfprintf(sp, "%02x", d[n]);
362 return 0;
365 static int
366 md5_data(Sum_t* p, Sumdata_t* data)
368 register Md5_t* x = (Md5_t*)p;
370 data->size = elementsof(x->digest);
371 data->num = 0;
372 data->buf = x->digest;
373 return 0;