204d59637ea04707d417d3c8996dcc38b0e79cd1
[reactos.git] / reactos / dll / win32 / advapi32 / crypt / crypt_md4.c
1 /*
2 * Copyright (C) 2001 Nikos Mavroyanopoulos
3 * Copyright (C) 2004 Hans Leidekker
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * This code implements the MD4 message-digest algorithm.
22 * It is based on code in the public domain written by Colin
23 * Plumb in 1993. The algorithm is due to Ron Rivest.
24 *
25 * Equivalent code is available from RSA Data Security, Inc.
26 * This code has been tested against that, and is equivalent,
27 * except that you don't need to include two pages of legalese
28 * with every copy.
29 *
30 * To compute the message digest of a chunk of bytes, declare an
31 * MD4_CTX structure, pass it to MD4Init, call MD4Update as
32 * needed on buffers full of bytes, and then call MD4Final, which
33 * will fill a supplied 16-byte array with the digest.
34 */
35
36 #include <advapi32.h>
37 #include "crypt.h"
38
39
40 /* The three core functions */
41
42 #define rotl32(x,n) (((x) << ((unsigned int)(n))) | ((x) >> (32 - (unsigned int)(n))))
43
44 #define F( x, y, z ) (((x) & (y)) | ((~x) & (z)))
45 #define G( x, y, z ) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
46 #define H( x, y, z ) ((x) ^ (y) ^ (z))
47
48 #define FF( a, b, c, d, x, s ) { \
49 (a) += F( (b), (c), (d) ) + (x); \
50 (a) = rotl32( (a), (s) ); \
51 }
52 #define GG( a, b, c, d, x, s ) { \
53 (a) += G( (b), (c), (d) ) + (x) + (unsigned int)0x5a827999; \
54 (a) = rotl32( (a), (s) ); \
55 }
56 #define HH( a, b, c, d, x, s ) { \
57 (a) += H( (b), (c), (d) ) + (x) + (unsigned int)0x6ed9eba1; \
58 (a) = rotl32( (a), (s) ); \
59 }
60
61 /*
62 * The core of the MD4 algorithm
63 */
64 static VOID MD4Transform(unsigned int buf[4], const unsigned int in[16])
65 {
66 register unsigned int a, b, c, d;
67
68 a = buf[0];
69 b = buf[1];
70 c = buf[2];
71 d = buf[3];
72
73 FF( a, b, c, d, in[0], 3 );
74 FF( d, a, b, c, in[1], 7 );
75 FF( c, d, a, b, in[2], 11 );
76 FF( b, c, d, a, in[3], 19 );
77 FF( a, b, c, d, in[4], 3 );
78 FF( d, a, b, c, in[5], 7 );
79 FF( c, d, a, b, in[6], 11 );
80 FF( b, c, d, a, in[7], 19 );
81 FF( a, b, c, d, in[8], 3 );
82 FF( d, a, b, c, in[9], 7 );
83 FF( c, d, a, b, in[10], 11 );
84 FF( b, c, d, a, in[11], 19 );
85 FF( a, b, c, d, in[12], 3 );
86 FF( d, a, b, c, in[13], 7 );
87 FF( c, d, a, b, in[14], 11 );
88 FF( b, c, d, a, in[15], 19 );
89
90 GG( a, b, c, d, in[0], 3 );
91 GG( d, a, b, c, in[4], 5 );
92 GG( c, d, a, b, in[8], 9 );
93 GG( b, c, d, a, in[12], 13 );
94 GG( a, b, c, d, in[1], 3 );
95 GG( d, a, b, c, in[5], 5 );
96 GG( c, d, a, b, in[9], 9 );
97 GG( b, c, d, a, in[13], 13 );
98 GG( a, b, c, d, in[2], 3 );
99 GG( d, a, b, c, in[6], 5 );
100 GG( c, d, a, b, in[10], 9 );
101 GG( b, c, d, a, in[14], 13 );
102 GG( a, b, c, d, in[3], 3 );
103 GG( d, a, b, c, in[7], 5 );
104 GG( c, d, a, b, in[11], 9 );
105 GG( b, c, d, a, in[15], 13 );
106
107 HH( a, b, c, d, in[0], 3 );
108 HH( d, a, b, c, in[8], 9 );
109 HH( c, d, a, b, in[4], 11 );
110 HH( b, c, d, a, in[12], 15 );
111 HH( a, b, c, d, in[2], 3 );
112 HH( d, a, b, c, in[10], 9 );
113 HH( c, d, a, b, in[6], 11 );
114 HH( b, c, d, a, in[14], 15 );
115 HH( a, b, c, d, in[1], 3 );
116 HH( d, a, b, c, in[9], 9 );
117 HH( c, d, a, b, in[5], 11 );
118 HH( b, c, d, a, in[13], 15 );
119 HH( a, b, c, d, in[3], 3 );
120 HH( d, a, b, c, in[11], 9 );
121 HH( c, d, a, b, in[7], 11 );
122 HH( b, c, d, a, in[15], 15 );
123
124 buf[0] += a;
125 buf[1] += b;
126 buf[2] += c;
127 buf[3] += d;
128 }
129
130 /*
131 * Start MD4 accumulation. Set bit count to 0 and buffer to mysterious
132 * initialization constants.
133 */
134 VOID WINAPI MD4Init(MD4_CTX *ctx)
135 {
136 ctx->buf[0] = 0x67452301;
137 ctx->buf[1] = 0xefcdab89;
138 ctx->buf[2] = 0x98badcfe;
139 ctx->buf[3] = 0x10325476;
140
141 ctx->i[0] = ctx->i[1] = 0;
142 }
143
144 /*
145 * Update context to reflect the concatenation of another buffer full
146 * of bytes.
147 */
148 VOID WINAPI MD4Update(MD4_CTX *ctx, const unsigned char *buf, unsigned int len)
149 {
150 register unsigned int t;
151
152 /* Update bitcount */
153 t = ctx->i[0];
154
155 if ((ctx->i[0] = t + ((unsigned int)len << 3)) < t)
156 ctx->i[1]++; /* Carry from low to high */
157
158 ctx->i[1] += len >> 29;
159 t = (t >> 3) & 0x3f;
160
161 /* Handle any leading odd-sized chunks */
162 if (t)
163 {
164 unsigned char *p = (unsigned char *)ctx->in + t;
165 t = 64 - t;
166
167 if (len < t)
168 {
169 memcpy(p, buf, len);
170 return;
171 }
172
173 memcpy(p, buf, t);
174 byteReverse(ctx->in, 16);
175
176 MD4Transform(ctx->buf, (unsigned int *)ctx->in);
177
178 buf += t;
179 len -= t;
180 }
181
182 /* Process data in 64-byte chunks */
183 while (len >= 64)
184 {
185 memcpy(ctx->in, buf, 64);
186 byteReverse(ctx->in, 16);
187
188 MD4Transform(ctx->buf, (unsigned int *)ctx->in);
189
190 buf += 64;
191 len -= 64;
192 }
193
194 /* Handle any remaining bytes of data. */
195 memcpy(ctx->in, buf, len);
196 }
197
198 /*
199 * Final wrapup - pad to 64-byte boundary with the bit pattern
200 * 1 0* (64-bit count of bits processed, MSB-first)
201 */
202 VOID WINAPI MD4Final(MD4_CTX *ctx)
203 {
204 unsigned int count;
205 unsigned char *p;
206
207 /* Compute number of bytes mod 64 */
208 count = (ctx->i[0] >> 3) & 0x3F;
209
210 /* Set the first char of padding to 0x80. This is safe since there is
211 always at least one byte free */
212 p = ctx->in + count;
213 *p++ = 0x80;
214
215 /* Bytes of padding needed to make 64 bytes */
216 count = 64 - 1 - count;
217
218 /* Pad out to 56 mod 64 */
219 if (count < 8)
220 {
221 /* Two lots of padding: Pad the first block to 64 bytes */
222 memset( p, 0, count );
223 byteReverse(ctx->in, 16);
224 MD4Transform(ctx->buf, (unsigned int *)ctx->in);
225
226 /* Now fill the next block with 56 bytes */
227 memset(ctx->in, 0, 56);
228 }
229 else
230 {
231 /* Pad block to 56 bytes */
232 memset(p, 0, count - 8);
233 }
234
235 byteReverse(ctx->in, 14);
236
237 /* Append length in bits and transform */
238 ((unsigned int *)ctx->in)[14] = ctx->i[0];
239 ((unsigned int *)ctx->in)[15] = ctx->i[1];
240
241 MD4Transform( ctx->buf, (unsigned int *)ctx->in );
242 byteReverse( (unsigned char *)ctx->buf, 4 );
243 memcpy(ctx->digest, ctx->buf, 16);
244 }