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