xref: /freebsd/sys/kern/md4c.c (revision 442e0975ee4b3d6ea809359b7da670b7bd548435)
1681a5bbeSBoris Popov /* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm
2681a5bbeSBoris Popov  */
3681a5bbeSBoris Popov 
49454b2d8SWarner Losh /*-
562cf53fdSPedro F. Giffuni    SPDX-License-Identifier: RSA-MD
662cf53fdSPedro F. Giffuni 
79454b2d8SWarner Losh    Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
8681a5bbeSBoris Popov 
9681a5bbeSBoris Popov    License to copy and use this software is granted provided that it
10681a5bbeSBoris Popov    is identified as the "RSA Data Security, Inc. MD4 Message-Digest
11681a5bbeSBoris Popov    Algorithm" in all material mentioning or referencing this software
12681a5bbeSBoris Popov    or this function.
13681a5bbeSBoris Popov 
14681a5bbeSBoris Popov    License is also granted to make and use derivative works provided
15681a5bbeSBoris Popov    that such works are identified as "derived from the RSA Data
16681a5bbeSBoris Popov    Security, Inc. MD4 Message-Digest Algorithm" in all material
17681a5bbeSBoris Popov    mentioning or referencing the derived work.
18681a5bbeSBoris Popov 
19681a5bbeSBoris Popov    RSA Data Security, Inc. makes no representations concerning either
20681a5bbeSBoris Popov    the merchantability of this software or the suitability of this
21681a5bbeSBoris Popov    software for any particular purpose. It is provided "as is"
22681a5bbeSBoris Popov    without express or implied warranty of any kind.
23681a5bbeSBoris Popov 
24681a5bbeSBoris Popov    These notices must be retained in any copies of any part of this
25681a5bbeSBoris Popov    documentation and/or software.
26681a5bbeSBoris Popov  */
27681a5bbeSBoris Popov 
28681a5bbeSBoris Popov #include <sys/param.h>
29*442e0975SKyle Evans #ifdef _KERNEL
30681a5bbeSBoris Popov #include <sys/systm.h>
31*442e0975SKyle Evans #else
32*442e0975SKyle Evans #include <string.h>
33*442e0975SKyle Evans #endif
34681a5bbeSBoris Popov #include <sys/md4.h>
35681a5bbeSBoris Popov 
36681a5bbeSBoris Popov typedef unsigned char *POINTER;
372cee5861SJohn Baldwin typedef uint16_t UINT2;
382cee5861SJohn Baldwin typedef uint32_t UINT4;
39681a5bbeSBoris Popov 
40681a5bbeSBoris Popov #define PROTO_LIST(list) list
41681a5bbeSBoris Popov 
42681a5bbeSBoris Popov /* Constants for MD4Transform routine.
43681a5bbeSBoris Popov  */
44681a5bbeSBoris Popov #define S11 3
45681a5bbeSBoris Popov #define S12 7
46681a5bbeSBoris Popov #define S13 11
47681a5bbeSBoris Popov #define S14 19
48681a5bbeSBoris Popov #define S21 3
49681a5bbeSBoris Popov #define S22 5
50681a5bbeSBoris Popov #define S23 9
51681a5bbeSBoris Popov #define S24 13
52681a5bbeSBoris Popov #define S31 3
53681a5bbeSBoris Popov #define S32 9
54681a5bbeSBoris Popov #define S33 11
55681a5bbeSBoris Popov #define S34 15
56681a5bbeSBoris Popov 
57681a5bbeSBoris Popov static void MD4Transform PROTO_LIST ((UINT4 [4], const unsigned char [64]));
58681a5bbeSBoris Popov static void Encode PROTO_LIST
59681a5bbeSBoris Popov   ((unsigned char *, UINT4 *, unsigned int));
60681a5bbeSBoris Popov static void Decode PROTO_LIST
61681a5bbeSBoris Popov   ((UINT4 *, const unsigned char *, unsigned int));
62681a5bbeSBoris Popov 
63681a5bbeSBoris Popov static unsigned char PADDING[64] = {
64681a5bbeSBoris Popov   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
65681a5bbeSBoris Popov   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
66681a5bbeSBoris Popov   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
67681a5bbeSBoris Popov };
68681a5bbeSBoris Popov 
69681a5bbeSBoris Popov /* F, G and H are basic MD4 functions.
70681a5bbeSBoris Popov  */
71681a5bbeSBoris Popov #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
72681a5bbeSBoris Popov #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
73681a5bbeSBoris Popov #define H(x, y, z) ((x) ^ (y) ^ (z))
74681a5bbeSBoris Popov 
75681a5bbeSBoris Popov /* ROTATE_LEFT rotates x left n bits.
76681a5bbeSBoris Popov  */
77681a5bbeSBoris Popov #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
78681a5bbeSBoris Popov 
79681a5bbeSBoris Popov /* FF, GG and HH are transformations for rounds 1, 2 and 3 */
80681a5bbeSBoris Popov /* Rotation is separate from addition to prevent recomputation */
81681a5bbeSBoris Popov #define FF(a, b, c, d, x, s) { \
82681a5bbeSBoris Popov     (a) += F ((b), (c), (d)) + (x); \
83681a5bbeSBoris Popov     (a) = ROTATE_LEFT ((a), (s)); \
84681a5bbeSBoris Popov   }
85681a5bbeSBoris Popov #define GG(a, b, c, d, x, s) { \
86681a5bbeSBoris Popov     (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
87681a5bbeSBoris Popov     (a) = ROTATE_LEFT ((a), (s)); \
88681a5bbeSBoris Popov   }
89681a5bbeSBoris Popov #define HH(a, b, c, d, x, s) { \
90681a5bbeSBoris Popov     (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
91681a5bbeSBoris Popov     (a) = ROTATE_LEFT ((a), (s)); \
92681a5bbeSBoris Popov   }
93681a5bbeSBoris Popov 
94681a5bbeSBoris Popov /* MD4 initialization. Begins an MD4 operation, writing a new context.
95681a5bbeSBoris Popov  */
9680dc9f88SEd Maste void
MD4Init(MD4_CTX * context)9780dc9f88SEd Maste MD4Init(MD4_CTX *context)
98681a5bbeSBoris Popov {
99681a5bbeSBoris Popov   context->count[0] = context->count[1] = 0;
100681a5bbeSBoris Popov 
101681a5bbeSBoris Popov   /* Load magic initialization constants.
102681a5bbeSBoris Popov    */
103681a5bbeSBoris Popov   context->state[0] = 0x67452301;
104681a5bbeSBoris Popov   context->state[1] = 0xefcdab89;
105681a5bbeSBoris Popov   context->state[2] = 0x98badcfe;
106681a5bbeSBoris Popov   context->state[3] = 0x10325476;
107681a5bbeSBoris Popov }
108681a5bbeSBoris Popov 
109681a5bbeSBoris Popov /* MD4 block update operation. Continues an MD4 message-digest
110681a5bbeSBoris Popov      operation, processing another message block, and updating the
111681a5bbeSBoris Popov      context.
112681a5bbeSBoris Popov  */
11380dc9f88SEd Maste void
MD4Update(MD4_CTX * context,const unsigned char * input,unsigned int inputLen)11480dc9f88SEd Maste MD4Update(MD4_CTX *context, const unsigned char *input,
11580dc9f88SEd Maste     unsigned int inputLen)
116681a5bbeSBoris Popov {
117681a5bbeSBoris Popov   unsigned int i, index, partLen;
118681a5bbeSBoris Popov 
119681a5bbeSBoris Popov   /* Compute number of bytes mod 64 */
120681a5bbeSBoris Popov   index = (unsigned int)((context->count[0] >> 3) & 0x3F);
121681a5bbeSBoris Popov   /* Update number of bits */
122681a5bbeSBoris Popov   if ((context->count[0] += ((UINT4)inputLen << 3))
123681a5bbeSBoris Popov       < ((UINT4)inputLen << 3))
124681a5bbeSBoris Popov     context->count[1]++;
125681a5bbeSBoris Popov   context->count[1] += ((UINT4)inputLen >> 29);
126681a5bbeSBoris Popov 
127681a5bbeSBoris Popov   partLen = 64 - index;
128681a5bbeSBoris Popov   /* Transform as many times as possible.
129681a5bbeSBoris Popov    */
130681a5bbeSBoris Popov   if (inputLen >= partLen) {
131681a5bbeSBoris Popov     bcopy(input, &context->buffer[index], partLen);
132681a5bbeSBoris Popov     MD4Transform (context->state, context->buffer);
133681a5bbeSBoris Popov 
134681a5bbeSBoris Popov     for (i = partLen; i + 63 < inputLen; i += 64)
135681a5bbeSBoris Popov       MD4Transform (context->state, &input[i]);
136681a5bbeSBoris Popov 
137681a5bbeSBoris Popov     index = 0;
138681a5bbeSBoris Popov   }
139681a5bbeSBoris Popov   else
140681a5bbeSBoris Popov     i = 0;
141681a5bbeSBoris Popov 
142681a5bbeSBoris Popov   /* Buffer remaining input */
143681a5bbeSBoris Popov   bcopy(&input[i], &context->buffer[index], inputLen-i);
144681a5bbeSBoris Popov }
145681a5bbeSBoris Popov 
146681a5bbeSBoris Popov /* MD4 padding. */
14780dc9f88SEd Maste void
MD4Pad(MD4_CTX * context)14880dc9f88SEd Maste MD4Pad(MD4_CTX *context)
149681a5bbeSBoris Popov {
150681a5bbeSBoris Popov   unsigned char bits[8];
151681a5bbeSBoris Popov   unsigned int index, padLen;
152681a5bbeSBoris Popov 
153681a5bbeSBoris Popov   /* Save number of bits */
154681a5bbeSBoris Popov   Encode (bits, context->count, 8);
155681a5bbeSBoris Popov 
156681a5bbeSBoris Popov   /* Pad out to 56 mod 64.
157681a5bbeSBoris Popov    */
158681a5bbeSBoris Popov   index = (unsigned int)((context->count[0] >> 3) & 0x3f);
159681a5bbeSBoris Popov   padLen = (index < 56) ? (56 - index) : (120 - index);
160681a5bbeSBoris Popov   MD4Update (context, PADDING, padLen);
161681a5bbeSBoris Popov 
162681a5bbeSBoris Popov   /* Append length (before padding) */
163681a5bbeSBoris Popov   MD4Update (context, bits, 8);
164681a5bbeSBoris Popov }
165681a5bbeSBoris Popov 
166681a5bbeSBoris Popov /* MD4 finalization. Ends an MD4 message-digest operation, writing the
167681a5bbeSBoris Popov      the message digest and zeroizing the context.
168681a5bbeSBoris Popov  */
16980dc9f88SEd Maste void
MD4Final(unsigned char digest[static16],MD4_CTX * context)17080dc9f88SEd Maste MD4Final(unsigned char digest[static 16], MD4_CTX *context)
171681a5bbeSBoris Popov {
172681a5bbeSBoris Popov   /* Do padding */
173681a5bbeSBoris Popov   MD4Pad (context);
174681a5bbeSBoris Popov 
175681a5bbeSBoris Popov   /* Store state in digest */
176681a5bbeSBoris Popov   Encode (digest, context->state, 16);
177681a5bbeSBoris Popov 
178681a5bbeSBoris Popov   /* Zeroize sensitive information.
179681a5bbeSBoris Popov    */
180571ebf76SConrad Meyer   bzero(context, sizeof (*context));
181681a5bbeSBoris Popov }
182681a5bbeSBoris Popov 
183681a5bbeSBoris Popov /* MD4 basic transformation. Transforms state based on block.
184681a5bbeSBoris Popov  */
18580dc9f88SEd Maste static void
MD4Transform(UINT4 state[4],const unsigned char block[64])18680dc9f88SEd Maste MD4Transform(UINT4 state[4], const unsigned char block[64])
187681a5bbeSBoris Popov {
188681a5bbeSBoris Popov   UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
189681a5bbeSBoris Popov 
190681a5bbeSBoris Popov   Decode (x, block, 64);
191681a5bbeSBoris Popov 
192681a5bbeSBoris Popov   /* Round 1 */
193681a5bbeSBoris Popov   FF (a, b, c, d, x[ 0], S11); /* 1 */
194681a5bbeSBoris Popov   FF (d, a, b, c, x[ 1], S12); /* 2 */
195681a5bbeSBoris Popov   FF (c, d, a, b, x[ 2], S13); /* 3 */
196681a5bbeSBoris Popov   FF (b, c, d, a, x[ 3], S14); /* 4 */
197681a5bbeSBoris Popov   FF (a, b, c, d, x[ 4], S11); /* 5 */
198681a5bbeSBoris Popov   FF (d, a, b, c, x[ 5], S12); /* 6 */
199681a5bbeSBoris Popov   FF (c, d, a, b, x[ 6], S13); /* 7 */
200681a5bbeSBoris Popov   FF (b, c, d, a, x[ 7], S14); /* 8 */
201681a5bbeSBoris Popov   FF (a, b, c, d, x[ 8], S11); /* 9 */
202681a5bbeSBoris Popov   FF (d, a, b, c, x[ 9], S12); /* 10 */
203681a5bbeSBoris Popov   FF (c, d, a, b, x[10], S13); /* 11 */
204681a5bbeSBoris Popov   FF (b, c, d, a, x[11], S14); /* 12 */
205681a5bbeSBoris Popov   FF (a, b, c, d, x[12], S11); /* 13 */
206681a5bbeSBoris Popov   FF (d, a, b, c, x[13], S12); /* 14 */
207681a5bbeSBoris Popov   FF (c, d, a, b, x[14], S13); /* 15 */
208681a5bbeSBoris Popov   FF (b, c, d, a, x[15], S14); /* 16 */
209681a5bbeSBoris Popov 
210681a5bbeSBoris Popov   /* Round 2 */
211681a5bbeSBoris Popov   GG (a, b, c, d, x[ 0], S21); /* 17 */
212681a5bbeSBoris Popov   GG (d, a, b, c, x[ 4], S22); /* 18 */
213681a5bbeSBoris Popov   GG (c, d, a, b, x[ 8], S23); /* 19 */
214681a5bbeSBoris Popov   GG (b, c, d, a, x[12], S24); /* 20 */
215681a5bbeSBoris Popov   GG (a, b, c, d, x[ 1], S21); /* 21 */
216681a5bbeSBoris Popov   GG (d, a, b, c, x[ 5], S22); /* 22 */
217681a5bbeSBoris Popov   GG (c, d, a, b, x[ 9], S23); /* 23 */
218681a5bbeSBoris Popov   GG (b, c, d, a, x[13], S24); /* 24 */
219681a5bbeSBoris Popov   GG (a, b, c, d, x[ 2], S21); /* 25 */
220681a5bbeSBoris Popov   GG (d, a, b, c, x[ 6], S22); /* 26 */
221681a5bbeSBoris Popov   GG (c, d, a, b, x[10], S23); /* 27 */
222681a5bbeSBoris Popov   GG (b, c, d, a, x[14], S24); /* 28 */
223681a5bbeSBoris Popov   GG (a, b, c, d, x[ 3], S21); /* 29 */
224681a5bbeSBoris Popov   GG (d, a, b, c, x[ 7], S22); /* 30 */
225681a5bbeSBoris Popov   GG (c, d, a, b, x[11], S23); /* 31 */
226681a5bbeSBoris Popov   GG (b, c, d, a, x[15], S24); /* 32 */
227681a5bbeSBoris Popov 
228681a5bbeSBoris Popov   /* Round 3 */
229681a5bbeSBoris Popov   HH (a, b, c, d, x[ 0], S31); /* 33 */
230681a5bbeSBoris Popov   HH (d, a, b, c, x[ 8], S32); /* 34 */
231681a5bbeSBoris Popov   HH (c, d, a, b, x[ 4], S33); /* 35 */
232681a5bbeSBoris Popov   HH (b, c, d, a, x[12], S34); /* 36 */
233681a5bbeSBoris Popov   HH (a, b, c, d, x[ 2], S31); /* 37 */
234681a5bbeSBoris Popov   HH (d, a, b, c, x[10], S32); /* 38 */
235681a5bbeSBoris Popov   HH (c, d, a, b, x[ 6], S33); /* 39 */
236681a5bbeSBoris Popov   HH (b, c, d, a, x[14], S34); /* 40 */
237681a5bbeSBoris Popov   HH (a, b, c, d, x[ 1], S31); /* 41 */
238681a5bbeSBoris Popov   HH (d, a, b, c, x[ 9], S32); /* 42 */
239681a5bbeSBoris Popov   HH (c, d, a, b, x[ 5], S33); /* 43 */
240681a5bbeSBoris Popov   HH (b, c, d, a, x[13], S34); /* 44 */
241681a5bbeSBoris Popov   HH (a, b, c, d, x[ 3], S31); /* 45 */
242681a5bbeSBoris Popov   HH (d, a, b, c, x[11], S32); /* 46 */
243681a5bbeSBoris Popov   HH (c, d, a, b, x[ 7], S33); /* 47 */
244681a5bbeSBoris Popov   HH (b, c, d, a, x[15], S34); /* 48 */
245681a5bbeSBoris Popov 
246681a5bbeSBoris Popov   state[0] += a;
247681a5bbeSBoris Popov   state[1] += b;
248681a5bbeSBoris Popov   state[2] += c;
249681a5bbeSBoris Popov   state[3] += d;
250681a5bbeSBoris Popov 
251681a5bbeSBoris Popov   /* Zeroize sensitive information.
252681a5bbeSBoris Popov    */
253681a5bbeSBoris Popov   bzero((POINTER)x, sizeof (x));
254681a5bbeSBoris Popov }
255681a5bbeSBoris Popov 
256681a5bbeSBoris Popov /* Encodes input (UINT4) into output (unsigned char). Assumes len is
257681a5bbeSBoris Popov      a multiple of 4.
258681a5bbeSBoris Popov  */
25980dc9f88SEd Maste static void
Encode(unsigned char * output,UINT4 * input,unsigned int len)26080dc9f88SEd Maste Encode(unsigned char *output, UINT4 *input, unsigned int len)
261681a5bbeSBoris Popov {
262681a5bbeSBoris Popov   unsigned int i, j;
263681a5bbeSBoris Popov 
264681a5bbeSBoris Popov   for (i = 0, j = 0; j < len; i++, j += 4) {
265681a5bbeSBoris Popov     output[j] = (unsigned char)(input[i] & 0xff);
266681a5bbeSBoris Popov     output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
267681a5bbeSBoris Popov     output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
268681a5bbeSBoris Popov     output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
269681a5bbeSBoris Popov   }
270681a5bbeSBoris Popov }
271681a5bbeSBoris Popov 
272681a5bbeSBoris Popov /* Decodes input (unsigned char) into output (UINT4). Assumes len is
273681a5bbeSBoris Popov      a multiple of 4.
274681a5bbeSBoris Popov  */
27580dc9f88SEd Maste static void
Decode(UINT4 * output,const unsigned char * input,unsigned int len)27680dc9f88SEd Maste Decode(UINT4 *output, const unsigned char *input, unsigned int len)
277681a5bbeSBoris Popov {
278681a5bbeSBoris Popov   unsigned int i, j;
279681a5bbeSBoris Popov 
280681a5bbeSBoris Popov   for (i = 0, j = 0; j < len; i++, j += 4)
281681a5bbeSBoris Popov     output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
282681a5bbeSBoris Popov       (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
283681a5bbeSBoris Popov }
284*442e0975SKyle Evans 
285*442e0975SKyle Evans #ifdef WEAK_REFS
286*442e0975SKyle Evans /* When building libmd, provide weak references. Note: this is not
287*442e0975SKyle Evans    activated in the context of compiling these sources for internal
288*442e0975SKyle Evans    use in libcrypt.
289*442e0975SKyle Evans  */
290*442e0975SKyle Evans #undef MD4Init
291*442e0975SKyle Evans __weak_reference(_libmd_MD4Init, MD4Init);
292*442e0975SKyle Evans #undef MD4Update
293*442e0975SKyle Evans __weak_reference(_libmd_MD4Update, MD4Update);
294*442e0975SKyle Evans #undef MD4Pad
295*442e0975SKyle Evans __weak_reference(_libmd_MD4Pad, MD4Pad);
296*442e0975SKyle Evans #undef MD4Final
297*442e0975SKyle Evans __weak_reference(_libmd_MD4Final, MD4Final);
298*442e0975SKyle Evans #endif
299