2003-07-23 Moritz Schulte <moritz@g10code.com>
[libgcrypt.git] / cipher / md4.c
1 /* md4.c - MD4 Message-Digest Algorithm
2  * Copyright (C) 2002, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  *
20  * Based on md5.c in libgcrypt, but rewritten to compute md4 checksums
21  * using a public domain md4 implementation with the following comments:
22  *
23  * Modified by Wei Dai from Andrew M. Kuchling's md4.c
24  * The original code and all modifications are in the public domain.
25  *
26  * This is the original introductory comment:
27  *
28  *  md4.c : MD4 hash algorithm.
29  *
30  * Part of the Python Cryptography Toolkit, version 1.1
31  *
32  * Distribute and use freely; there are no restrictions on further
33  * dissemination and usage except those imposed by the laws of your
34  * country of residence.
35  *
36  */
37
38 /* MD4 test suite:
39  * MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0
40  * MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24
41  * MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d
42  * MD4 ("message digest") = d9130a8164549fe818874806e1c7014b
43  * MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9
44  * MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
45  * 043f8582f241db351ce627e153e7f0e4
46  * MD4 ("123456789012345678901234567890123456789012345678901234567890123456
47  * 78901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536
48  */
49
50 #include <config.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <assert.h>
55 #include "g10lib.h"
56 #include "memory.h"
57 #include "cipher.h"
58
59 #include "bithelp.h"
60
61
62 typedef struct {
63     u32 A,B,C,D;          /* chaining variables */
64     u32  nblocks;
65     byte buf[64];
66     int  count;
67 } MD4_CONTEXT;
68
69
70 static void
71 md4_init( void *context )
72 {
73   MD4_CONTEXT *ctx = (MD4_CONTEXT *) context;
74
75   ctx->A = 0x67452301;
76   ctx->B = 0xefcdab89;
77   ctx->C = 0x98badcfe;
78   ctx->D = 0x10325476;
79
80   ctx->nblocks = 0;
81   ctx->count = 0;
82 }
83
84 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
85 #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
86 #define H(x, y, z) ((x) ^ (y) ^ (z))
87
88
89 /****************
90  * transform 64 bytes
91  */
92 static void
93 transform( MD4_CONTEXT *ctx, byte *data )
94 {
95     u32 in[16];
96     register u32 A = ctx->A;
97     register u32 B = ctx->B;
98     register u32 C = ctx->C;
99     register u32 D = ctx->D;
100
101 #ifdef WORDS_BIGENDIAN
102     { int i;
103       byte *p2, *p1;
104       for(i=0, p1=data, p2=(byte*)in; i < 16; i++, p2 += 4 ) {
105         p2[3] = *p1++;
106         p2[2] = *p1++;
107         p2[1] = *p1++;
108         p2[0] = *p1++;
109       }
110     }
111 #else
112     memcpy (in, data, 64);
113 #endif
114
115     /* Round 1.  */
116 #define function(a,b,c,d,k,s) a=rol(a+F(b,c,d)+in[k],s);
117           function(A,B,C,D, 0, 3);
118           function(D,A,B,C, 1, 7);
119           function(C,D,A,B, 2,11);
120           function(B,C,D,A, 3,19);
121           function(A,B,C,D, 4, 3);
122           function(D,A,B,C, 5, 7);
123           function(C,D,A,B, 6,11);
124           function(B,C,D,A, 7,19);
125           function(A,B,C,D, 8, 3);
126           function(D,A,B,C, 9, 7);
127           function(C,D,A,B,10,11);
128           function(B,C,D,A,11,19);
129           function(A,B,C,D,12, 3);
130           function(D,A,B,C,13, 7);
131           function(C,D,A,B,14,11);
132           function(B,C,D,A,15,19);
133
134 #undef function
135
136     /* Round 2.  */
137 #define function(a,b,c,d,k,s) a=rol(a+G(b,c,d)+in[k]+0x5a827999,s);
138
139           function(A,B,C,D, 0, 3);
140           function(D,A,B,C, 4, 5);
141           function(C,D,A,B, 8, 9);
142           function(B,C,D,A,12,13);
143           function(A,B,C,D, 1, 3);
144           function(D,A,B,C, 5, 5);
145           function(C,D,A,B, 9, 9);
146           function(B,C,D,A,13,13);
147           function(A,B,C,D, 2, 3);
148           function(D,A,B,C, 6, 5);
149           function(C,D,A,B,10, 9);
150           function(B,C,D,A,14,13);
151           function(A,B,C,D, 3, 3);
152           function(D,A,B,C, 7, 5);
153           function(C,D,A,B,11, 9);
154           function(B,C,D,A,15,13);
155
156 #undef function
157
158     /* Round 3.  */
159 #define function(a,b,c,d,k,s) a=rol(a+H(b,c,d)+in[k]+0x6ed9eba1,s);
160
161           function(A,B,C,D, 0, 3);
162           function(D,A,B,C, 8, 9);
163           function(C,D,A,B, 4,11);
164           function(B,C,D,A,12,15);
165           function(A,B,C,D, 2, 3);
166           function(D,A,B,C,10, 9);
167           function(C,D,A,B, 6,11);
168           function(B,C,D,A,14,15);
169           function(A,B,C,D, 1, 3);
170           function(D,A,B,C, 9, 9);
171           function(C,D,A,B, 5,11);
172           function(B,C,D,A,13,15);
173           function(A,B,C,D, 3, 3);
174           function(D,A,B,C,11, 9);
175           function(C,D,A,B, 7,11);
176           function(B,C,D,A,15,15);
177
178
179     /* Put checksum in context given as argument.  */
180     ctx->A += A;
181     ctx->B += B;
182     ctx->C += C;
183     ctx->D += D;
184 }
185
186
187
188 /* The routine updates the message-digest context to
189  * account for the presence of each of the characters inBuf[0..inLen-1]
190  * in the message whose digest is being computed.
191  */
192 static void
193 md4_write( void *context, byte *inbuf, size_t inlen)
194 {
195   MD4_CONTEXT *hd = (MD4_CONTEXT *) context;
196     if( hd->count == 64 ) { /* flush the buffer */
197         transform( hd, hd->buf );
198         _gcry_burn_stack (80+6*sizeof(void*));
199         hd->count = 0;
200         hd->nblocks++;
201     }
202     if( !inbuf )
203         return;
204     if( hd->count ) {
205         for( ; inlen && hd->count < 64; inlen-- )
206             hd->buf[hd->count++] = *inbuf++;
207         md4_write( hd, NULL, 0 );
208         if( !inlen )
209             return;
210     }
211     _gcry_burn_stack (80+6*sizeof(void*));
212
213     while( inlen >= 64 ) {
214         transform( hd, inbuf );
215         hd->count = 0;
216         hd->nblocks++;
217         inlen -= 64;
218         inbuf += 64;
219     }
220     for( ; inlen && hd->count < 64; inlen-- )
221         hd->buf[hd->count++] = *inbuf++;
222
223 }
224
225
226
227 /* The routine final terminates the message-digest computation and
228  * ends with the desired message digest in mdContext->digest[0...15].
229  * The handle is prepared for a new MD4 cycle.
230  * Returns 16 bytes representing the digest.
231  */
232
233 static void
234 md4_final( void *context )
235 {
236   MD4_CONTEXT *hd = (MD4_CONTEXT *) context;
237     u32 t, msb, lsb;
238     byte *p;
239
240     md4_write(hd, NULL, 0); /* flush */;
241
242     t = hd->nblocks;
243     /* multiply by 64 to make a byte count */
244     lsb = t << 6;
245     msb = t >> 26;
246     /* add the count */
247     t = lsb;
248     if( (lsb += hd->count) < t )
249         msb++;
250     /* multiply by 8 to make a bit count */
251     t = lsb;
252     lsb <<= 3;
253     msb <<= 3;
254     msb |= t >> 29;
255
256     if( hd->count < 56 ) { /* enough room */
257         hd->buf[hd->count++] = 0x80; /* pad */
258         while( hd->count < 56 )
259             hd->buf[hd->count++] = 0;  /* pad */
260     }
261     else { /* need one extra block */
262         hd->buf[hd->count++] = 0x80; /* pad character */
263         while( hd->count < 64 )
264             hd->buf[hd->count++] = 0;
265         md4_write(hd, NULL, 0);  /* flush */;
266         memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
267     }
268     /* append the 64 bit count */
269     hd->buf[56] = lsb      ;
270     hd->buf[57] = lsb >>  8;
271     hd->buf[58] = lsb >> 16;
272     hd->buf[59] = lsb >> 24;
273     hd->buf[60] = msb      ;
274     hd->buf[61] = msb >>  8;
275     hd->buf[62] = msb >> 16;
276     hd->buf[63] = msb >> 24;
277     transform( hd, hd->buf );
278     _gcry_burn_stack (80+6*sizeof(void*));
279
280     p = hd->buf;
281 #ifdef WORDS_BIGENDIAN
282 #define X(a) do { *p++ = hd->a      ; *p++ = hd->a >> 8;      \
283                       *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0)
284 #else /* little endian */
285 #define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0)
286 #endif
287     X(A);
288     X(B);
289     X(C);
290     X(D);
291 #undef X
292
293 }
294
295 static byte *
296 md4_read (void *context)
297 {
298   MD4_CONTEXT *hd = (MD4_CONTEXT *) context;
299   return hd->buf;
300 }
301
302 static byte asn[18] = /* Object ID is 1.2.840.113549.2.4 */
303   { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
304     0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 };
305
306 static gcry_md_oid_spec_t oid_spec_md4[] =
307   {
308     /* iso.member-body.us.rsadsi.digestAlgorithm.md4 */
309     { "1.2.840.113549.2.4" },
310     { NULL },
311   };
312
313 gcry_md_spec_t digest_spec_md4 =
314   {
315     "MD4", asn, DIM (asn), oid_spec_md4,16,
316     md4_init, md4_write, md4_final, md4_read,
317     sizeof (MD4_CONTEXT)
318   };
319
320 /* end of file */