md5c.c revision 1.4 1 1.4 cegger /* $NetBSD: md5c.c,v 1.4 2009/03/16 05:59:21 cegger 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.4 cegger __RCSID("$NetBSD: md5c.c,v 1.4 2009/03/16 05:59:21 cegger 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.3 apb typedef uint16_t UINT2;
58 1.3 apb typedef uint32_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.4 cegger Encode (unsigned char *output,
98 1.4 cegger UINT4 *input,
99 1.4 cegger unsigned int len)
100 1.1 christos {
101 1.1 christos unsigned int i, j;
102 1.1 christos
103 1.1 christos for (i = 0, j = 0; j < len; i++, j += 4) {
104 1.1 christos output[j] = (unsigned char)(input[i] & 0xff);
105 1.1 christos output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
106 1.1 christos output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
107 1.1 christos output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
108 1.1 christos }
109 1.1 christos }
110 1.1 christos
111 1.1 christos /*
112 1.1 christos * Decodes input (unsigned char) into output (UINT4). Assumes len is
113 1.1 christos * a multiple of 4.
114 1.1 christos */
115 1.1 christos static void
116 1.4 cegger Decode (UINT4 *output,
117 1.4 cegger const unsigned char *input,
118 1.4 cegger unsigned int len)
119 1.1 christos {
120 1.1 christos unsigned int i, j;
121 1.1 christos
122 1.1 christos for (i = 0, j = 0; j < len; i++, j += 4)
123 1.1 christos output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
124 1.1 christos (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
125 1.1 christos }
126 1.1 christos
127 1.1 christos static const unsigned char PADDING[64] = {
128 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,
129 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,
130 1.1 christos 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
131 1.1 christos };
132 1.1 christos
133 1.1 christos /*
134 1.1 christos * F, G, H and I are basic MD5 functions.
135 1.1 christos */
136 1.1 christos #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
137 1.1 christos #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
138 1.1 christos #define H(x, y, z) ((x) ^ (y) ^ (z))
139 1.1 christos #define I(x, y, z) ((y) ^ ((x) | (~z)))
140 1.1 christos
141 1.1 christos /*
142 1.1 christos * ROTATE_LEFT rotates x left n bits.
143 1.1 christos */
144 1.1 christos #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
145 1.1 christos
146 1.1 christos /*
147 1.1 christos * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
148 1.1 christos * Rotation is separate from addition to prevent recomputation.
149 1.1 christos */
150 1.1 christos #define FF(a, b, c, d, x, s, ac) { \
151 1.1 christos (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
152 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \
153 1.1 christos (a) += (b); \
154 1.1 christos }
155 1.1 christos
156 1.1 christos #define GG(a, b, c, d, x, s, ac) { \
157 1.1 christos (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
158 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \
159 1.1 christos (a) += (b); \
160 1.1 christos }
161 1.1 christos
162 1.1 christos #define HH(a, b, c, d, x, s, ac) { \
163 1.1 christos (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
164 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \
165 1.1 christos (a) += (b); \
166 1.1 christos }
167 1.1 christos
168 1.1 christos #define II(a, b, c, d, x, s, ac) { \
169 1.1 christos (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
170 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \
171 1.1 christos (a) += (b); \
172 1.1 christos }
173 1.1 christos
174 1.1 christos /*
175 1.1 christos * MD5 initialization. Begins an MD5 operation, writing a new context.
176 1.1 christos */
177 1.1 christos void
178 1.4 cegger MD5Init(MD5_CTX *context)
179 1.1 christos {
180 1.1 christos
181 1.1 christos _DIAGASSERT(context != 0);
182 1.1 christos
183 1.1 christos context->count[0] = context->count[1] = 0;
184 1.1 christos
185 1.1 christos /* Load magic initialization constants. */
186 1.1 christos context->state[0] = 0x67452301;
187 1.1 christos context->state[1] = 0xefcdab89;
188 1.1 christos context->state[2] = 0x98badcfe;
189 1.1 christos context->state[3] = 0x10325476;
190 1.1 christos }
191 1.1 christos
192 1.1 christos /*
193 1.1 christos * MD5 block update operation. Continues an MD5 message-digest
194 1.1 christos * operation, processing another message block, and updating the
195 1.1 christos * context.
196 1.1 christos */
197 1.1 christos void
198 1.4 cegger MD5Update(MD5_CTX *context,
199 1.4 cegger const unsigned char *input, /* input block */
200 1.4 cegger unsigned int inputLen) /* length of input block */
201 1.1 christos {
202 1.1 christos unsigned int i, idx, partLen;
203 1.1 christos
204 1.1 christos _DIAGASSERT(context != 0);
205 1.1 christos _DIAGASSERT(input != 0);
206 1.1 christos
207 1.1 christos /* Compute number of bytes mod 64 */
208 1.1 christos idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
209 1.1 christos
210 1.1 christos /* Update number of bits */
211 1.1 christos if ((context->count[0] += ((UINT4)inputLen << 3))
212 1.1 christos < ((UINT4)inputLen << 3))
213 1.1 christos context->count[1]++;
214 1.1 christos context->count[1] += ((UINT4)inputLen >> 29);
215 1.1 christos
216 1.1 christos partLen = 64 - idx;
217 1.1 christos
218 1.1 christos /* Transform as many times as possible. */
219 1.1 christos if (inputLen >= partLen) {
220 1.1 christos memcpy((POINTER)&context->buffer[idx], input, partLen);
221 1.1 christos MD5Transform(context->state, context->buffer);
222 1.1 christos
223 1.1 christos for (i = partLen; i + 63 < inputLen; i += 64)
224 1.1 christos MD5Transform(context->state, &input[i]);
225 1.1 christos
226 1.1 christos idx = 0;
227 1.1 christos } else
228 1.1 christos i = 0;
229 1.1 christos
230 1.1 christos /* Buffer remaining input */
231 1.1 christos memcpy(&context->buffer[idx], &input[i], inputLen - i);
232 1.1 christos }
233 1.1 christos
234 1.1 christos /*
235 1.1 christos * MD5 finalization. Ends an MD5 message-digest operation, writing the
236 1.1 christos * message digest and zeroing the context.
237 1.1 christos */
238 1.1 christos void
239 1.4 cegger MD5Final(unsigned char digest[16], /* message digest */
240 1.4 cegger MD5_CTX *context) /* context */
241 1.1 christos {
242 1.1 christos unsigned char bits[8];
243 1.1 christos unsigned int idx, padLen;
244 1.1 christos
245 1.1 christos _DIAGASSERT(digest != 0);
246 1.1 christos _DIAGASSERT(context != 0);
247 1.1 christos
248 1.1 christos /* Save number of bits */
249 1.1 christos Encode(bits, context->count, 8);
250 1.1 christos
251 1.1 christos /* Pad out to 56 mod 64. */
252 1.1 christos idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
253 1.1 christos padLen = (idx < 56) ? (56 - idx) : (120 - idx);
254 1.1 christos MD5Update (context, PADDING, padLen);
255 1.1 christos
256 1.1 christos /* Append length (before padding) */
257 1.1 christos MD5Update(context, bits, 8);
258 1.1 christos
259 1.1 christos /* Store state in digest */
260 1.1 christos Encode(digest, context->state, 16);
261 1.1 christos
262 1.1 christos /* Zeroize sensitive information. */
263 1.1 christos ZEROIZE((POINTER)(void *)context, sizeof(*context));
264 1.1 christos }
265 1.1 christos
266 1.1 christos /*
267 1.1 christos * MD5 basic transformation. Transforms state based on block.
268 1.1 christos */
269 1.1 christos static void
270 1.4 cegger MD5Transform(UINT4 state[4], const unsigned char block[64])
271 1.1 christos {
272 1.1 christos UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
273 1.1 christos
274 1.1 christos Decode(x, block, 64);
275 1.1 christos
276 1.1 christos /* Round 1 */
277 1.1 christos FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
278 1.1 christos FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
279 1.1 christos FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
280 1.1 christos FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
281 1.1 christos FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
282 1.1 christos FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
283 1.1 christos FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
284 1.1 christos FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
285 1.1 christos FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
286 1.1 christos FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
287 1.1 christos FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
288 1.1 christos FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
289 1.1 christos FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
290 1.1 christos FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
291 1.1 christos FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
292 1.1 christos FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
293 1.1 christos
294 1.1 christos /* Round 2 */
295 1.1 christos GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
296 1.1 christos GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
297 1.1 christos GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
298 1.1 christos GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
299 1.1 christos GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
300 1.1 christos GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
301 1.1 christos GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
302 1.1 christos GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
303 1.1 christos GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
304 1.1 christos GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
305 1.1 christos GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
306 1.1 christos GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
307 1.1 christos GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
308 1.1 christos GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
309 1.1 christos GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
310 1.1 christos GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
311 1.1 christos
312 1.1 christos /* Round 3 */
313 1.1 christos HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
314 1.1 christos HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
315 1.1 christos HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
316 1.1 christos HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
317 1.1 christos HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
318 1.1 christos HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
319 1.1 christos HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
320 1.1 christos HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
321 1.1 christos HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
322 1.1 christos HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
323 1.1 christos HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
324 1.1 christos HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
325 1.1 christos HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
326 1.1 christos HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
327 1.1 christos HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
328 1.1 christos HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
329 1.1 christos
330 1.1 christos /* Round 4 */
331 1.1 christos II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
332 1.1 christos II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
333 1.1 christos II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
334 1.1 christos II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
335 1.1 christos II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
336 1.1 christos II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
337 1.1 christos II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
338 1.1 christos II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
339 1.1 christos II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
340 1.1 christos II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
341 1.1 christos II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
342 1.1 christos II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
343 1.1 christos II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
344 1.1 christos II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
345 1.1 christos II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
346 1.1 christos II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
347 1.1 christos
348 1.1 christos state[0] += a;
349 1.1 christos state[1] += b;
350 1.1 christos state[2] += c;
351 1.1 christos state[3] += d;
352 1.1 christos
353 1.1 christos /* Zeroize sensitive information. */
354 1.1 christos ZEROIZE((POINTER)(void *)x, sizeof (x));
355 1.1 christos }
356 1.1 christos
357 1.1 christos #endif /* HAVE_MD5_H */
358