md4c.c revision 1.5 1 1.5 matt /* $NetBSD: md4c.c,v 1.5 2012/03/20 16:21:41 matt Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * This file is derived from the RSA Data Security, Inc. MD4 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) 1990-2, RSA Data Security, Inc. All rights reserved.
11 1.1 christos *
12 1.1 christos * License to copy and use this software is granted provided that it
13 1.1 christos * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
14 1.1 christos * Algorithm" in all material mentioning or referencing this software
15 1.1 christos * or this function.
16 1.1 christos *
17 1.1 christos * License is also granted to make and use derivative works provided
18 1.1 christos * that such works are identified as "derived from the RSA Data
19 1.1 christos * Security, Inc. MD4 Message-Digest Algorithm" in all material
20 1.1 christos * mentioning or referencing the derived work.
21 1.1 christos *
22 1.1 christos * RSA Data Security, Inc. makes no representations concerning either
23 1.1 christos * the merchantability of this software or the suitability of this
24 1.1 christos * software for any particular purpose. It is provided "as is"
25 1.1 christos * without express or implied warranty of any kind.
26 1.1 christos *
27 1.1 christos * These notices must be retained in any copies of any part of this
28 1.1 christos * documentation and/or software.
29 1.1 christos */
30 1.1 christos
31 1.1 christos #if !defined(_KERNEL) && !defined(_STANDALONE)
32 1.1 christos #include <sys/cdefs.h>
33 1.1 christos #if defined(LIBC_SCCS) && !defined(lint)
34 1.5 matt __RCSID("$NetBSD: md4c.c,v 1.5 2012/03/20 16:21:41 matt Exp $");
35 1.1 christos #endif /* LIBC_SCCS and not lint */
36 1.1 christos
37 1.1 christos #include "namespace.h"
38 1.1 christos
39 1.1 christos #include <sys/types.h>
40 1.1 christos
41 1.1 christos #include <assert.h>
42 1.1 christos #include <md4.h>
43 1.1 christos #include <string.h>
44 1.1 christos
45 1.1 christos #if HAVE_NBTOOL_CONFIG_H
46 1.1 christos #include "nbtool_config.h"
47 1.1 christos #endif
48 1.1 christos
49 1.1 christos #else
50 1.1 christos
51 1.2 matt #include <sys/param.h>
52 1.1 christos #include <sys/md4.h>
53 1.1 christos #include <lib/libkern/libkern.h>
54 1.1 christos
55 1.1 christos #endif /* !_KERNEL && !_STANDALONE */
56 1.1 christos
57 1.1 christos #if !HAVE_MD4_H
58 1.1 christos
59 1.1 christos typedef unsigned char *POINTER;
60 1.3 apb typedef uint16_t UINT2;
61 1.3 apb typedef uint32_t UINT4;
62 1.1 christos
63 1.1 christos /*
64 1.1 christos * Constants for MD4Transform routine.
65 1.1 christos */
66 1.1 christos #define S11 3
67 1.1 christos #define S12 7
68 1.1 christos #define S13 11
69 1.1 christos #define S14 19
70 1.1 christos #define S21 3
71 1.1 christos #define S22 5
72 1.1 christos #define S23 9
73 1.1 christos #define S24 13
74 1.1 christos #define S31 3
75 1.1 christos #define S32 9
76 1.1 christos #define S33 11
77 1.1 christos #define S34 15
78 1.1 christos
79 1.5 matt static void MD4Transform(UINT4 [4], const unsigned char [64]);
80 1.1 christos
81 1.5 matt static void Encode(unsigned char *, UINT4 *, unsigned int);
82 1.5 matt static void Decode(UINT4 *, const unsigned char *, unsigned int);
83 1.1 christos
84 1.1 christos static const unsigned char PADDING[64] = {
85 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,
86 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,
87 1.1 christos 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
88 1.1 christos };
89 1.1 christos
90 1.1 christos /*
91 1.1 christos * F, G and H are basic MD4 functions.
92 1.1 christos */
93 1.1 christos #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
94 1.1 christos #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
95 1.1 christos #define H(x, y, z) ((x) ^ (y) ^ (z))
96 1.1 christos
97 1.1 christos /*
98 1.1 christos * ROTATE_LEFT rotates x left n bits.
99 1.1 christos */
100 1.1 christos #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
101 1.1 christos
102 1.1 christos /*
103 1.1 christos * FF, GG and HH are transformations for rounds 1, 2 and 3.
104 1.1 christos * Rotation is separate from addition to prevent recomputation.
105 1.1 christos */
106 1.1 christos #define FF(a, b, c, d, x, s) { \
107 1.1 christos (a) += F ((b), (c), (d)) + (x); \
108 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \
109 1.1 christos }
110 1.1 christos
111 1.1 christos #define GG(a, b, c, d, x, s) { \
112 1.1 christos (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
113 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \
114 1.1 christos }
115 1.1 christos
116 1.1 christos #define HH(a, b, c, d, x, s) { \
117 1.1 christos (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
118 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \
119 1.1 christos }
120 1.1 christos
121 1.1 christos #if !defined(_KERNEL) && !defined(_STANDALONE) && defined(__weak_alias)
122 1.1 christos __weak_alias(MD4Init,_MD4Init)
123 1.1 christos __weak_alias(MD4Update,_MD4Update)
124 1.1 christos __weak_alias(MD4Final,_MD4Final)
125 1.1 christos __weak_alias(MD4Transform,_MD4Transform)
126 1.1 christos #endif
127 1.1 christos
128 1.1 christos /*
129 1.1 christos * MD4 initialization. Begins an MD4 operation, writing a new context.
130 1.1 christos */
131 1.1 christos void
132 1.4 cegger MD4Init(MD4_CTX *context) /* context */
133 1.1 christos {
134 1.1 christos
135 1.1 christos _DIAGASSERT(context != 0);
136 1.1 christos
137 1.1 christos context->count[0] = context->count[1] = 0;
138 1.1 christos
139 1.1 christos /* Load magic initialization constants. */
140 1.1 christos context->state[0] = 0x67452301;
141 1.1 christos context->state[1] = 0xefcdab89;
142 1.1 christos context->state[2] = 0x98badcfe;
143 1.1 christos context->state[3] = 0x10325476;
144 1.1 christos }
145 1.1 christos
146 1.1 christos /*
147 1.1 christos * MD4 block update operation. Continues an MD4 message-digest
148 1.1 christos * operation, processing another message block, and updating the
149 1.1 christos * context.
150 1.1 christos */
151 1.1 christos void
152 1.4 cegger MD4Update (MD4_CTX *context, /* context */
153 1.4 cegger const unsigned char *input, /* input block */
154 1.4 cegger unsigned int inputLen) /* length of input block */
155 1.1 christos {
156 1.1 christos unsigned int i, idx, partLen;
157 1.1 christos
158 1.1 christos _DIAGASSERT(context != 0);
159 1.1 christos _DIAGASSERT(input != 0);
160 1.1 christos
161 1.1 christos /* Compute number of bytes mod 64 */
162 1.1 christos idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
163 1.1 christos
164 1.1 christos /* Update number of bits */
165 1.1 christos if ((context->count[0] += ((UINT4)inputLen << 3))
166 1.1 christos < ((UINT4)inputLen << 3))
167 1.1 christos context->count[1]++;
168 1.1 christos context->count[1] += ((UINT4)inputLen >> 29);
169 1.1 christos
170 1.1 christos partLen = 64 - idx;
171 1.1 christos
172 1.1 christos /* Transform as many times as possible. */
173 1.1 christos if (inputLen >= partLen) {
174 1.1 christos memcpy(&context->buffer[idx], input, partLen);
175 1.1 christos MD4Transform(context->state, context->buffer);
176 1.1 christos
177 1.1 christos for (i = partLen; i + 63 < inputLen; i += 64)
178 1.1 christos MD4Transform(context->state, &input[i]);
179 1.1 christos
180 1.1 christos idx = 0;
181 1.1 christos } else
182 1.1 christos i = 0;
183 1.1 christos
184 1.1 christos /* Buffer remaining input */
185 1.1 christos memcpy(&context->buffer[idx], &input[i], inputLen - i);
186 1.1 christos }
187 1.1 christos
188 1.1 christos /*
189 1.1 christos * MD4 finalization. Ends an MD4 message-digest operation, writing the
190 1.1 christos * message digest and zeroing the context.
191 1.1 christos */
192 1.1 christos void
193 1.4 cegger MD4Final (unsigned char digest[16], /* message digest */
194 1.4 cegger MD4_CTX *context) /* context */
195 1.1 christos {
196 1.1 christos unsigned char bits[8];
197 1.1 christos unsigned int idx, padLen;
198 1.1 christos
199 1.1 christos _DIAGASSERT(digest != 0);
200 1.1 christos _DIAGASSERT(context != 0);
201 1.1 christos
202 1.1 christos /* Save number of bits */
203 1.1 christos Encode(bits, context->count, 8);
204 1.1 christos
205 1.1 christos /* Pad out to 56 mod 64. */
206 1.1 christos idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
207 1.1 christos padLen = (idx < 56) ? (56 - idx) : (120 - idx);
208 1.1 christos MD4Update(context, PADDING, padLen);
209 1.1 christos
210 1.1 christos /* Append length (before padding) */
211 1.1 christos MD4Update(context, bits, 8);
212 1.1 christos
213 1.1 christos /* Store state in digest */
214 1.1 christos Encode(digest, context->state, 16);
215 1.1 christos
216 1.1 christos /* Zeroize sensitive information. */
217 1.1 christos memset(context, 0, sizeof(*context));
218 1.1 christos }
219 1.1 christos
220 1.1 christos /*
221 1.1 christos * MD4 basic transformation. Transforms state based on block.
222 1.1 christos */
223 1.1 christos static void
224 1.4 cegger MD4Transform (UINT4 state[4], const unsigned char block[64])
225 1.1 christos {
226 1.1 christos UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
227 1.1 christos
228 1.1 christos Decode(x, block, 64);
229 1.1 christos
230 1.1 christos /* Round 1 */
231 1.1 christos FF (a, b, c, d, x[ 0], S11); /* 1 */
232 1.1 christos FF (d, a, b, c, x[ 1], S12); /* 2 */
233 1.1 christos FF (c, d, a, b, x[ 2], S13); /* 3 */
234 1.1 christos FF (b, c, d, a, x[ 3], S14); /* 4 */
235 1.1 christos FF (a, b, c, d, x[ 4], S11); /* 5 */
236 1.1 christos FF (d, a, b, c, x[ 5], S12); /* 6 */
237 1.1 christos FF (c, d, a, b, x[ 6], S13); /* 7 */
238 1.1 christos FF (b, c, d, a, x[ 7], S14); /* 8 */
239 1.1 christos FF (a, b, c, d, x[ 8], S11); /* 9 */
240 1.1 christos FF (d, a, b, c, x[ 9], S12); /* 10 */
241 1.1 christos FF (c, d, a, b, x[10], S13); /* 11 */
242 1.1 christos FF (b, c, d, a, x[11], S14); /* 12 */
243 1.1 christos FF (a, b, c, d, x[12], S11); /* 13 */
244 1.1 christos FF (d, a, b, c, x[13], S12); /* 14 */
245 1.1 christos FF (c, d, a, b, x[14], S13); /* 15 */
246 1.1 christos FF (b, c, d, a, x[15], S14); /* 16 */
247 1.1 christos
248 1.1 christos /* Round 2 */
249 1.1 christos GG (a, b, c, d, x[ 0], S21); /* 17 */
250 1.1 christos GG (d, a, b, c, x[ 4], S22); /* 18 */
251 1.1 christos GG (c, d, a, b, x[ 8], S23); /* 19 */
252 1.1 christos GG (b, c, d, a, x[12], S24); /* 20 */
253 1.1 christos GG (a, b, c, d, x[ 1], S21); /* 21 */
254 1.1 christos GG (d, a, b, c, x[ 5], S22); /* 22 */
255 1.1 christos GG (c, d, a, b, x[ 9], S23); /* 23 */
256 1.1 christos GG (b, c, d, a, x[13], S24); /* 24 */
257 1.1 christos GG (a, b, c, d, x[ 2], S21); /* 25 */
258 1.1 christos GG (d, a, b, c, x[ 6], S22); /* 26 */
259 1.1 christos GG (c, d, a, b, x[10], S23); /* 27 */
260 1.1 christos GG (b, c, d, a, x[14], S24); /* 28 */
261 1.1 christos GG (a, b, c, d, x[ 3], S21); /* 29 */
262 1.1 christos GG (d, a, b, c, x[ 7], S22); /* 30 */
263 1.1 christos GG (c, d, a, b, x[11], S23); /* 31 */
264 1.1 christos GG (b, c, d, a, x[15], S24); /* 32 */
265 1.1 christos
266 1.1 christos /* Round 3 */
267 1.1 christos HH (a, b, c, d, x[ 0], S31); /* 33 */
268 1.1 christos HH (d, a, b, c, x[ 8], S32); /* 34 */
269 1.1 christos HH (c, d, a, b, x[ 4], S33); /* 35 */
270 1.1 christos HH (b, c, d, a, x[12], S34); /* 36 */
271 1.1 christos HH (a, b, c, d, x[ 2], S31); /* 37 */
272 1.1 christos HH (d, a, b, c, x[10], S32); /* 38 */
273 1.1 christos HH (c, d, a, b, x[ 6], S33); /* 39 */
274 1.1 christos HH (b, c, d, a, x[14], S34); /* 40 */
275 1.1 christos HH (a, b, c, d, x[ 1], S31); /* 41 */
276 1.1 christos HH (d, a, b, c, x[ 9], S32); /* 42 */
277 1.1 christos HH (c, d, a, b, x[ 5], S33); /* 43 */
278 1.1 christos HH (b, c, d, a, x[13], S34); /* 44 */
279 1.1 christos HH (a, b, c, d, x[ 3], S31); /* 45 */
280 1.1 christos HH (d, a, b, c, x[11], S32); /* 46 */
281 1.1 christos HH (c, d, a, b, x[ 7], S33); /* 47 */
282 1.1 christos HH (b, c, d, a, x[15], S34); /* 48 */
283 1.1 christos
284 1.1 christos state[0] += a;
285 1.1 christos state[1] += b;
286 1.1 christos state[2] += c;
287 1.1 christos state[3] += d;
288 1.1 christos
289 1.1 christos /* Zeroize sensitive information. */
290 1.1 christos memset(x, 0, sizeof (x));
291 1.1 christos }
292 1.1 christos
293 1.1 christos /*
294 1.1 christos * Encodes input (UINT4) into output (unsigned char). Assumes len is
295 1.1 christos * a multiple of 4.
296 1.1 christos */
297 1.1 christos static void
298 1.4 cegger Encode(unsigned char *output, UINT4 *input, unsigned int len)
299 1.1 christos {
300 1.1 christos unsigned int i, j;
301 1.1 christos
302 1.1 christos for (i = 0, j = 0; j < len; i++, j += 4) {
303 1.1 christos output[j] = (unsigned char)(input[i] & 0xff);
304 1.1 christos output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
305 1.1 christos output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
306 1.1 christos output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
307 1.1 christos }
308 1.1 christos }
309 1.1 christos
310 1.1 christos /*
311 1.1 christos * Decodes input (unsigned char) into output (UINT4). Assumes len is
312 1.1 christos * a multiple of 4.
313 1.1 christos */
314 1.1 christos static void
315 1.4 cegger Decode(UINT4 *output, const unsigned char *input, unsigned int len)
316 1.1 christos {
317 1.1 christos unsigned int i, j;
318 1.1 christos
319 1.1 christos for (i = 0, j = 0; j < len; i++, j += 4)
320 1.1 christos output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
321 1.1 christos (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
322 1.1 christos }
323 1.1 christos
324 1.1 christos #endif /* HAVE_MD4_H */
325