md5c.c revision 1.2 1 1.2 matt /* $NetBSD: md5c.c,v 1.2 2005/12/24 08:34:10 matt Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * This file is derived from the RSA Data Security, Inc. MD5 Message-Digest
5 1.1 christos * Algorithm and has been modified by Jason R. Thorpe <thorpej (at) NetBSD.org>
6 1.1 christos * for portability and formatting.
7 1.1 christos */
8 1.1 christos
9 1.1 christos /*
10 1.1 christos * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
11 1.1 christos * rights reserved.
12 1.1 christos *
13 1.1 christos * License to copy and use this software is granted provided that it
14 1.1 christos * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
15 1.1 christos * Algorithm" in all material mentioning or referencing this software
16 1.1 christos * or this function.
17 1.1 christos *
18 1.1 christos * License is also granted to make and use derivative works provided
19 1.1 christos * that such works are identified as "derived from the RSA Data
20 1.1 christos * Security, Inc. MD5 Message-Digest Algorithm" in all material
21 1.1 christos * mentioning or referencing the derived work.
22 1.1 christos *
23 1.1 christos * RSA Data Security, Inc. makes no representations concerning either
24 1.1 christos * the merchantability of this software or the suitability of this
25 1.1 christos * software for any particular purpose. It is provided "as is"
26 1.1 christos * without express or implied warranty of any kind.
27 1.1 christos *
28 1.1 christos * These notices must be retained in any copies of any part of this
29 1.1 christos * documentation and/or software.
30 1.1 christos */
31 1.1 christos
32 1.1 christos #if defined(_KERNEL) || defined(_STANDALONE)
33 1.1 christos #include <sys/param.h>
34 1.1 christos #include <sys/md5.h>
35 1.2 matt #include <lib/libkern/libkern.h>
36 1.1 christos #else
37 1.1 christos #include <sys/cdefs.h>
38 1.1 christos #if defined(LIBC_SCCS) && !defined(lint)
39 1.2 matt __RCSID("$NetBSD: md5c.c,v 1.2 2005/12/24 08:34:10 matt Exp $");
40 1.1 christos #endif /* LIBC_SCCS and not lint */
41 1.1 christos #include "namespace.h"
42 1.1 christos #include <sys/types.h>
43 1.1 christos #include <assert.h>
44 1.1 christos #include <string.h>
45 1.1 christos #include <md5.h>
46 1.1 christos #endif /* _KERNEL || _STANDALONE */
47 1.1 christos
48 1.1 christos #if HAVE_NBTOOL_CONFIG_H
49 1.1 christos #include "nbtool_config.h"
50 1.1 christos #endif
51 1.1 christos
52 1.1 christos #if !HAVE_MD5_H
53 1.1 christos
54 1.1 christos #define ZEROIZE(d, l) memset((d), 0, (l))
55 1.1 christos
56 1.1 christos typedef unsigned char *POINTER;
57 1.1 christos typedef u_int16_t UINT2;
58 1.1 christos typedef u_int32_t UINT4;
59 1.1 christos
60 1.1 christos /*
61 1.1 christos * Constants for MD5Transform routine.
62 1.1 christos */
63 1.1 christos #define S11 7
64 1.1 christos #define S12 12
65 1.1 christos #define S13 17
66 1.1 christos #define S14 22
67 1.1 christos #define S21 5
68 1.1 christos #define S22 9
69 1.1 christos #define S23 14
70 1.1 christos #define S24 20
71 1.1 christos #define S31 4
72 1.1 christos #define S32 11
73 1.1 christos #define S33 16
74 1.1 christos #define S34 23
75 1.1 christos #define S41 6
76 1.1 christos #define S42 10
77 1.1 christos #define S43 15
78 1.1 christos #define S44 21
79 1.1 christos
80 1.1 christos #if !defined(_KERNEL) && !defined(_STANDALONE) && defined(__weak_alias)
81 1.1 christos __weak_alias(MD5Init,_MD5Init)
82 1.1 christos __weak_alias(MD5Update,_MD5Update)
83 1.1 christos __weak_alias(MD5Final,_MD5Final)
84 1.1 christos __weak_alias(MD5Transform,_MD5Transform)
85 1.1 christos #endif
86 1.1 christos
87 1.1 christos static void MD5Transform __P((UINT4 [4], const unsigned char [64]));
88 1.1 christos
89 1.1 christos static void Encode __P((unsigned char *, UINT4 *, unsigned int));
90 1.1 christos static void Decode __P((UINT4 *, const unsigned char *, unsigned int));
91 1.1 christos
92 1.1 christos /*
93 1.1 christos * Encodes input (UINT4) into output (unsigned char). Assumes len is
94 1.1 christos * a multiple of 4.
95 1.1 christos */
96 1.1 christos static void
97 1.1 christos Encode (output, input, len)
98 1.1 christos unsigned char *output;
99 1.1 christos UINT4 *input;
100 1.1 christos unsigned int len;
101 1.1 christos {
102 1.1 christos unsigned int i, j;
103 1.1 christos
104 1.1 christos for (i = 0, j = 0; j < len; i++, j += 4) {
105 1.1 christos output[j] = (unsigned char)(input[i] & 0xff);
106 1.1 christos output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
107 1.1 christos output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
108 1.1 christos output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
109 1.1 christos }
110 1.1 christos }
111 1.1 christos
112 1.1 christos /*
113 1.1 christos * Decodes input (unsigned char) into output (UINT4). Assumes len is
114 1.1 christos * a multiple of 4.
115 1.1 christos */
116 1.1 christos static void
117 1.1 christos Decode (output, input, len)
118 1.1 christos UINT4 *output;
119 1.1 christos const unsigned char *input;
120 1.1 christos unsigned int len;
121 1.1 christos {
122 1.1 christos unsigned int i, j;
123 1.1 christos
124 1.1 christos for (i = 0, j = 0; j < len; i++, j += 4)
125 1.1 christos output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
126 1.1 christos (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
127 1.1 christos }
128 1.1 christos
129 1.1 christos static const unsigned char PADDING[64] = {
130 1.1 christos 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
131 1.1 christos 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
132 1.1 christos 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
133 1.1 christos };
134 1.1 christos
135 1.1 christos /*
136 1.1 christos * F, G, H and I are basic MD5 functions.
137 1.1 christos */
138 1.1 christos #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
139 1.1 christos #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
140 1.1 christos #define H(x, y, z) ((x) ^ (y) ^ (z))
141 1.1 christos #define I(x, y, z) ((y) ^ ((x) | (~z)))
142 1.1 christos
143 1.1 christos /*
144 1.1 christos * ROTATE_LEFT rotates x left n bits.
145 1.1 christos */
146 1.1 christos #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
147 1.1 christos
148 1.1 christos /*
149 1.1 christos * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
150 1.1 christos * Rotation is separate from addition to prevent recomputation.
151 1.1 christos */
152 1.1 christos #define FF(a, b, c, d, x, s, ac) { \
153 1.1 christos (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
154 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \
155 1.1 christos (a) += (b); \
156 1.1 christos }
157 1.1 christos
158 1.1 christos #define GG(a, b, c, d, x, s, ac) { \
159 1.1 christos (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
160 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \
161 1.1 christos (a) += (b); \
162 1.1 christos }
163 1.1 christos
164 1.1 christos #define HH(a, b, c, d, x, s, ac) { \
165 1.1 christos (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
166 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \
167 1.1 christos (a) += (b); \
168 1.1 christos }
169 1.1 christos
170 1.1 christos #define II(a, b, c, d, x, s, ac) { \
171 1.1 christos (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
172 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \
173 1.1 christos (a) += (b); \
174 1.1 christos }
175 1.1 christos
176 1.1 christos /*
177 1.1 christos * MD5 initialization. Begins an MD5 operation, writing a new context.
178 1.1 christos */
179 1.1 christos void
180 1.1 christos MD5Init(context)
181 1.1 christos MD5_CTX *context; /* context */
182 1.1 christos {
183 1.1 christos
184 1.1 christos _DIAGASSERT(context != 0);
185 1.1 christos
186 1.1 christos context->count[0] = context->count[1] = 0;
187 1.1 christos
188 1.1 christos /* Load magic initialization constants. */
189 1.1 christos context->state[0] = 0x67452301;
190 1.1 christos context->state[1] = 0xefcdab89;
191 1.1 christos context->state[2] = 0x98badcfe;
192 1.1 christos context->state[3] = 0x10325476;
193 1.1 christos }
194 1.1 christos
195 1.1 christos /*
196 1.1 christos * MD5 block update operation. Continues an MD5 message-digest
197 1.1 christos * operation, processing another message block, and updating the
198 1.1 christos * context.
199 1.1 christos */
200 1.1 christos void
201 1.1 christos MD5Update(context, input, inputLen)
202 1.1 christos MD5_CTX *context; /* context */
203 1.1 christos const unsigned char *input; /* input block */
204 1.1 christos unsigned int inputLen; /* length of input block */
205 1.1 christos {
206 1.1 christos unsigned int i, idx, partLen;
207 1.1 christos
208 1.1 christos _DIAGASSERT(context != 0);
209 1.1 christos _DIAGASSERT(input != 0);
210 1.1 christos
211 1.1 christos /* Compute number of bytes mod 64 */
212 1.1 christos idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
213 1.1 christos
214 1.1 christos /* Update number of bits */
215 1.1 christos if ((context->count[0] += ((UINT4)inputLen << 3))
216 1.1 christos < ((UINT4)inputLen << 3))
217 1.1 christos context->count[1]++;
218 1.1 christos context->count[1] += ((UINT4)inputLen >> 29);
219 1.1 christos
220 1.1 christos partLen = 64 - idx;
221 1.1 christos
222 1.1 christos /* Transform as many times as possible. */
223 1.1 christos if (inputLen >= partLen) {
224 1.1 christos memcpy((POINTER)&context->buffer[idx], input, partLen);
225 1.1 christos MD5Transform(context->state, context->buffer);
226 1.1 christos
227 1.1 christos for (i = partLen; i + 63 < inputLen; i += 64)
228 1.1 christos MD5Transform(context->state, &input[i]);
229 1.1 christos
230 1.1 christos idx = 0;
231 1.1 christos } else
232 1.1 christos i = 0;
233 1.1 christos
234 1.1 christos /* Buffer remaining input */
235 1.1 christos memcpy(&context->buffer[idx], &input[i], inputLen - i);
236 1.1 christos }
237 1.1 christos
238 1.1 christos /*
239 1.1 christos * MD5 finalization. Ends an MD5 message-digest operation, writing the
240 1.1 christos * message digest and zeroing the context.
241 1.1 christos */
242 1.1 christos void
243 1.1 christos MD5Final(digest, context)
244 1.1 christos unsigned char digest[16]; /* message digest */
245 1.1 christos MD5_CTX *context; /* context */
246 1.1 christos {
247 1.1 christos unsigned char bits[8];
248 1.1 christos unsigned int idx, padLen;
249 1.1 christos
250 1.1 christos _DIAGASSERT(digest != 0);
251 1.1 christos _DIAGASSERT(context != 0);
252 1.1 christos
253 1.1 christos /* Save number of bits */
254 1.1 christos Encode(bits, context->count, 8);
255 1.1 christos
256 1.1 christos /* Pad out to 56 mod 64. */
257 1.1 christos idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
258 1.1 christos padLen = (idx < 56) ? (56 - idx) : (120 - idx);
259 1.1 christos MD5Update (context, PADDING, padLen);
260 1.1 christos
261 1.1 christos /* Append length (before padding) */
262 1.1 christos MD5Update(context, bits, 8);
263 1.1 christos
264 1.1 christos /* Store state in digest */
265 1.1 christos Encode(digest, context->state, 16);
266 1.1 christos
267 1.1 christos /* Zeroize sensitive information. */
268 1.1 christos ZEROIZE((POINTER)(void *)context, sizeof(*context));
269 1.1 christos }
270 1.1 christos
271 1.1 christos /*
272 1.1 christos * MD5 basic transformation. Transforms state based on block.
273 1.1 christos */
274 1.1 christos static void
275 1.1 christos MD5Transform(state, block)
276 1.1 christos UINT4 state[4];
277 1.1 christos const unsigned char block[64];
278 1.1 christos {
279 1.1 christos UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
280 1.1 christos
281 1.1 christos Decode(x, block, 64);
282 1.1 christos
283 1.1 christos /* Round 1 */
284 1.1 christos FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
285 1.1 christos FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
286 1.1 christos FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
287 1.1 christos FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
288 1.1 christos FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
289 1.1 christos FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
290 1.1 christos FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
291 1.1 christos FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
292 1.1 christos FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
293 1.1 christos FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
294 1.1 christos FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
295 1.1 christos FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
296 1.1 christos FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
297 1.1 christos FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
298 1.1 christos FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
299 1.1 christos FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
300 1.1 christos
301 1.1 christos /* Round 2 */
302 1.1 christos GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
303 1.1 christos GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
304 1.1 christos GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
305 1.1 christos GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
306 1.1 christos GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
307 1.1 christos GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
308 1.1 christos GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
309 1.1 christos GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
310 1.1 christos GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
311 1.1 christos GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
312 1.1 christos GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
313 1.1 christos GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
314 1.1 christos GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
315 1.1 christos GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
316 1.1 christos GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
317 1.1 christos GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
318 1.1 christos
319 1.1 christos /* Round 3 */
320 1.1 christos HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
321 1.1 christos HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
322 1.1 christos HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
323 1.1 christos HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
324 1.1 christos HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
325 1.1 christos HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
326 1.1 christos HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
327 1.1 christos HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
328 1.1 christos HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
329 1.1 christos HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
330 1.1 christos HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
331 1.1 christos HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
332 1.1 christos HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
333 1.1 christos HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
334 1.1 christos HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
335 1.1 christos HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
336 1.1 christos
337 1.1 christos /* Round 4 */
338 1.1 christos II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
339 1.1 christos II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
340 1.1 christos II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
341 1.1 christos II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
342 1.1 christos II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
343 1.1 christos II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
344 1.1 christos II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
345 1.1 christos II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
346 1.1 christos II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
347 1.1 christos II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
348 1.1 christos II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
349 1.1 christos II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
350 1.1 christos II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
351 1.1 christos II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
352 1.1 christos II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
353 1.1 christos II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
354 1.1 christos
355 1.1 christos state[0] += a;
356 1.1 christos state[1] += b;
357 1.1 christos state[2] += c;
358 1.1 christos state[3] += d;
359 1.1 christos
360 1.1 christos /* Zeroize sensitive information. */
361 1.1 christos ZEROIZE((POINTER)(void *)x, sizeof (x));
362 1.1 christos }
363 1.1 christos
364 1.1 christos #endif /* HAVE_MD5_H */
365