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