GCM: Add support for split data buffers and online operation
[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 );
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 ( 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
185 /* The routine final terminates the message-digest computation and
186  * ends with the desired message digest in mdContext->digest[0...15].
187  * The handle is prepared for a new MD4 cycle.
188  * Returns 16 bytes representing the digest.
189  */
190
191 static void
192 md4_final( void *context )
193 {
194   MD4_CONTEXT *hd = context;
195   u32 t, th, msb, lsb;
196   byte *p;
197   unsigned int burn;
198
199   _gcry_md_block_write(hd, NULL, 0); /* flush */;
200
201   t = hd->bctx.nblocks;
202   if (sizeof t == sizeof hd->bctx.nblocks)
203     th = hd->bctx.nblocks_high;
204   else
205     th = hd->bctx.nblocks >> 32;
206
207   /* multiply by 64 to make a byte count */
208   lsb = t << 6;
209   msb = (th << 6) | (t >> 26);
210   /* add the count */
211   t = lsb;
212   if( (lsb += hd->bctx.count) < t )
213     msb++;
214   /* multiply by 8 to make a bit count */
215   t = lsb;
216   lsb <<= 3;
217   msb <<= 3;
218   msb |= t >> 29;
219
220   if( hd->bctx.count < 56 )  /* enough room */
221     {
222       hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
223       while( hd->bctx.count < 56 )
224         hd->bctx.buf[hd->bctx.count++] = 0;  /* pad */
225     }
226   else /* need one extra block */
227     {
228       hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
229       while( hd->bctx.count < 64 )
230         hd->bctx.buf[hd->bctx.count++] = 0;
231       _gcry_md_block_write(hd, NULL, 0);  /* flush */;
232       memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
233     }
234   /* append the 64 bit count */
235   buf_put_le32(hd->bctx.buf + 56, lsb);
236   buf_put_le32(hd->bctx.buf + 60, msb);
237   burn = transform( hd, hd->bctx.buf );
238   _gcry_burn_stack (burn);
239
240   p = hd->bctx.buf;
241 #define X(a) do { *(u32*)p = le_bswap32((*hd).a) ; p += 4; } while(0)
242   X(A);
243   X(B);
244   X(C);
245   X(D);
246 #undef X
247
248 }
249
250 static byte *
251 md4_read (void *context)
252 {
253   MD4_CONTEXT *hd = context;
254   return hd->bctx.buf;
255 }
256
257 static byte asn[18] = /* Object ID is 1.2.840.113549.2.4 */
258   { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
259     0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 };
260
261 static gcry_md_oid_spec_t oid_spec_md4[] =
262   {
263     /* iso.member-body.us.rsadsi.digestAlgorithm.md4 */
264     { "1.2.840.113549.2.4" },
265     { NULL },
266   };
267
268 gcry_md_spec_t _gcry_digest_spec_md4 =
269   {
270     GCRY_MD_MD4, {0, 0},
271     "MD4", asn, DIM (asn), oid_spec_md4,16,
272     md4_init, _gcry_md_block_write, md4_final, md4_read,
273     sizeof (MD4_CONTEXT)
274   };