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