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