1734b6a94Sdarrenm /*
24b56a003SDaniel 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
394b56a003SDaniel Anderson #if defined(__i386) || defined(__amd64)
404b56a003SDaniel Anderson #define UNALIGNED_POINTERS_PERMITTED
414b56a003SDaniel Anderson #endif
424b56a003SDaniel 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
MD4Init(MD4_CTX * context)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
MD4Update(MD4_CTX * context,const void * _RESTRICT_KYWD inptr,size_t inputLen)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
MD4Final(void * digest,MD4_CTX * context)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
MD4Transform(uint32_t state[4],unsigned char block[64])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
Encode(unsigned char * output,uint32_t * input,unsigned int len)2674b56a003SDaniel 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) {
2724b56a003SDaniel Anderson #if defined(_LITTLE_ENDIAN) && defined(UNALIGNED_POINTERS_PERMITTED)
273*25cc6a40SDaniel Anderson *(uint32_t *)(void *)&output[j] = input[i];
2744b56a003SDaniel Anderson #else
2754b56a003SDaniel 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);
2804b56a003SDaniel 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
Decode(uint32_t * output,unsigned char * input,unsigned int len)2894b56a003SDaniel Anderson Decode(uint32_t *output, unsigned char *input, unsigned int len)
290734b6a94Sdarrenm {
291734b6a94Sdarrenm unsigned int i, j;
292734b6a94Sdarrenm
2934b56a003SDaniel Anderson for (i = 0, j = 0; j < len; i++, j += 4) {
2944b56a003SDaniel Anderson #if defined(_LITTLE_ENDIAN) && defined(UNALIGNED_POINTERS_PERMITTED)
295*25cc6a40SDaniel Anderson output[i] = *(uint32_t *)(void *)&input[j];
2964b56a003SDaniel Anderson #else
2974b56a003SDaniel 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);
3024b56a003SDaniel Anderson #endif /* _LITTLE_ENDIAN && UNALIGNED_POINTERS_PERMITTED */
3034b56a003SDaniel Anderson }
3044b56a003SDaniel Anderson
305734b6a94Sdarrenm }
306