1 /* md5c.c: "RSA Data Security, Inc. MD5 Message-Digest Algorithm"
2 "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm"
4 %%% portions-copyright-cmetz-96
5 Portions of this software are Copyright 1996-1999 by Craig Metz, All Rights
6 Reserved. The Inner Net License Version 2 applies to these portions of
8 You should have received a copy of the license with this software. If
9 you didn't get a copy, you may request one from <license@inner.net>.
11 Portions of this software are Copyright 1995 by Randall Atkinson and Dan
12 McDonald, All Rights Reserved. All Rights under this copyright are assigned
13 to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
14 License Agreement applies to this software.
18 Modified by cmetz for OPIE 2.3. Changed PTR to VOIDPTR.
19 Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
20 Don't play macro games with memset/memcpy. Renamed exported
21 functions to avoid conflicts. Use unified context structure.
22 Modified at NRL for OPIE 2.1. Minor autoconf mods.
23 Modified at NRL for OPIE 2.0.
24 Originally from RSADSI reference code.
26 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
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 Algorithm" in all material mentioning or referencing this software
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 Algorithm" 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.
51 /* Constants for MD5Transform routine.
70 static VOIDRET MD5Transform __P((UINT4[4], unsigned char[64]));
72 static unsigned char PADDING[64] =
74 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
80 * Encodes input (UINT4) into output (unsigned char).
81 * Assumes len is a multiple of 4.
83 static VOIDRET EEncode FUNCTION((output, input, len), unsigned char *output AND UINT4 *input AND unsigned int len)
87 for (i = 0, j = 0; j < len; i++, j += 4) {
88 output[j] = (unsigned char) (input[i] & 0xff);
89 output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
90 output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
91 output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
96 * Decodes input (unsigned char) into output (UINT4).
97 * Assumes len is a multiple of 4.
99 static VOIDRET EDecode FUNCTION((output, input, len), UINT4 *output AND unsigned char *input AND unsigned int len)
103 for (i = 0, j = 0; j < len; i++, j += 4)
104 output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
105 (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
108 /* F, G, H and I are basic MD5 functions. */
109 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
110 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
111 #define H(x, y, z) ((x) ^ (y) ^ (z))
112 #define I(x, y, z) ((y) ^ ((x) | (~z)))
114 /* ROTATE_LEFT rotates x left n bits. */
115 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
117 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
118 Rotation is separate from addition to prevent recomputation. */
120 #define FF(a, b, c, d, x, s, ac) { \
121 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
122 (a) = ROTATE_LEFT ((a), (s)); \
126 #define GG(a, b, c, d, x, s, ac) { \
127 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
128 (a) = ROTATE_LEFT ((a), (s)); \
132 #define HH(a, b, c, d, x, s, ac) { \
133 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
134 (a) = ROTATE_LEFT ((a), (s)); \
138 #define II(a, b, c, d, x, s, ac) { \
139 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
140 (a) = ROTATE_LEFT ((a), (s)); \
144 /* MD5 initialization. Begins an MD5 operation, writing a new context. */
145 VOIDRET opiemd5init FUNCTION((context), struct opiemdx_ctx *context)
147 context->count[0] = context->count[1] = 0;
148 /* Load magic initialization constants. */
149 context->state[0] = 0x67452301;
150 context->state[1] = 0xefcdab89;
151 context->state[2] = 0x98badcfe;
152 context->state[3] = 0x10325476;
156 * MD5 block update operation. Continues an MD5 message-digest
157 * operation, processing another message block, and updating the
160 VOIDRET opiemd5update FUNCTION((context, input, inputLen), struct opiemdx_ctx *context AND unsigned char *input AND unsigned int inputLen)
162 unsigned int i, index, partLen;
164 /* Compute number of bytes mod 64 */
165 index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
167 /* Update number of bits */
168 if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3))
171 context->count[1] += ((UINT4) inputLen >> 29);
172 partLen = 64 - index;
174 /* Transform as many times as possible. */
175 if (inputLen >= partLen) {
176 memcpy((VOIDPTR)&context->buffer[index], (VOIDPTR)input, partLen);
177 MD5Transform(context->state, context->buffer);
179 for (i = partLen; i + 63 < inputLen; i += 64)
180 MD5Transform(context->state, &input[i]);
186 /* Buffer remaining input */
187 memcpy((VOIDPTR) & context->buffer[index],
188 (VOIDPTR) & input[i],
192 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
193 the message digest and zeroizing the context.
195 VOIDRET opiemd5final FUNCTION((digest, context), unsigned char *digest AND struct opiemdx_ctx *context)
197 unsigned char bits[8];
198 unsigned int index, padLen;
200 /* Save number of bits */
201 EEncode(bits, context->count, 8);
203 /* Pad out to 56 mod 64. */
204 index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
205 padLen = (index < 56) ? (56 - index) : (120 - index);
206 opiemd5update(context, PADDING, padLen);
208 /* Append length (before padding) */
209 opiemd5update(context, bits, 8);
211 /* Store state in digest */
212 EEncode(digest, context->state, 16);
214 /* Zeroize sensitive information. */
215 memset((VOIDPTR) context, 0, sizeof(*context));
218 /* MD5 basic transformation. Transforms state based on block. */
219 static VOIDRET MD5Transform FUNCTION((state, block), UINT4 state[4] AND unsigned char block[64])
221 UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
223 EDecode(x, block, 64);
226 FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
227 FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
228 FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
229 FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
230 FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
231 FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
232 FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
233 FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
234 FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
235 FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
236 FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
237 FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
238 FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
239 FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
240 FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
241 FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
244 GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
245 GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
246 GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
247 GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
248 GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
249 GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
250 GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
251 GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
252 GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
253 GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
254 GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
255 GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
256 GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
257 GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
258 GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
259 GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
262 HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
263 HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
264 HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
265 HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
266 HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
267 HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
268 HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
269 HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
270 HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
271 HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
272 HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
273 HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
274 HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
275 HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
276 HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
277 HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
280 II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
281 II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
282 II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
283 II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
284 II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
285 II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
286 II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
287 II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
288 II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
289 II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
290 II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
291 II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
292 II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
293 II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
294 II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
295 II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
302 /* Zeroize sensitive information. */
303 memset((VOIDPTR)x, 0, sizeof(x));