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