source: trunk/src/advapi32/crypt_md4.cpp

Last change on this file was 21326, checked in by ydario, 16 years ago

advapi32 and crypt32 updates.

  • Property svn:eol-style set to native
File size: 8.5 KB
Line 
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 St, 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 <stdarg.h>
37
38#include "ntstatus.h"
39#define WIN32_NO_STATUS
40#include "windef.h"
41#include "winternl.h"
42
43#include <string.h>
44
45typedef struct
46{
47 unsigned int buf[4];
48 unsigned int i[2];
49 unsigned char in[64];
50 unsigned char digest[16];
51} MD4_CTX;
52
53static void MD4Transform( unsigned int buf[4], unsigned int const in[16] );
54
55/*
56 * Note: this code is harmless on little-endian machines.
57 */
58static void byteReverse( unsigned char *buf, unsigned longs )
59{
60 unsigned int t;
61
62 do {
63 t = ((unsigned)buf[3] << 8 | buf[2]) << 16 |
64 ((unsigned)buf[1] << 8 | buf[0]);
65 *(unsigned int *)buf = t;
66 buf += 4;
67 } while (--longs);
68}
69
70/*
71 * Start MD4 accumulation. Set bit count to 0 and buffer to mysterious
72 * initialization constants.
73 */
74VOID WINAPI MD4Init( MD4_CTX *ctx )
75{
76 ctx->buf[0] = 0x67452301;
77 ctx->buf[1] = 0xefcdab89;
78 ctx->buf[2] = 0x98badcfe;
79 ctx->buf[3] = 0x10325476;
80
81 ctx->i[0] = ctx->i[1] = 0;
82}
83
84/*
85 * Update context to reflect the concatenation of another buffer full
86 * of bytes.
87 */
88VOID WINAPI MD4Update( MD4_CTX *ctx, const unsigned char *buf, unsigned int len )
89{
90 register unsigned int t;
91
92 /* Update bitcount */
93 t = ctx->i[0];
94
95 if ((ctx->i[0] = t + (len << 3)) < t)
96 ctx->i[1]++; /* Carry from low to high */
97
98 ctx->i[1] += len >> 29;
99 t = (t >> 3) & 0x3f;
100
101 /* Handle any leading odd-sized chunks */
102 if (t)
103 {
104 unsigned char *p = (unsigned char *)ctx->in + t;
105 t = 64 - t;
106
107 if (len < t)
108 {
109 memcpy( p, buf, len );
110 return;
111 }
112
113 memcpy( p, buf, t );
114 byteReverse( ctx->in, 16 );
115
116 MD4Transform( ctx->buf, (unsigned int *)ctx->in );
117
118 buf += t;
119 len -= t;
120 }
121
122 /* Process data in 64-byte chunks */
123 while (len >= 64)
124 {
125 memcpy( ctx->in, buf, 64 );
126 byteReverse( ctx->in, 16 );
127
128 MD4Transform( ctx->buf, (unsigned int *)ctx->in );
129
130 buf += 64;
131 len -= 64;
132 }
133
134 /* Handle any remaining bytes of data. */
135 memcpy( ctx->in, buf, len );
136}
137
138/*
139 * Final wrapup - pad to 64-byte boundary with the bit pattern
140 * 1 0* (64-bit count of bits processed, MSB-first)
141 */
142VOID WINAPI MD4Final( MD4_CTX *ctx )
143{
144 unsigned int count;
145 unsigned char *p;
146
147 /* Compute number of bytes mod 64 */
148 count = (ctx->i[0] >> 3) & 0x3F;
149
150 /* Set the first char of padding to 0x80. This is safe since there is
151 always at least one byte free */
152 p = ctx->in + count;
153 *p++ = 0x80;
154
155 /* Bytes of padding needed to make 64 bytes */
156 count = 64 - 1 - count;
157
158 /* Pad out to 56 mod 64 */
159 if (count < 8)
160 {
161 /* Two lots of padding: Pad the first block to 64 bytes */
162 memset( p, 0, count );
163 byteReverse( ctx->in, 16 );
164 MD4Transform( ctx->buf, (unsigned int *)ctx->in );
165
166 /* Now fill the next block with 56 bytes */
167 memset( ctx->in, 0, 56 );
168 }
169 else
170 {
171 /* Pad block to 56 bytes */
172 memset( p, 0, count - 8 );
173 }
174
175 byteReverse( ctx->in, 14 );
176
177 /* Append length in bits and transform */
178 ((unsigned int *)ctx->in)[14] = ctx->i[0];
179 ((unsigned int *)ctx->in)[15] = ctx->i[1];
180
181 MD4Transform( ctx->buf, (unsigned int *)ctx->in );
182 byteReverse( (unsigned char *)ctx->buf, 4 );
183 memcpy( ctx->digest, ctx->buf, 16 );
184}
185
186/* The three core functions */
187
188#define rotl32(x,n) (((x) << ((unsigned int)(n))) | ((x) >> (32 - (unsigned int)(n))))
189
190#define F( x, y, z ) (((x) & (y)) | ((~x) & (z)))
191#define G( x, y, z ) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
192#define H( x, y, z ) ((x) ^ (y) ^ (z))
193
194#define FF( a, b, c, d, x, s ) { \
195 (a) += F( (b), (c), (d) ) + (x); \
196 (a) = rotl32( (a), (s) ); \
197 }
198#define GG( a, b, c, d, x, s ) { \
199 (a) += G( (b), (c), (d) ) + (x) + (unsigned int)0x5a827999; \
200 (a) = rotl32( (a), (s) ); \
201 }
202#define HH( a, b, c, d, x, s ) { \
203 (a) += H( (b), (c), (d) ) + (x) + (unsigned int)0x6ed9eba1; \
204 (a) = rotl32( (a), (s) ); \
205 }
206
207/*
208 * The core of the MD4 algorithm
209 */
210static void MD4Transform( unsigned int buf[4], const unsigned int in[16] )
211{
212 register unsigned int a, b, c, d;
213
214 a = buf[0];
215 b = buf[1];
216 c = buf[2];
217 d = buf[3];
218
219 FF( a, b, c, d, in[0], 3 );
220 FF( d, a, b, c, in[1], 7 );
221 FF( c, d, a, b, in[2], 11 );
222 FF( b, c, d, a, in[3], 19 );
223 FF( a, b, c, d, in[4], 3 );
224 FF( d, a, b, c, in[5], 7 );
225 FF( c, d, a, b, in[6], 11 );
226 FF( b, c, d, a, in[7], 19 );
227 FF( a, b, c, d, in[8], 3 );
228 FF( d, a, b, c, in[9], 7 );
229 FF( c, d, a, b, in[10], 11 );
230 FF( b, c, d, a, in[11], 19 );
231 FF( a, b, c, d, in[12], 3 );
232 FF( d, a, b, c, in[13], 7 );
233 FF( c, d, a, b, in[14], 11 );
234 FF( b, c, d, a, in[15], 19 );
235
236 GG( a, b, c, d, in[0], 3 );
237 GG( d, a, b, c, in[4], 5 );
238 GG( c, d, a, b, in[8], 9 );
239 GG( b, c, d, a, in[12], 13 );
240 GG( a, b, c, d, in[1], 3 );
241 GG( d, a, b, c, in[5], 5 );
242 GG( c, d, a, b, in[9], 9 );
243 GG( b, c, d, a, in[13], 13 );
244 GG( a, b, c, d, in[2], 3 );
245 GG( d, a, b, c, in[6], 5 );
246 GG( c, d, a, b, in[10], 9 );
247 GG( b, c, d, a, in[14], 13 );
248 GG( a, b, c, d, in[3], 3 );
249 GG( d, a, b, c, in[7], 5 );
250 GG( c, d, a, b, in[11], 9 );
251 GG( b, c, d, a, in[15], 13 );
252
253 HH( a, b, c, d, in[0], 3 );
254 HH( d, a, b, c, in[8], 9 );
255 HH( c, d, a, b, in[4], 11 );
256 HH( b, c, d, a, in[12], 15 );
257 HH( a, b, c, d, in[2], 3 );
258 HH( d, a, b, c, in[10], 9 );
259 HH( c, d, a, b, in[6], 11 );
260 HH( b, c, d, a, in[14], 15 );
261 HH( a, b, c, d, in[1], 3 );
262 HH( d, a, b, c, in[9], 9 );
263 HH( c, d, a, b, in[5], 11 );
264 HH( b, c, d, a, in[13], 15 );
265 HH( a, b, c, d, in[3], 3 );
266 HH( d, a, b, c, in[11], 9 );
267 HH( c, d, a, b, in[7], 11 );
268 HH( b, c, d, a, in[15], 15 );
269
270 buf[0] += a;
271 buf[1] += b;
272 buf[2] += c;
273 buf[3] += d;
274}
275
276/******************************************************************************
277 * SystemFunction007 [ADVAPI32.@]
278 *
279 * MD4 hash a unicode string
280 *
281 * PARAMS
282 * string [I] the string to hash
283 * output [O] the md4 hash of the string (16 bytes)
284 *
285 * RETURNS
286 * Success: STATUS_SUCCESS
287 * Failure: STATUS_UNSUCCESSFUL
288 *
289 */
290NTSTATUS WINAPI SystemFunction007(const UNICODE_STRING *string, LPBYTE hash)
291{
292 MD4_CTX ctx;
293
294 MD4Init( &ctx );
295 MD4Update( &ctx, (const BYTE *)string->Buffer, string->Length );
296 MD4Final( &ctx );
297 memcpy( hash, ctx.digest, 0x10 );
298
299 return STATUS_SUCCESS;
300}
301
302/******************************************************************************
303 * SystemFunction010 [ADVAPI32.@]
304 * SystemFunction011 [ADVAPI32.@]
305 *
306 * MD4 hashes 16 bytes of data
307 *
308 * PARAMS
309 * unknown [] seems to have no effect on the output
310 * data [I] pointer to data to hash (16 bytes)
311 * output [O] the md4 hash of the data (16 bytes)
312 *
313 * RETURNS
314 * Success: STATUS_SUCCESS
315 * Failure: STATUS_UNSUCCESSFUL
316 *
317 */
318NTSTATUS WINAPI SystemFunction010(LPVOID unknown, const BYTE *data, LPBYTE hash)
319{
320 MD4_CTX ctx;
321
322 MD4Init( &ctx );
323 MD4Update( &ctx, data, 0x10 );
324 MD4Final( &ctx );
325 memcpy( hash, ctx.digest, 0x10 );
326
327 return STATUS_SUCCESS;
328}
Note: See TracBrowser for help on using the repository browser.