]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/opie/libopie/md4c.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / opie / libopie / md4c.c
1 /* md4c.c: "RSA Data Security, Inc. MD4 Message-Digest Algorithm"
2
3 %%% portions-copyright-cmetz-96
4 Portions of this software are Copyright 1996-1999 by Craig Metz, All Rights
5 Reserved. The Inner Net License Version 2 applies to these portions of
6 the software.
7 You should have received a copy of the license with this software. If
8 you didn't get a copy, you may request one from <license@inner.net>.
9
10 Portions of this software are Copyright 1995 by Randall Atkinson and Dan
11 McDonald, All Rights Reserved. All Rights under this copyright are assigned
12 to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
13 License Agreement applies to this software.
14
15         History:
16
17         Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
18               Use the real memcpy() and memset(). Use unified context
19               structure.
20         Modified at NRL for OPIE 2.0.
21         Originally from RSADSI reference code.
22 */
23 /* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
24
25    License to copy and use this software is granted provided that it
26    is identified as the "RSA Data Security, Inc. MD4 Message-Digest
27    Algorithm" in all material mentioning or referencing this software
28    or this function.
29
30    License is also granted to make and use derivative works provided
31    that such works are identified as "derived from the RSA Data
32    Security, Inc. MD4 Message-Digest Algorithm" in all material
33    mentioning or referencing the derived work.
34
35    RSA Data Security, Inc. makes no representations concerning either
36    the merchantability of this software or the suitability of this
37    software for any particular purpose. It is provided "as is"
38    without express or implied warranty of any kind.
39
40    These notices must be retained in any copies of any part of this
41    documentation and/or software.
42  */
43
44 #include "opie_cfg.h"
45 #include "opie.h"
46
47 /* Constants for MD4Transform routine.
48  */
49 #define S11 3
50 #define S12 7
51 #define S13 11
52 #define S14 19
53 #define S21 3
54 #define S22 5
55 #define S23 9
56 #define S24 13
57 #define S31 3
58 #define S32 9
59 #define S33 11
60 #define S34 15
61
62 static VOIDRET MD4Transform __P((UINT4[4], unsigned char[64]));
63 static VOIDRET Encode __P((unsigned char *, UINT4 *, unsigned int));
64 static VOIDRET Decode __P((UINT4 *, unsigned char *, unsigned int));
65
66 static unsigned char PADDING[64] =
67 {
68   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
71 };
72
73 /* F, G and H are basic MD4 functions.
74  */
75 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
76 #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
77 #define H(x, y, z) ((x) ^ (y) ^ (z))
78
79 /* ROTATE_LEFT rotates x left n bits.
80  */
81 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
82
83 /* FF, GG and HH are transformations for rounds 1, 2 and 3 */
84 /* Rotation is separate from addition to prevent recomputation */
85
86 #define FF(a, b, c, d, x, s) { \
87     (a) += F ((b), (c), (d)) + (x); \
88     (a) = ROTATE_LEFT ((a), (s)); \
89   }
90 #define GG(a, b, c, d, x, s) { \
91     (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
92     (a) = ROTATE_LEFT ((a), (s)); \
93   }
94 #define HH(a, b, c, d, x, s) { \
95     (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
96     (a) = ROTATE_LEFT ((a), (s)); \
97   }
98
99 /* MD4 initialization. Begins an MD4 operation, writing a new context.
100  */
101 VOIDRET opiemd4init FUNCTION((context), struct opiemdx_ctx *context)
102 {
103   context->count[0] = context->count[1] = 0;
104
105   /* Load magic initialization constants. */
106   context->state[0] = 0x67452301;
107   context->state[1] = 0xefcdab89;
108   context->state[2] = 0x98badcfe;
109   context->state[3] = 0x10325476;
110 }
111
112 /* MD4 block update operation. Continues an MD4 message-digest
113    operation, processing another message block, and updating the
114    context.
115  */
116 VOIDRET opiemd4update FUNCTION((context, input, inputLen), struct opiemdx_ctx *context AND unsigned char *input AND unsigned int inputLen)
117 {
118   unsigned int i, index, partLen;
119
120   /* Compute number of bytes mod 64 */
121   index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
122   /* Update number of bits */
123   if ((context->count[0] += ((UINT4) inputLen << 3))
124       < ((UINT4) inputLen << 3))
125     context->count[1]++;
126   context->count[1] += ((UINT4) inputLen >> 29);
127
128   partLen = 64 - index;
129
130   /* Transform as many times as possible. */
131   if (inputLen >= partLen) {
132     memcpy((POINTER) & context->buffer[index], (POINTER) input, partLen);
133     MD4Transform(context->state, context->buffer);
134
135     for (i = partLen; i + 63 < inputLen; i += 64)
136       MD4Transform(context->state, &input[i]);
137
138     index = 0;
139   } else
140     i = 0;
141
142   /* Buffer remaining input */
143   memcpy((POINTER) & context->buffer[index], (POINTER) & input[i], inputLen - i);
144 }
145
146 /* MD4 finalization. Ends an MD4 message-digest operation, writing the
147    the message digest and zeroizing the context.
148  */
149 VOIDRET opiemd4final FUNCTION((digest, context), unsigned char *digest AND struct opiemdx_ctx *context)
150 {
151   unsigned char bits[8];
152   unsigned int index, padLen;
153
154   /* Save number of bits */
155   Encode(bits, context->count, 8);
156
157   /* Pad out to 56 mod 64. */
158   index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
159   padLen = (index < 56) ? (56 - index) : (120 - index);
160   opiemd4update(context, PADDING, padLen);
161
162   /* Append length (before padding) */
163   opiemd4update(context, bits, 8);
164   /* Store state in digest */
165   Encode(digest, context->state, 16);
166
167   /* Zeroize sensitive information. */
168   memset((POINTER) context, 0, sizeof(*context));
169 }
170
171 /* MD4 basic transformation. Transforms state based on block.
172  */
173 static VOIDRET MD4Transform FUNCTION((state, block), UINT4 state[4] AND unsigned char block[64])
174 {
175   UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
176
177   Decode(x, block, 64);
178
179   /* Round 1 */
180   FF(a, b, c, d, x[0], S11);    /* 1 */
181   FF(d, a, b, c, x[1], S12);    /* 2 */
182   FF(c, d, a, b, x[2], S13);    /* 3 */
183   FF(b, c, d, a, x[3], S14);    /* 4 */
184   FF(a, b, c, d, x[4], S11);    /* 5 */
185   FF(d, a, b, c, x[5], S12);    /* 6 */
186   FF(c, d, a, b, x[6], S13);    /* 7 */
187   FF(b, c, d, a, x[7], S14);    /* 8 */
188   FF(a, b, c, d, x[8], S11);    /* 9 */
189   FF(d, a, b, c, x[9], S12);    /* 10 */
190   FF(c, d, a, b, x[10], S13);   /* 11 */
191   FF(b, c, d, a, x[11], S14);   /* 12 */
192   FF(a, b, c, d, x[12], S11);   /* 13 */
193   FF(d, a, b, c, x[13], S12);   /* 14 */
194   FF(c, d, a, b, x[14], S13);   /* 15 */
195   FF(b, c, d, a, x[15], S14);   /* 16 */
196
197   /* Round 2 */
198   GG(a, b, c, d, x[0], S21);    /* 17 */
199   GG(d, a, b, c, x[4], S22);    /* 18 */
200   GG(c, d, a, b, x[8], S23);    /* 19 */
201   GG(b, c, d, a, x[12], S24);   /* 20 */
202   GG(a, b, c, d, x[1], S21);    /* 21 */
203   GG(d, a, b, c, x[5], S22);    /* 22 */
204   GG(c, d, a, b, x[9], S23);    /* 23 */
205   GG(b, c, d, a, x[13], S24);   /* 24 */
206   GG(a, b, c, d, x[2], S21);    /* 25 */
207   GG(d, a, b, c, x[6], S22);    /* 26 */
208   GG(c, d, a, b, x[10], S23);   /* 27 */
209   GG(b, c, d, a, x[14], S24);   /* 28 */
210   GG(a, b, c, d, x[3], S21);    /* 29 */
211   GG(d, a, b, c, x[7], S22);    /* 30 */
212   GG(c, d, a, b, x[11], S23);   /* 31 */
213   GG(b, c, d, a, x[15], S24);   /* 32 */
214
215   /* Round 3 */
216   HH(a, b, c, d, x[0], S31);    /* 33 */
217   HH(d, a, b, c, x[8], S32);    /* 34 */
218   HH(c, d, a, b, x[4], S33);    /* 35 */
219   HH(b, c, d, a, x[12], S34);   /* 36 */
220   HH(a, b, c, d, x[2], S31);    /* 37 */
221   HH(d, a, b, c, x[10], S32);   /* 38 */
222   HH(c, d, a, b, x[6], S33);    /* 39 */
223   HH(b, c, d, a, x[14], S34);   /* 40 */
224   HH(a, b, c, d, x[1], S31);    /* 41 */
225   HH(d, a, b, c, x[9], S32);    /* 42 */
226   HH(c, d, a, b, x[5], S33);    /* 43 */
227   HH(b, c, d, a, x[13], S34);   /* 44 */
228   HH(a, b, c, d, x[3], S31);    /* 45 */
229   HH(d, a, b, c, x[11], S32);   /* 46 */
230   HH(c, d, a, b, x[7], S33);    /* 47 */
231   HH(b, c, d, a, x[15], S34);   /* 48 */
232
233   state[0] += a;
234   state[1] += b;
235   state[2] += c;
236   state[3] += d;
237
238   /* Zeroize sensitive information. */
239   memset((POINTER) x, 0, sizeof(x));
240 }
241
242 /* Encodes input (UINT4) into output (unsigned char). Assumes len is
243    a multiple of 4.
244  */
245 static VOIDRET Encode FUNCTION((output, input, len), unsigned char *output AND UINT4 *input AND unsigned int len)
246 {
247   unsigned int i, j;
248
249   for (i = 0, j = 0; j < len; i++, j += 4) {
250     output[j] = (unsigned char) (input[i] & 0xff);
251     output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
252     output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
253     output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
254   }
255 }
256
257 /* Decodes input (unsigned char) into output (UINT4). Assumes len is
258    a multiple of 4.
259  */
260 static VOIDRET Decode FUNCTION((output, input, len), UINT4 *output AND unsigned char *input AND unsigned int len)
261 {
262   unsigned int i, j;
263
264   for (i = 0, j = 0; j < len; i++, j += 4)
265     output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
266       (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
267 }