xref: /freebsd/sys/kern/md4c.c (revision 80dc9f8888ca78eb0d9efb1eeebab40f109873e2)
1681a5bbeSBoris Popov /* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm
2681a5bbeSBoris Popov  */
3681a5bbeSBoris Popov 
49454b2d8SWarner Losh /*-
59454b2d8SWarner Losh    Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
6681a5bbeSBoris Popov 
7681a5bbeSBoris Popov    License to copy and use this software is granted provided that it
8681a5bbeSBoris Popov    is identified as the "RSA Data Security, Inc. MD4 Message-Digest
9681a5bbeSBoris Popov    Algorithm" in all material mentioning or referencing this software
10681a5bbeSBoris Popov    or this function.
11681a5bbeSBoris Popov 
12681a5bbeSBoris Popov    License is also granted to make and use derivative works provided
13681a5bbeSBoris Popov    that such works are identified as "derived from the RSA Data
14681a5bbeSBoris Popov    Security, Inc. MD4 Message-Digest Algorithm" in all material
15681a5bbeSBoris Popov    mentioning or referencing the derived work.
16681a5bbeSBoris Popov 
17681a5bbeSBoris Popov    RSA Data Security, Inc. makes no representations concerning either
18681a5bbeSBoris Popov    the merchantability of this software or the suitability of this
19681a5bbeSBoris Popov    software for any particular purpose. It is provided "as is"
20681a5bbeSBoris Popov    without express or implied warranty of any kind.
21681a5bbeSBoris Popov 
22681a5bbeSBoris Popov    These notices must be retained in any copies of any part of this
23681a5bbeSBoris Popov    documentation and/or software.
24681a5bbeSBoris Popov  */
25681a5bbeSBoris Popov 
26677b542eSDavid E. O'Brien #include <sys/cdefs.h>
27677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
28677b542eSDavid E. O'Brien 
29681a5bbeSBoris Popov #include <sys/param.h>
30681a5bbeSBoris Popov #include <sys/systm.h>
31681a5bbeSBoris Popov #include <sys/md4.h>
32681a5bbeSBoris Popov 
33681a5bbeSBoris Popov typedef unsigned char *POINTER;
34681a5bbeSBoris Popov typedef u_int16_t UINT2;
35681a5bbeSBoris Popov typedef u_int32_t UINT4;
36681a5bbeSBoris Popov 
37681a5bbeSBoris Popov #define PROTO_LIST(list) list
38681a5bbeSBoris Popov 
39681a5bbeSBoris Popov /* Constants for MD4Transform routine.
40681a5bbeSBoris Popov  */
41681a5bbeSBoris Popov #define S11 3
42681a5bbeSBoris Popov #define S12 7
43681a5bbeSBoris Popov #define S13 11
44681a5bbeSBoris Popov #define S14 19
45681a5bbeSBoris Popov #define S21 3
46681a5bbeSBoris Popov #define S22 5
47681a5bbeSBoris Popov #define S23 9
48681a5bbeSBoris Popov #define S24 13
49681a5bbeSBoris Popov #define S31 3
50681a5bbeSBoris Popov #define S32 9
51681a5bbeSBoris Popov #define S33 11
52681a5bbeSBoris Popov #define S34 15
53681a5bbeSBoris Popov 
54681a5bbeSBoris Popov static void MD4Transform PROTO_LIST ((UINT4 [4], const unsigned char [64]));
55681a5bbeSBoris Popov static void Encode PROTO_LIST
56681a5bbeSBoris Popov   ((unsigned char *, UINT4 *, unsigned int));
57681a5bbeSBoris Popov static void Decode PROTO_LIST
58681a5bbeSBoris Popov   ((UINT4 *, const unsigned char *, unsigned int));
59681a5bbeSBoris Popov 
60681a5bbeSBoris Popov static unsigned char PADDING[64] = {
61681a5bbeSBoris Popov   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62681a5bbeSBoris Popov   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63681a5bbeSBoris Popov   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
64681a5bbeSBoris Popov };
65681a5bbeSBoris Popov 
66681a5bbeSBoris Popov /* F, G and H are basic MD4 functions.
67681a5bbeSBoris Popov  */
68681a5bbeSBoris Popov #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
69681a5bbeSBoris Popov #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
70681a5bbeSBoris Popov #define H(x, y, z) ((x) ^ (y) ^ (z))
71681a5bbeSBoris Popov 
72681a5bbeSBoris Popov /* ROTATE_LEFT rotates x left n bits.
73681a5bbeSBoris Popov  */
74681a5bbeSBoris Popov #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
75681a5bbeSBoris Popov 
76681a5bbeSBoris Popov /* FF, GG and HH are transformations for rounds 1, 2 and 3 */
77681a5bbeSBoris Popov /* Rotation is separate from addition to prevent recomputation */
78681a5bbeSBoris Popov #define FF(a, b, c, d, x, s) { \
79681a5bbeSBoris Popov     (a) += F ((b), (c), (d)) + (x); \
80681a5bbeSBoris Popov     (a) = ROTATE_LEFT ((a), (s)); \
81681a5bbeSBoris Popov   }
82681a5bbeSBoris Popov #define GG(a, b, c, d, x, s) { \
83681a5bbeSBoris Popov     (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
84681a5bbeSBoris Popov     (a) = ROTATE_LEFT ((a), (s)); \
85681a5bbeSBoris Popov   }
86681a5bbeSBoris Popov #define HH(a, b, c, d, x, s) { \
87681a5bbeSBoris Popov     (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
88681a5bbeSBoris Popov     (a) = ROTATE_LEFT ((a), (s)); \
89681a5bbeSBoris Popov   }
90681a5bbeSBoris Popov 
91681a5bbeSBoris Popov /* MD4 initialization. Begins an MD4 operation, writing a new context.
92681a5bbeSBoris Popov  */
93*80dc9f88SEd Maste void
94*80dc9f88SEd Maste MD4Init(MD4_CTX *context)
95681a5bbeSBoris Popov {
96681a5bbeSBoris Popov   context->count[0] = context->count[1] = 0;
97681a5bbeSBoris Popov 
98681a5bbeSBoris Popov   /* Load magic initialization constants.
99681a5bbeSBoris Popov    */
100681a5bbeSBoris Popov   context->state[0] = 0x67452301;
101681a5bbeSBoris Popov   context->state[1] = 0xefcdab89;
102681a5bbeSBoris Popov   context->state[2] = 0x98badcfe;
103681a5bbeSBoris Popov   context->state[3] = 0x10325476;
104681a5bbeSBoris Popov }
105681a5bbeSBoris Popov 
106681a5bbeSBoris Popov /* MD4 block update operation. Continues an MD4 message-digest
107681a5bbeSBoris Popov      operation, processing another message block, and updating the
108681a5bbeSBoris Popov      context.
109681a5bbeSBoris Popov  */
110*80dc9f88SEd Maste void
111*80dc9f88SEd Maste MD4Update(MD4_CTX *context, const unsigned char *input,
112*80dc9f88SEd Maste     unsigned int inputLen)
113681a5bbeSBoris Popov {
114681a5bbeSBoris Popov   unsigned int i, index, partLen;
115681a5bbeSBoris Popov 
116681a5bbeSBoris Popov   /* Compute number of bytes mod 64 */
117681a5bbeSBoris Popov   index = (unsigned int)((context->count[0] >> 3) & 0x3F);
118681a5bbeSBoris Popov   /* Update number of bits */
119681a5bbeSBoris Popov   if ((context->count[0] += ((UINT4)inputLen << 3))
120681a5bbeSBoris Popov       < ((UINT4)inputLen << 3))
121681a5bbeSBoris Popov     context->count[1]++;
122681a5bbeSBoris Popov   context->count[1] += ((UINT4)inputLen >> 29);
123681a5bbeSBoris Popov 
124681a5bbeSBoris Popov   partLen = 64 - index;
125681a5bbeSBoris Popov   /* Transform as many times as possible.
126681a5bbeSBoris Popov    */
127681a5bbeSBoris Popov   if (inputLen >= partLen) {
128681a5bbeSBoris Popov     bcopy(input, &context->buffer[index], partLen);
129681a5bbeSBoris Popov     MD4Transform (context->state, context->buffer);
130681a5bbeSBoris Popov 
131681a5bbeSBoris Popov     for (i = partLen; i + 63 < inputLen; i += 64)
132681a5bbeSBoris Popov       MD4Transform (context->state, &input[i]);
133681a5bbeSBoris Popov 
134681a5bbeSBoris Popov     index = 0;
135681a5bbeSBoris Popov   }
136681a5bbeSBoris Popov   else
137681a5bbeSBoris Popov     i = 0;
138681a5bbeSBoris Popov 
139681a5bbeSBoris Popov   /* Buffer remaining input */
140681a5bbeSBoris Popov   bcopy(&input[i], &context->buffer[index], inputLen-i);
141681a5bbeSBoris Popov }
142681a5bbeSBoris Popov 
143681a5bbeSBoris Popov /* MD4 padding. */
144*80dc9f88SEd Maste void
145*80dc9f88SEd Maste MD4Pad(MD4_CTX *context)
146681a5bbeSBoris Popov {
147681a5bbeSBoris Popov   unsigned char bits[8];
148681a5bbeSBoris Popov   unsigned int index, padLen;
149681a5bbeSBoris Popov 
150681a5bbeSBoris Popov   /* Save number of bits */
151681a5bbeSBoris Popov   Encode (bits, context->count, 8);
152681a5bbeSBoris Popov 
153681a5bbeSBoris Popov   /* Pad out to 56 mod 64.
154681a5bbeSBoris Popov    */
155681a5bbeSBoris Popov   index = (unsigned int)((context->count[0] >> 3) & 0x3f);
156681a5bbeSBoris Popov   padLen = (index < 56) ? (56 - index) : (120 - index);
157681a5bbeSBoris Popov   MD4Update (context, PADDING, padLen);
158681a5bbeSBoris Popov 
159681a5bbeSBoris Popov   /* Append length (before padding) */
160681a5bbeSBoris Popov   MD4Update (context, bits, 8);
161681a5bbeSBoris Popov }
162681a5bbeSBoris Popov 
163681a5bbeSBoris Popov /* MD4 finalization. Ends an MD4 message-digest operation, writing the
164681a5bbeSBoris Popov      the message digest and zeroizing the context.
165681a5bbeSBoris Popov  */
166*80dc9f88SEd Maste void
167*80dc9f88SEd Maste MD4Final(unsigned char digest[static 16], MD4_CTX *context)
168681a5bbeSBoris Popov {
169681a5bbeSBoris Popov   /* Do padding */
170681a5bbeSBoris Popov   MD4Pad (context);
171681a5bbeSBoris Popov 
172681a5bbeSBoris Popov   /* Store state in digest */
173681a5bbeSBoris Popov   Encode (digest, context->state, 16);
174681a5bbeSBoris Popov 
175681a5bbeSBoris Popov   /* Zeroize sensitive information.
176681a5bbeSBoris Popov    */
177571ebf76SConrad Meyer   bzero(context, sizeof (*context));
178681a5bbeSBoris Popov }
179681a5bbeSBoris Popov 
180681a5bbeSBoris Popov /* MD4 basic transformation. Transforms state based on block.
181681a5bbeSBoris Popov  */
182*80dc9f88SEd Maste static void
183*80dc9f88SEd Maste MD4Transform(UINT4 state[4], const unsigned char block[64])
184681a5bbeSBoris Popov {
185681a5bbeSBoris Popov   UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
186681a5bbeSBoris Popov 
187681a5bbeSBoris Popov   Decode (x, block, 64);
188681a5bbeSBoris Popov 
189681a5bbeSBoris Popov   /* Round 1 */
190681a5bbeSBoris Popov   FF (a, b, c, d, x[ 0], S11); /* 1 */
191681a5bbeSBoris Popov   FF (d, a, b, c, x[ 1], S12); /* 2 */
192681a5bbeSBoris Popov   FF (c, d, a, b, x[ 2], S13); /* 3 */
193681a5bbeSBoris Popov   FF (b, c, d, a, x[ 3], S14); /* 4 */
194681a5bbeSBoris Popov   FF (a, b, c, d, x[ 4], S11); /* 5 */
195681a5bbeSBoris Popov   FF (d, a, b, c, x[ 5], S12); /* 6 */
196681a5bbeSBoris Popov   FF (c, d, a, b, x[ 6], S13); /* 7 */
197681a5bbeSBoris Popov   FF (b, c, d, a, x[ 7], S14); /* 8 */
198681a5bbeSBoris Popov   FF (a, b, c, d, x[ 8], S11); /* 9 */
199681a5bbeSBoris Popov   FF (d, a, b, c, x[ 9], S12); /* 10 */
200681a5bbeSBoris Popov   FF (c, d, a, b, x[10], S13); /* 11 */
201681a5bbeSBoris Popov   FF (b, c, d, a, x[11], S14); /* 12 */
202681a5bbeSBoris Popov   FF (a, b, c, d, x[12], S11); /* 13 */
203681a5bbeSBoris Popov   FF (d, a, b, c, x[13], S12); /* 14 */
204681a5bbeSBoris Popov   FF (c, d, a, b, x[14], S13); /* 15 */
205681a5bbeSBoris Popov   FF (b, c, d, a, x[15], S14); /* 16 */
206681a5bbeSBoris Popov 
207681a5bbeSBoris Popov   /* Round 2 */
208681a5bbeSBoris Popov   GG (a, b, c, d, x[ 0], S21); /* 17 */
209681a5bbeSBoris Popov   GG (d, a, b, c, x[ 4], S22); /* 18 */
210681a5bbeSBoris Popov   GG (c, d, a, b, x[ 8], S23); /* 19 */
211681a5bbeSBoris Popov   GG (b, c, d, a, x[12], S24); /* 20 */
212681a5bbeSBoris Popov   GG (a, b, c, d, x[ 1], S21); /* 21 */
213681a5bbeSBoris Popov   GG (d, a, b, c, x[ 5], S22); /* 22 */
214681a5bbeSBoris Popov   GG (c, d, a, b, x[ 9], S23); /* 23 */
215681a5bbeSBoris Popov   GG (b, c, d, a, x[13], S24); /* 24 */
216681a5bbeSBoris Popov   GG (a, b, c, d, x[ 2], S21); /* 25 */
217681a5bbeSBoris Popov   GG (d, a, b, c, x[ 6], S22); /* 26 */
218681a5bbeSBoris Popov   GG (c, d, a, b, x[10], S23); /* 27 */
219681a5bbeSBoris Popov   GG (b, c, d, a, x[14], S24); /* 28 */
220681a5bbeSBoris Popov   GG (a, b, c, d, x[ 3], S21); /* 29 */
221681a5bbeSBoris Popov   GG (d, a, b, c, x[ 7], S22); /* 30 */
222681a5bbeSBoris Popov   GG (c, d, a, b, x[11], S23); /* 31 */
223681a5bbeSBoris Popov   GG (b, c, d, a, x[15], S24); /* 32 */
224681a5bbeSBoris Popov 
225681a5bbeSBoris Popov   /* Round 3 */
226681a5bbeSBoris Popov   HH (a, b, c, d, x[ 0], S31); /* 33 */
227681a5bbeSBoris Popov   HH (d, a, b, c, x[ 8], S32); /* 34 */
228681a5bbeSBoris Popov   HH (c, d, a, b, x[ 4], S33); /* 35 */
229681a5bbeSBoris Popov   HH (b, c, d, a, x[12], S34); /* 36 */
230681a5bbeSBoris Popov   HH (a, b, c, d, x[ 2], S31); /* 37 */
231681a5bbeSBoris Popov   HH (d, a, b, c, x[10], S32); /* 38 */
232681a5bbeSBoris Popov   HH (c, d, a, b, x[ 6], S33); /* 39 */
233681a5bbeSBoris Popov   HH (b, c, d, a, x[14], S34); /* 40 */
234681a5bbeSBoris Popov   HH (a, b, c, d, x[ 1], S31); /* 41 */
235681a5bbeSBoris Popov   HH (d, a, b, c, x[ 9], S32); /* 42 */
236681a5bbeSBoris Popov   HH (c, d, a, b, x[ 5], S33); /* 43 */
237681a5bbeSBoris Popov   HH (b, c, d, a, x[13], S34); /* 44 */
238681a5bbeSBoris Popov   HH (a, b, c, d, x[ 3], S31); /* 45 */
239681a5bbeSBoris Popov   HH (d, a, b, c, x[11], S32); /* 46 */
240681a5bbeSBoris Popov   HH (c, d, a, b, x[ 7], S33); /* 47 */
241681a5bbeSBoris Popov   HH (b, c, d, a, x[15], S34); /* 48 */
242681a5bbeSBoris Popov 
243681a5bbeSBoris Popov   state[0] += a;
244681a5bbeSBoris Popov   state[1] += b;
245681a5bbeSBoris Popov   state[2] += c;
246681a5bbeSBoris Popov   state[3] += d;
247681a5bbeSBoris Popov 
248681a5bbeSBoris Popov   /* Zeroize sensitive information.
249681a5bbeSBoris Popov    */
250681a5bbeSBoris Popov   bzero((POINTER)x, sizeof (x));
251681a5bbeSBoris Popov }
252681a5bbeSBoris Popov 
253681a5bbeSBoris Popov /* Encodes input (UINT4) into output (unsigned char). Assumes len is
254681a5bbeSBoris Popov      a multiple of 4.
255681a5bbeSBoris Popov  */
256*80dc9f88SEd Maste static void
257*80dc9f88SEd Maste Encode(unsigned char *output, UINT4 *input, unsigned int len)
258681a5bbeSBoris Popov {
259681a5bbeSBoris Popov   unsigned int i, j;
260681a5bbeSBoris Popov 
261681a5bbeSBoris Popov   for (i = 0, j = 0; j < len; i++, j += 4) {
262681a5bbeSBoris Popov     output[j] = (unsigned char)(input[i] & 0xff);
263681a5bbeSBoris Popov     output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
264681a5bbeSBoris Popov     output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
265681a5bbeSBoris Popov     output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
266681a5bbeSBoris Popov   }
267681a5bbeSBoris Popov }
268681a5bbeSBoris Popov 
269681a5bbeSBoris Popov /* Decodes input (unsigned char) into output (UINT4). Assumes len is
270681a5bbeSBoris Popov      a multiple of 4.
271681a5bbeSBoris Popov  */
272*80dc9f88SEd Maste static void
273*80dc9f88SEd Maste Decode(UINT4 *output, const unsigned char *input, unsigned int len)
274681a5bbeSBoris Popov {
275681a5bbeSBoris Popov   unsigned int i, j;
276681a5bbeSBoris Popov 
277681a5bbeSBoris Popov   for (i = 0, j = 0; j < len; i++, j += 4)
278681a5bbeSBoris Popov     output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
279681a5bbeSBoris Popov       (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
280681a5bbeSBoris Popov }
281