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
61typedef struct {
62    u32 A,B,C,D;	  /* chaining variables */
63    u32  nblocks;
64    byte buf[64];
65    int  count;
66} MD4_CONTEXT;
67
68
69static void
70md4_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 */
91static void
92transform ( 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 */
193static void
194md4_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
239static void
240md4_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
303static byte *
304md4_read (void *context)
305{
306  MD4_CONTEXT *hd = context;
307  return hd->buf;
308}
309
310static 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
314static 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
321gcry_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