Portability fixes.
[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
55 #include "g10lib.h"
56 #include "cipher.h"
57
58 #include "bithelp.h"
59
60
61 typedef struct {
62     u32 A,B,C,D;          /* chaining variables */
63     u32  nblocks;
64     byte buf[64];
65     int  count;
66 } MD4_CONTEXT;
67
68
69 static void
70 md4_init( void *context )
71 {
72   MD4_CONTEXT *ctx = context;
73
74   ctx->A = 0x67452301;
75   ctx->B = 0xefcdab89;
76   ctx->C = 0x98badcfe;
77   ctx->D = 0x10325476;
78
79   ctx->nblocks = 0;
80   ctx->count = 0;
81 }
82
83 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
84 #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
85 #define H(x, y, z) ((x) ^ (y) ^ (z))
86
87
88 /****************
89  * transform 64 bytes
90  */
91 static void
92 transform ( MD4_CONTEXT *ctx, const unsigned char *data )
93 {
94   u32 in[16];
95   register u32 A = ctx->A;
96   register u32 B = ctx->B;
97   register u32 C = ctx->C;
98   register u32 D = ctx->D;
99
100 #ifdef WORDS_BIGENDIAN
101   {
102     int i;
103     byte *p2, *p1;
104     for(i=0, p1=data, p2=(byte*)in; i < 16; i++, p2 += 4 )
105       {
106         p2[3] = *p1++;
107         p2[2] = *p1++;
108         p2[1] = *p1++;
109         p2[0] = *p1++;
110       }
111   }
112 #else
113   memcpy (in, data, 64);
114 #endif
115
116   /* Round 1.  */
117 #define function(a,b,c,d,k,s) a=rol(a+F(b,c,d)+in[k],s);
118   function(A,B,C,D, 0, 3);
119   function(D,A,B,C, 1, 7);
120   function(C,D,A,B, 2,11);
121   function(B,C,D,A, 3,19);
122   function(A,B,C,D, 4, 3);
123   function(D,A,B,C, 5, 7);
124   function(C,D,A,B, 6,11);
125   function(B,C,D,A, 7,19);
126   function(A,B,C,D, 8, 3);
127   function(D,A,B,C, 9, 7);
128   function(C,D,A,B,10,11);
129   function(B,C,D,A,11,19);
130   function(A,B,C,D,12, 3);
131   function(D,A,B,C,13, 7);
132   function(C,D,A,B,14,11);
133   function(B,C,D,A,15,19);
134
135 #undef function
136
137   /* Round 2.  */
138 #define function(a,b,c,d,k,s) a=rol(a+G(b,c,d)+in[k]+0x5a827999,s);
139
140   function(A,B,C,D, 0, 3);
141   function(D,A,B,C, 4, 5);
142   function(C,D,A,B, 8, 9);
143   function(B,C,D,A,12,13);
144   function(A,B,C,D, 1, 3);
145   function(D,A,B,C, 5, 5);
146   function(C,D,A,B, 9, 9);
147   function(B,C,D,A,13,13);
148   function(A,B,C,D, 2, 3);
149   function(D,A,B,C, 6, 5);
150   function(C,D,A,B,10, 9);
151   function(B,C,D,A,14,13);
152   function(A,B,C,D, 3, 3);
153   function(D,A,B,C, 7, 5);
154   function(C,D,A,B,11, 9);
155   function(B,C,D,A,15,13);
156
157 #undef function
158
159   /* Round 3.  */
160 #define function(a,b,c,d,k,s) a=rol(a+H(b,c,d)+in[k]+0x6ed9eba1,s);
161
162   function(A,B,C,D, 0, 3);
163   function(D,A,B,C, 8, 9);
164   function(C,D,A,B, 4,11);
165   function(B,C,D,A,12,15);
166   function(A,B,C,D, 2, 3);
167   function(D,A,B,C,10, 9);
168   function(C,D,A,B, 6,11);
169   function(B,C,D,A,14,15);
170   function(A,B,C,D, 1, 3);
171   function(D,A,B,C, 9, 9);
172   function(C,D,A,B, 5,11);
173   function(B,C,D,A,13,15);
174   function(A,B,C,D, 3, 3);
175   function(D,A,B,C,11, 9);
176   function(C,D,A,B, 7,11);
177   function(B,C,D,A,15,15);
178
179
180   /* Put checksum in context given as argument.  */
181   ctx->A += A;
182   ctx->B += B;
183   ctx->C += C;
184   ctx->D += D;
185 }
186
187
188
189 /* The routine updates the message-digest context to
190  * account for the presence of each of the characters inBuf[0..inLen-1]
191  * in the message whose digest is being computed.
192  */
193 static void
194 md4_write ( void *context, const void *inbuf_arg, size_t inlen)
195 {
196   const unsigned char *inbuf = inbuf_arg;
197   MD4_CONTEXT *hd = context;
198
199   if( hd->count == 64 ) /* flush the buffer */
200     { 
201       transform( hd, hd->buf );
202       _gcry_burn_stack (80+6*sizeof(void*));
203       hd->count = 0;
204       hd->nblocks++;
205     }
206   if( !inbuf )
207     return;
208
209   if( hd->count )
210     {
211       for( ; inlen && hd->count < 64; inlen-- )
212         hd->buf[hd->count++] = *inbuf++;
213       md4_write( hd, NULL, 0 );
214       if( !inlen )
215         return;
216     }
217   _gcry_burn_stack (80+6*sizeof(void*));
218
219   while( inlen >= 64 )
220     {
221       transform( hd, inbuf );
222       hd->count = 0;
223       hd->nblocks++;
224       inlen -= 64;
225       inbuf += 64;
226     }
227   for( ; inlen && hd->count < 64; inlen-- )
228     hd->buf[hd->count++] = *inbuf++;
229 }
230
231
232
233 /* The routine final terminates the message-digest computation and
234  * ends with the desired message digest in mdContext->digest[0...15].
235  * The handle is prepared for a new MD4 cycle.
236  * Returns 16 bytes representing the digest.
237  */
238
239 static void
240 md4_final( void *context )
241 {
242   MD4_CONTEXT *hd = context;
243   u32 t, msb, lsb;
244   byte *p;
245
246   md4_write(hd, NULL, 0); /* flush */;
247
248   t = hd->nblocks;
249   /* multiply by 64 to make a byte count */
250   lsb = t << 6;
251   msb = t >> 26;
252   /* add the count */
253   t = lsb;
254   if( (lsb += hd->count) < t )
255     msb++;
256   /* multiply by 8 to make a bit count */
257   t = lsb;
258   lsb <<= 3;
259   msb <<= 3;
260   msb |= t >> 29;
261   
262   if( hd->count < 56 )  /* enough room */
263     {
264       hd->buf[hd->count++] = 0x80; /* pad */
265       while( hd->count < 56 )
266         hd->buf[hd->count++] = 0;  /* pad */
267     }
268   else /* need one extra block */ 
269     { 
270       hd->buf[hd->count++] = 0x80; /* pad character */
271       while( hd->count < 64 )
272         hd->buf[hd->count++] = 0;
273       md4_write(hd, NULL, 0);  /* flush */;
274       memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
275     }
276   /* append the 64 bit count */
277   hd->buf[56] = lsb        ;
278   hd->buf[57] = lsb >>  8;
279   hd->buf[58] = lsb >> 16;
280   hd->buf[59] = lsb >> 24;
281   hd->buf[60] = msb        ;
282   hd->buf[61] = msb >>  8;
283   hd->buf[62] = msb >> 16;
284   hd->buf[63] = msb >> 24;
285   transform( hd, hd->buf );
286   _gcry_burn_stack (80+6*sizeof(void*));
287
288   p = hd->buf;
289 #ifdef WORDS_BIGENDIAN
290 #define X(a) do { *p++ = hd->a      ; *p++ = hd->a >> 8;      \
291                   *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0)
292 #else /* little endian */
293 #define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0)
294 #endif
295   X(A);
296   X(B);
297   X(C);
298   X(D);
299 #undef X
300
301 }
302
303 static byte *
304 md4_read (void *context)
305 {
306   MD4_CONTEXT *hd = context;
307   return hd->buf;
308 }
309
310 static byte asn[18] = /* Object ID is 1.2.840.113549.2.4 */
311   { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
312     0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 };
313
314 static gcry_md_oid_spec_t oid_spec_md4[] =
315   {
316     /* iso.member-body.us.rsadsi.digestAlgorithm.md4 */
317     { "1.2.840.113549.2.4" },
318     { NULL },
319   };
320
321 gcry_md_spec_t _gcry_digest_spec_md4 =
322   {
323     "MD4", asn, DIM (asn), oid_spec_md4,16,
324     md4_init, md4_write, md4_final, md4_read,
325     sizeof (MD4_CONTEXT)
326   };
327