xref: /titanic_53/usr/src/common/crypto/md4/md4.c (revision 5151fb1220e0ceafdc172203863c73da4285c170)
1734b6a94Sdarrenm /*
2*5151fb12Sdarrenm  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
3734b6a94Sdarrenm  * Use is subject to license terms.
4734b6a94Sdarrenm  */
5734b6a94Sdarrenm 
6734b6a94Sdarrenm #pragma ident	"%Z%%M%	%I%	%E% SMI"
7734b6a94Sdarrenm 
8734b6a94Sdarrenm /*
9734b6a94Sdarrenm  * MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm
10734b6a94Sdarrenm  */
11734b6a94Sdarrenm 
12734b6a94Sdarrenm /*
13734b6a94Sdarrenm  * Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
14734b6a94Sdarrenm  *
15734b6a94Sdarrenm  * License to copy and use this software is granted provided that it
16734b6a94Sdarrenm  * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
17734b6a94Sdarrenm  * Algorithm" in all material mentioning or referencing this software
18734b6a94Sdarrenm  * or this function.
19734b6a94Sdarrenm  *
20734b6a94Sdarrenm  * License is also granted to make and use derivative works provided
21734b6a94Sdarrenm  * that such works are identified as "derived from the RSA Data
22734b6a94Sdarrenm  * Security, Inc. MD4 Message-Digest Algorithm" in all material
23734b6a94Sdarrenm  * mentioning or referencing the derived work.
24734b6a94Sdarrenm  *
25734b6a94Sdarrenm  * RSA Data Security, Inc. makes no representations concerning either
26734b6a94Sdarrenm  * the merchantability of this software or the suitability of this
27734b6a94Sdarrenm  * software for any particular purpose. It is provided "as is"
28734b6a94Sdarrenm  * without express or implied warranty of any kind.
29734b6a94Sdarrenm  *
30734b6a94Sdarrenm  * These notices must be retained in any copies of any part of this
31734b6a94Sdarrenm  * documentation and/or software.
32734b6a94Sdarrenm  */
33734b6a94Sdarrenm 
34734b6a94Sdarrenm #include <sys/types.h>
35*5151fb12Sdarrenm #ifdef _KERNEL
36*5151fb12Sdarrenm #include <sys/sunddi.h>
37*5151fb12Sdarrenm #else
38*5151fb12Sdarrenm #include <strings.h>
39*5151fb12Sdarrenm #endif /* _KERNEL */
40734b6a94Sdarrenm 
41*5151fb12Sdarrenm #include <sys/md4.h>
42734b6a94Sdarrenm 
43734b6a94Sdarrenm /*
44734b6a94Sdarrenm  * Constants for MD4Transform routine.
45734b6a94Sdarrenm  */
46734b6a94Sdarrenm #define	S11 3
47734b6a94Sdarrenm #define	S12 7
48734b6a94Sdarrenm #define	S13 11
49734b6a94Sdarrenm #define	S14 19
50734b6a94Sdarrenm #define	S21 3
51734b6a94Sdarrenm #define	S22 5
52734b6a94Sdarrenm #define	S23 9
53734b6a94Sdarrenm #define	S24 13
54734b6a94Sdarrenm #define	S31 3
55734b6a94Sdarrenm #define	S32 9
56734b6a94Sdarrenm #define	S33 11
57734b6a94Sdarrenm #define	S34 15
58734b6a94Sdarrenm 
59*5151fb12Sdarrenm static void MD4Transform(uint32_t [4], unsigned char [64]);
60*5151fb12Sdarrenm static void Encode(unsigned char *, uint32_t *, unsigned int);
61*5151fb12Sdarrenm static void Decode(uint32_t *, unsigned char *, unsigned int);
62734b6a94Sdarrenm 
63734b6a94Sdarrenm static unsigned char PADDING[64] = {
64734b6a94Sdarrenm 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
65734b6a94Sdarrenm 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
66734b6a94Sdarrenm 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
67734b6a94Sdarrenm };
68734b6a94Sdarrenm 
69734b6a94Sdarrenm /*
70734b6a94Sdarrenm  * F, G and H are basic MD4 functions.
71734b6a94Sdarrenm  */
72734b6a94Sdarrenm #define	F(x, y, z) (((x) & (y)) | ((~x) & (z)))
73734b6a94Sdarrenm #define	G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
74734b6a94Sdarrenm #define	H(x, y, z) ((x) ^ (y) ^ (z))
75734b6a94Sdarrenm 
76734b6a94Sdarrenm /*
77734b6a94Sdarrenm  * ROTATE_LEFT rotates x left n bits.
78734b6a94Sdarrenm  */
79734b6a94Sdarrenm #define	ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
80734b6a94Sdarrenm 
81734b6a94Sdarrenm /* FF, GG and HH are transformations for rounds 1, 2 and 3 */
82734b6a94Sdarrenm /* Rotation is separate from addition to prevent recomputation */
83734b6a94Sdarrenm 
84734b6a94Sdarrenm #define	FF(a, b, c, d, x, s) { \
85734b6a94Sdarrenm 		(a) += F((b), (c), (d)) + (x); \
86734b6a94Sdarrenm 		(a) = ROTATE_LEFT((a), (s)); \
87734b6a94Sdarrenm 	}
88734b6a94Sdarrenm #define	GG(a, b, c, d, x, s) { \
89*5151fb12Sdarrenm 		(a) += G((b), (c), (d)) + (x) + (uint32_t)0x5a827999; \
90734b6a94Sdarrenm 		(a) = ROTATE_LEFT((a), (s)); \
91734b6a94Sdarrenm 	}
92734b6a94Sdarrenm #define	HH(a, b, c, d, x, s) { \
93*5151fb12Sdarrenm 		(a) += H((b), (c), (d)) + (x) + (uint32_t)0x6ed9eba1; \
94734b6a94Sdarrenm 		(a) = ROTATE_LEFT((a), (s)); \
95734b6a94Sdarrenm 	}
96734b6a94Sdarrenm 
97734b6a94Sdarrenm /*
98734b6a94Sdarrenm  * MD4 initialization. Begins an MD4 operation, writing a new context.
99734b6a94Sdarrenm  */
100734b6a94Sdarrenm void
101*5151fb12Sdarrenm MD4Init(MD4_CTX *context)
102734b6a94Sdarrenm {
103734b6a94Sdarrenm 	context->count[0] = context->count[1] = 0;
104734b6a94Sdarrenm 
105734b6a94Sdarrenm 	/*
106734b6a94Sdarrenm 	 * Load magic initialization constants.
107734b6a94Sdarrenm 	 */
108734b6a94Sdarrenm 	context->state[0] = 0x67452301UL;
109734b6a94Sdarrenm 	context->state[1] = 0xefcdab89UL;
110734b6a94Sdarrenm 	context->state[2] = 0x98badcfeUL;
111734b6a94Sdarrenm 	context->state[3] = 0x10325476UL;
112734b6a94Sdarrenm }
113734b6a94Sdarrenm 
114734b6a94Sdarrenm 
115734b6a94Sdarrenm /*
116734b6a94Sdarrenm  * MD4 block update operation. Continues an MD4 message-digest
117734b6a94Sdarrenm  * operation, processing another message block, and updating the
118734b6a94Sdarrenm  * context.
119734b6a94Sdarrenm  */
120734b6a94Sdarrenm void
121734b6a94Sdarrenm MD4Update(MD4_CTX *context, const void *_RESTRICT_KYWD inptr, size_t inputLen)
122734b6a94Sdarrenm {
123734b6a94Sdarrenm 	unsigned int i, index, partLen;
124734b6a94Sdarrenm 	uchar_t *input = (uchar_t *)inptr;
125734b6a94Sdarrenm 
126734b6a94Sdarrenm 	/* Compute number of bytes mod 64 */
127734b6a94Sdarrenm 	index = (unsigned int)((context->count[0] >> 3) & 0x3F);
128734b6a94Sdarrenm 	/* Update number of bits */
129*5151fb12Sdarrenm 	if ((context->count[0] += ((uint32_t)inputLen << 3))
130*5151fb12Sdarrenm 	    < ((uint32_t)inputLen << 3))
131734b6a94Sdarrenm 		context->count[1]++;
132*5151fb12Sdarrenm 	context->count[1] += ((uint32_t)inputLen >> 29);
133734b6a94Sdarrenm 
134734b6a94Sdarrenm 	partLen = 64 - index;
135734b6a94Sdarrenm 
136734b6a94Sdarrenm 	/*
137734b6a94Sdarrenm 	 * Transform as many times as possible.
138734b6a94Sdarrenm 	 */
139734b6a94Sdarrenm 	if (inputLen >= partLen) {
140734b6a94Sdarrenm 		bcopy(input, &context->buffer[index], partLen);
141734b6a94Sdarrenm 		MD4Transform(context->state, (uchar_t *)context->buffer);
142734b6a94Sdarrenm 
143734b6a94Sdarrenm 		for (i = partLen; i + 63 < inputLen; i += 64) {
144734b6a94Sdarrenm 			MD4Transform(context->state, (uchar_t *)&input[i]);
145734b6a94Sdarrenm 		}
146734b6a94Sdarrenm 
147734b6a94Sdarrenm 		index = 0;
148734b6a94Sdarrenm 	} else {
149734b6a94Sdarrenm 		i = 0;
150734b6a94Sdarrenm 	}
151734b6a94Sdarrenm 
152734b6a94Sdarrenm 	/* Buffer remaining input */
153734b6a94Sdarrenm 	bcopy(&input[i], &context->buffer[index], inputLen - i);
154734b6a94Sdarrenm }
155734b6a94Sdarrenm 
156734b6a94Sdarrenm /*
157734b6a94Sdarrenm  * MD4 finalization. Ends an MD4 message-digest operation, writing the
158734b6a94Sdarrenm  *	the message digest and zeroizing the context.
159734b6a94Sdarrenm  */
160734b6a94Sdarrenm void
161734b6a94Sdarrenm MD4Final(void *digest, MD4_CTX *context)
162734b6a94Sdarrenm {
163734b6a94Sdarrenm 	unsigned char bits[8];
164734b6a94Sdarrenm 	unsigned int index, padLen;
165734b6a94Sdarrenm 
166734b6a94Sdarrenm 	/* Save number of bits */
167734b6a94Sdarrenm 	Encode(bits, context->count, 8);
168734b6a94Sdarrenm 
169734b6a94Sdarrenm 	/*
170734b6a94Sdarrenm 	 * Pad out to 56 mod 64.
171734b6a94Sdarrenm 	 */
172734b6a94Sdarrenm 	index = (unsigned int)((context->count[0] >> 3) & 0x3f);
173734b6a94Sdarrenm 	padLen = (index < 56) ? (56 - index) : (120 - index);
174734b6a94Sdarrenm 	MD4Update(context, PADDING, padLen);
175734b6a94Sdarrenm 
176734b6a94Sdarrenm 	/* Append length (before padding) */
177734b6a94Sdarrenm 	MD4Update(context, bits, 8);
178734b6a94Sdarrenm 	/* Store state in digest */
179734b6a94Sdarrenm 	Encode(digest, context->state, 16);
180734b6a94Sdarrenm 
181734b6a94Sdarrenm 	/* zeroize sensitive information */
182734b6a94Sdarrenm 	bzero(context, sizeof (*context));
183734b6a94Sdarrenm }
184734b6a94Sdarrenm 
185734b6a94Sdarrenm /*
186734b6a94Sdarrenm  * MD4 basic transformation. Transforms state based on block.
187734b6a94Sdarrenm  */
188734b6a94Sdarrenm static void
189*5151fb12Sdarrenm MD4Transform(uint32_t state[4], unsigned char block[64])
190734b6a94Sdarrenm {
191*5151fb12Sdarrenm 	uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
192734b6a94Sdarrenm 
193734b6a94Sdarrenm 
194734b6a94Sdarrenm 	Decode(x, block, 64);
195734b6a94Sdarrenm 
196734b6a94Sdarrenm 	/* Round 1 */
197734b6a94Sdarrenm 	FF(a, b, c, d, x[ 0], S11); /* 1 */
198734b6a94Sdarrenm 	FF(d, a, b, c, x[ 1], S12); /* 2 */
199734b6a94Sdarrenm 	FF(c, d, a, b, x[ 2], S13); /* 3 */
200734b6a94Sdarrenm 	FF(b, c, d, a, x[ 3], S14); /* 4 */
201734b6a94Sdarrenm 	FF(a, b, c, d, x[ 4], S11); /* 5 */
202734b6a94Sdarrenm 	FF(d, a, b, c, x[ 5], S12); /* 6 */
203734b6a94Sdarrenm 	FF(c, d, a, b, x[ 6], S13); /* 7 */
204734b6a94Sdarrenm 	FF(b, c, d, a, x[ 7], S14); /* 8 */
205734b6a94Sdarrenm 	FF(a, b, c, d, x[ 8], S11); /* 9 */
206734b6a94Sdarrenm 	FF(d, a, b, c, x[ 9], S12); /* 10 */
207734b6a94Sdarrenm 	FF(c, d, a, b, x[10], S13); /* 11 */
208734b6a94Sdarrenm 	FF(b, c, d, a, x[11], S14); /* 12 */
209734b6a94Sdarrenm 	FF(a, b, c, d, x[12], S11); /* 13 */
210734b6a94Sdarrenm 	FF(d, a, b, c, x[13], S12); /* 14 */
211734b6a94Sdarrenm 	FF(c, d, a, b, x[14], S13); /* 15 */
212734b6a94Sdarrenm 	FF(b, c, d, a, x[15], S14); /* 16 */
213734b6a94Sdarrenm 
214734b6a94Sdarrenm 	/* Round 2 */
215734b6a94Sdarrenm 	GG(a, b, c, d, x[ 0], S21); /* 17 */
216734b6a94Sdarrenm 	GG(d, a, b, c, x[ 4], S22); /* 18 */
217734b6a94Sdarrenm 	GG(c, d, a, b, x[ 8], S23); /* 19 */
218734b6a94Sdarrenm 	GG(b, c, d, a, x[12], S24); /* 20 */
219734b6a94Sdarrenm 	GG(a, b, c, d, x[ 1], S21); /* 21 */
220734b6a94Sdarrenm 	GG(d, a, b, c, x[ 5], S22); /* 22 */
221734b6a94Sdarrenm 	GG(c, d, a, b, x[ 9], S23); /* 23 */
222734b6a94Sdarrenm 	GG(b, c, d, a, x[13], S24); /* 24 */
223734b6a94Sdarrenm 	GG(a, b, c, d, x[ 2], S21); /* 25 */
224734b6a94Sdarrenm 	GG(d, a, b, c, x[ 6], S22); /* 26 */
225734b6a94Sdarrenm 	GG(c, d, a, b, x[10], S23); /* 27 */
226734b6a94Sdarrenm 	GG(b, c, d, a, x[14], S24); /* 28 */
227734b6a94Sdarrenm 	GG(a, b, c, d, x[ 3], S21); /* 29 */
228734b6a94Sdarrenm 	GG(d, a, b, c, x[ 7], S22); /* 30 */
229734b6a94Sdarrenm 	GG(c, d, a, b, x[11], S23); /* 31 */
230734b6a94Sdarrenm 	GG(b, c, d, a, x[15], S24); /* 32 */
231734b6a94Sdarrenm 
232734b6a94Sdarrenm 
233734b6a94Sdarrenm 	/* Round 3 */
234734b6a94Sdarrenm 	HH(a, b, c, d, x[ 0], S31); /* 33 */
235734b6a94Sdarrenm 	HH(d, a, b, c, x[ 8], S32); /* 34 */
236734b6a94Sdarrenm 	HH(c, d, a, b, x[ 4], S33); /* 35 */
237734b6a94Sdarrenm 	HH(b, c, d, a, x[12], S34); /* 36 */
238734b6a94Sdarrenm 	HH(a, b, c, d, x[ 2], S31); /* 37 */
239734b6a94Sdarrenm 	HH(d, a, b, c, x[10], S32); /* 38 */
240734b6a94Sdarrenm 	HH(c, d, a, b, x[ 6], S33); /* 39 */
241734b6a94Sdarrenm 	HH(b, c, d, a, x[14], S34); /* 40 */
242734b6a94Sdarrenm 	HH(a, b, c, d, x[ 1], S31); /* 41 */
243734b6a94Sdarrenm 	HH(d, a, b, c, x[ 9], S32); /* 42 */
244734b6a94Sdarrenm 	HH(c, d, a, b, x[ 5], S33); /* 43 */
245734b6a94Sdarrenm 	HH(b, c, d, a, x[13], S34); /* 44 */
246734b6a94Sdarrenm 	HH(a, b, c, d, x[ 3], S31); /* 45 */
247734b6a94Sdarrenm 	HH(d, a, b, c, x[11], S32); /* 46 */
248734b6a94Sdarrenm 	HH(c, d, a, b, x[ 7], S33); /* 47 */
249734b6a94Sdarrenm 	HH(b, c, d, a, x[15], S34); /* 48 */
250734b6a94Sdarrenm 
251734b6a94Sdarrenm 	state[0] += a;
252734b6a94Sdarrenm 	state[1] += b;
253734b6a94Sdarrenm 	state[2] += c;
254734b6a94Sdarrenm 	state[3] += d;
255734b6a94Sdarrenm 
256734b6a94Sdarrenm 	/* zeroize sensitive information */
257734b6a94Sdarrenm 	bzero(x, sizeof (*x));
258734b6a94Sdarrenm }
259734b6a94Sdarrenm 
260734b6a94Sdarrenm /*
261*5151fb12Sdarrenm  * Encodes input (uint32_t) into output (unsigned char). Assumes len is
262734b6a94Sdarrenm  * a multiple of 4.
263734b6a94Sdarrenm  */
264734b6a94Sdarrenm static void
265734b6a94Sdarrenm Encode(output, input, len)
266734b6a94Sdarrenm 	unsigned char *output;
267*5151fb12Sdarrenm 	uint32_t *input;
268734b6a94Sdarrenm 	unsigned int len;
269734b6a94Sdarrenm {
270734b6a94Sdarrenm 	unsigned int i, j;
271734b6a94Sdarrenm 
272734b6a94Sdarrenm 	for (i = 0, j = 0; j < len; i++, j += 4) {
273734b6a94Sdarrenm 		output[j] = (unsigned char)(input[i] & 0xff);
274734b6a94Sdarrenm 		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
275734b6a94Sdarrenm 		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
276734b6a94Sdarrenm 		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
277734b6a94Sdarrenm 	}
278734b6a94Sdarrenm }
279734b6a94Sdarrenm 
280734b6a94Sdarrenm /*
281*5151fb12Sdarrenm  * Decodes input (unsigned char) into output (uint32_t). Assumes len is
282734b6a94Sdarrenm  * a multiple of 4.
283734b6a94Sdarrenm  */
284734b6a94Sdarrenm static void
285734b6a94Sdarrenm Decode(output, input, len)
286*5151fb12Sdarrenm 	uint32_t *output;
287734b6a94Sdarrenm 	unsigned char *input;
288734b6a94Sdarrenm 	unsigned int len;
289734b6a94Sdarrenm {
290734b6a94Sdarrenm 	unsigned int i, j;
291734b6a94Sdarrenm 
292734b6a94Sdarrenm 	for (i = 0, j = 0; j < len; i++, j += 4)
293*5151fb12Sdarrenm 		output[i] = ((uint32_t)input[j]) |
294*5151fb12Sdarrenm 			(((uint32_t)input[j+1]) << 8) |
295*5151fb12Sdarrenm 			(((uint32_t)input[j+2]) << 16) |
296*5151fb12Sdarrenm 			(((uint32_t)input[j+3]) << 24);
297734b6a94Sdarrenm }
298