summaryrefslogtreecommitdiffabout
path: root/pwmanager/libcrypt/cipher/md4.c
Unidiff
Diffstat (limited to 'pwmanager/libcrypt/cipher/md4.c') (more/less context) (show whitespace changes)
-rw-r--r--pwmanager/libcrypt/cipher/md4.c327
1 files changed, 327 insertions, 0 deletions
diff --git a/pwmanager/libcrypt/cipher/md4.c b/pwmanager/libcrypt/cipher/md4.c
new file mode 100644
index 0000000..0d0a559
--- a/dev/null
+++ b/pwmanager/libcrypt/cipher/md4.c
@@ -0,0 +1,327 @@
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#include <assert.h>
55#include "g10lib.h"
56#include "memory.h"
57#include "cipher.h"
58
59#include "bithelp.h"
60
61
62typedef struct {
63 u32 A,B,C,D; /* chaining variables */
64 u32 nblocks;
65 byte buf[64];
66 int count;
67} MD4_CONTEXT;
68
69
70static void
71md4_init( void *context )
72{
73 MD4_CONTEXT *ctx = context;
74
75 ctx->A = 0x67452301;
76 ctx->B = 0xefcdab89;
77 ctx->C = 0x98badcfe;
78 ctx->D = 0x10325476;
79
80 ctx->nblocks = 0;
81 ctx->count = 0;
82}
83
84#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
85#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
86#define H(x, y, z) ((x) ^ (y) ^ (z))
87
88
89/****************
90 * transform 64 bytes
91 */
92static void
93transform( MD4_CONTEXT *ctx, byte *data )
94{
95 u32 in[16];
96 register u32 A = ctx->A;
97 register u32 B = ctx->B;
98 register u32 C = ctx->C;
99 register u32 D = ctx->D;
100
101#ifdef WORDS_BIGENDIAN
102 {
103 int i;
104 byte *p2, *p1;
105 for(i=0, p1=data, p2=(byte*)in; i < 16; i++, p2 += 4 )
106 {
107 p2[3] = *p1++;
108 p2[2] = *p1++;
109 p2[1] = *p1++;
110 p2[0] = *p1++;
111 }
112 }
113#else
114 memcpy (in, data, 64);
115#endif
116
117 /* Round 1. */
118#define function(a,b,c,d,k,s) a=rol(a+F(b,c,d)+in[k],s);
119 function(A,B,C,D, 0, 3);
120 function(D,A,B,C, 1, 7);
121 function(C,D,A,B, 2,11);
122 function(B,C,D,A, 3,19);
123 function(A,B,C,D, 4, 3);
124 function(D,A,B,C, 5, 7);
125 function(C,D,A,B, 6,11);
126 function(B,C,D,A, 7,19);
127 function(A,B,C,D, 8, 3);
128 function(D,A,B,C, 9, 7);
129 function(C,D,A,B,10,11);
130 function(B,C,D,A,11,19);
131 function(A,B,C,D,12, 3);
132 function(D,A,B,C,13, 7);
133 function(C,D,A,B,14,11);
134 function(B,C,D,A,15,19);
135
136#undef function
137
138 /* Round 2. */
139#define function(a,b,c,d,k,s) a=rol(a+G(b,c,d)+in[k]+0x5a827999,s);
140
141 function(A,B,C,D, 0, 3);
142 function(D,A,B,C, 4, 5);
143 function(C,D,A,B, 8, 9);
144 function(B,C,D,A,12,13);
145 function(A,B,C,D, 1, 3);
146 function(D,A,B,C, 5, 5);
147 function(C,D,A,B, 9, 9);
148 function(B,C,D,A,13,13);
149 function(A,B,C,D, 2, 3);
150 function(D,A,B,C, 6, 5);
151 function(C,D,A,B,10, 9);
152 function(B,C,D,A,14,13);
153 function(A,B,C,D, 3, 3);
154 function(D,A,B,C, 7, 5);
155 function(C,D,A,B,11, 9);
156 function(B,C,D,A,15,13);
157
158#undef function
159
160 /* Round 3. */
161#define function(a,b,c,d,k,s) a=rol(a+H(b,c,d)+in[k]+0x6ed9eba1,s);
162
163 function(A,B,C,D, 0, 3);
164 function(D,A,B,C, 8, 9);
165 function(C,D,A,B, 4,11);
166 function(B,C,D,A,12,15);
167 function(A,B,C,D, 2, 3);
168 function(D,A,B,C,10, 9);
169 function(C,D,A,B, 6,11);
170 function(B,C,D,A,14,15);
171 function(A,B,C,D, 1, 3);
172 function(D,A,B,C, 9, 9);
173 function(C,D,A,B, 5,11);
174 function(B,C,D,A,13,15);
175 function(A,B,C,D, 3, 3);
176 function(D,A,B,C,11, 9);
177 function(C,D,A,B, 7,11);
178 function(B,C,D,A,15,15);
179
180
181 /* Put checksum in context given as argument. */
182 ctx->A += A;
183 ctx->B += B;
184 ctx->C += C;
185 ctx->D += D;
186}
187
188
189
190/* The routine updates the message-digest context to
191 * account for the presence of each of the characters inBuf[0..inLen-1]
192 * in the message whose digest is being computed.
193 */
194static void
195md4_write( void *context, byte *inbuf, size_t inlen)
196{
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