/src/libgcrypt/cipher/md4.c
Line | Count | Source (jump to first uncovered line) |
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, unsigned int flags) |
73 | 0 | { |
74 | 0 | MD4_CONTEXT *ctx = context; |
75 | |
|
76 | 0 | (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_shift = _gcry_ctz(64); |
87 | 0 | ctx->bctx.bwrite = transform; |
88 | 0 | } |
89 | | |
90 | 0 | #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) |
91 | 0 | #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) |
92 | 0 | #define H(x, y, z) ((x) ^ (y) ^ (z)) |
93 | | |
94 | | |
95 | | /**************** |
96 | | * transform 64 bytes |
97 | | */ |
98 | | static unsigned int |
99 | | transform_blk ( void *c, const unsigned char *data ) |
100 | 0 | { |
101 | 0 | MD4_CONTEXT *ctx = c; |
102 | 0 | 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 | 0 | 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 | 0 | #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 | 0 | #undef function |
132 | | |
133 | | /* Round 2. */ |
134 | 0 | #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 | 0 | #undef function |
154 | | |
155 | | /* Round 3. */ |
156 | 0 | #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 | 0 | } |
184 | | |
185 | | |
186 | | static unsigned int |
187 | | transform ( void *c, const unsigned char *data, size_t nblks ) |
188 | 0 | { |
189 | 0 | unsigned int burn; |
190 | |
|
191 | 0 | do |
192 | 0 | { |
193 | 0 | burn = transform_blk (c, data); |
194 | 0 | data += 64; |
195 | 0 | } |
196 | 0 | while (--nblks); |
197 | |
|
198 | 0 | return burn; |
199 | 0 | } |
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 | | md4_final( void *context ) |
210 | 0 | { |
211 | 0 | MD4_CONTEXT *hd = context; |
212 | 0 | u32 t, th, msb, lsb; |
213 | 0 | byte *p; |
214 | 0 | unsigned int burn; |
215 | |
|
216 | 0 | t = hd->bctx.nblocks; |
217 | 0 | if (sizeof t == sizeof hd->bctx.nblocks) |
218 | 0 | th = hd->bctx.nblocks_high; |
219 | 0 | else |
220 | 0 | th = hd->bctx.nblocks >> 32; |
221 | | |
222 | | /* multiply by 64 to make a byte count */ |
223 | 0 | lsb = t << 6; |
224 | 0 | msb = (th << 6) | (t >> 26); |
225 | | /* add the count */ |
226 | 0 | t = lsb; |
227 | 0 | if( (lsb += hd->bctx.count) < t ) |
228 | 0 | msb++; |
229 | | /* multiply by 8 to make a bit count */ |
230 | 0 | t = lsb; |
231 | 0 | lsb <<= 3; |
232 | 0 | msb <<= 3; |
233 | 0 | msb |= t >> 29; |
234 | |
|
235 | 0 | if (hd->bctx.count < 56) /* enough room */ |
236 | 0 | { |
237 | 0 | hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ |
238 | 0 | if (hd->bctx.count < 56) |
239 | 0 | memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count); |
240 | | |
241 | | /* append the 64 bit count */ |
242 | 0 | buf_put_le32(hd->bctx.buf + 56, lsb); |
243 | 0 | buf_put_le32(hd->bctx.buf + 60, msb); |
244 | 0 | burn = transform (hd, hd->bctx.buf, 1); |
245 | 0 | } |
246 | 0 | else /* need one extra block */ |
247 | 0 | { |
248 | 0 | hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ |
249 | | /* fill pad and next block with zeroes */ |
250 | 0 | memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56); |
251 | | |
252 | | /* append the 64 bit count */ |
253 | 0 | buf_put_le32(hd->bctx.buf + 64 + 56, lsb); |
254 | 0 | buf_put_le32(hd->bctx.buf + 64 + 60, msb); |
255 | 0 | burn = transform (hd, hd->bctx.buf, 2); |
256 | 0 | } |
257 | |
|
258 | 0 | p = hd->bctx.buf; |
259 | 0 | #define X(a) do { buf_put_le32(p, hd->a); p += 4; } while(0) |
260 | 0 | X(A); |
261 | 0 | X(B); |
262 | 0 | X(C); |
263 | 0 | X(D); |
264 | 0 | #undef X |
265 | |
|
266 | 0 | hd->bctx.count = 0; |
267 | |
|
268 | 0 | _gcry_burn_stack (burn); |
269 | 0 | } |
270 | | |
271 | | static byte * |
272 | | md4_read (void *context) |
273 | 0 | { |
274 | 0 | MD4_CONTEXT *hd = context; |
275 | 0 | return hd->bctx.buf; |
276 | 0 | } |
277 | | |
278 | | static const byte asn[18] = /* Object ID is 1.2.840.113549.2.4 */ |
279 | | { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, |
280 | | 0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 }; |
281 | | |
282 | | static const gcry_md_oid_spec_t oid_spec_md4[] = |
283 | | { |
284 | | /* iso.member-body.us.rsadsi.digestAlgorithm.md4 */ |
285 | | { "1.2.840.113549.2.4" }, |
286 | | { NULL }, |
287 | | }; |
288 | | |
289 | | const gcry_md_spec_t _gcry_digest_spec_md4 = |
290 | | { |
291 | | GCRY_MD_MD4, {0, 0}, |
292 | | "MD4", asn, DIM (asn), oid_spec_md4,16, |
293 | | md4_init, _gcry_md_block_write, md4_final, md4_read, NULL, |
294 | | NULL, |
295 | | sizeof (MD4_CONTEXT) |
296 | | }; |