Line data Source code
1 : /* md5.c - MD5 Message-Digest Algorithm
2 : * Copyright (C) 1995,1996,1998,1999,2001,2002,
3 : * 2003 Free Software Foundation, Inc.
4 : *
5 : * This file is part of Libgcrypt.
6 : *
7 : * Libgcrypt is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU Lesser General Public License as
9 : * published by the Free Software Foundation; either version 2.1 of
10 : * the License, or (at your option) any later version.
11 : *
12 : * Libgcrypt is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU Lesser General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU Lesser General Public
18 : * License along with this program; if not, write to the Free Software
19 : * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 : *
21 : * According to the definition of MD5 in RFC 1321 from April 1992.
22 : * NOTE: This is *not* the same file as the one from glibc.
23 : * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
24 : * heavily modified for GnuPG by Werner Koch <wk@gnupg.org>
25 : */
26 :
27 : /* Test values:
28 : * "" D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E
29 : * "a" 0C C1 75 B9 C0 F1 B6 A8 31 C3 99 E2 69 77 26 61
30 : * "abc 90 01 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72
31 : * "message digest" F9 6B 69 7D 7C B7 93 8D 52 5A 2F 31 AA F1 61 D0
32 : */
33 :
34 : #include <config.h>
35 : #include <stdio.h>
36 : #include <stdlib.h>
37 : #include <string.h>
38 :
39 : #include "g10lib.h"
40 : #include "cipher.h"
41 :
42 : #include "bithelp.h"
43 : #include "bufhelp.h"
44 : #include "hash-common.h"
45 :
46 :
47 : typedef struct {
48 : gcry_md_block_ctx_t bctx;
49 : u32 A,B,C,D; /* chaining variables */
50 : } MD5_CONTEXT;
51 :
52 : static unsigned int
53 : transform ( void *ctx, const unsigned char *data, size_t datalen );
54 :
55 : static void
56 0 : md5_init( void *context, unsigned int flags)
57 : {
58 0 : MD5_CONTEXT *ctx = context;
59 :
60 : (void)flags;
61 :
62 0 : ctx->A = 0x67452301;
63 0 : ctx->B = 0xefcdab89;
64 0 : ctx->C = 0x98badcfe;
65 0 : ctx->D = 0x10325476;
66 :
67 0 : ctx->bctx.nblocks = 0;
68 0 : ctx->bctx.nblocks_high = 0;
69 0 : ctx->bctx.count = 0;
70 0 : ctx->bctx.blocksize = 64;
71 0 : ctx->bctx.bwrite = transform;
72 0 : }
73 :
74 :
75 : /* These are the four functions used in the four steps of the MD5 algorithm
76 : and defined in the RFC 1321. The first function is a little bit optimized
77 : (as found in Colin Plumbs public domain implementation). */
78 : /* #define FF(b, c, d) ((b & c) | (~b & d)) */
79 : #define FF(b, c, d) (d ^ (b & (c ^ d)))
80 : #define FG(b, c, d) FF (d, b, c)
81 : #define FH(b, c, d) (b ^ c ^ d)
82 : #define FI(b, c, d) (c ^ (b | ~d))
83 :
84 :
85 : /****************
86 : * transform 64 bytes
87 : */
88 : static unsigned int
89 0 : transform_blk ( void *c, const unsigned char *data )
90 : {
91 0 : MD5_CONTEXT *ctx = c;
92 : u32 correct_words[16];
93 0 : register u32 A = ctx->A;
94 0 : register u32 B = ctx->B;
95 0 : register u32 C = ctx->C;
96 0 : register u32 D = ctx->D;
97 0 : u32 *cwp = correct_words;
98 : int i;
99 :
100 0 : for ( i = 0; i < 16; i++ )
101 0 : correct_words[i] = buf_get_le32(data + i * 4);
102 :
103 : #define OP(a, b, c, d, s, T) \
104 : do \
105 : { \
106 : a += FF (b, c, d) + (*cwp++) + T; \
107 : a = rol(a, s); \
108 : a += b; \
109 : } \
110 : while (0)
111 :
112 : /* Before we start, one word about the strange constants.
113 : They are defined in RFC 1321 as
114 :
115 : T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
116 : */
117 :
118 : /* Round 1. */
119 0 : OP (A, B, C, D, 7, 0xd76aa478);
120 0 : OP (D, A, B, C, 12, 0xe8c7b756);
121 0 : OP (C, D, A, B, 17, 0x242070db);
122 0 : OP (B, C, D, A, 22, 0xc1bdceee);
123 0 : OP (A, B, C, D, 7, 0xf57c0faf);
124 0 : OP (D, A, B, C, 12, 0x4787c62a);
125 0 : OP (C, D, A, B, 17, 0xa8304613);
126 0 : OP (B, C, D, A, 22, 0xfd469501);
127 0 : OP (A, B, C, D, 7, 0x698098d8);
128 0 : OP (D, A, B, C, 12, 0x8b44f7af);
129 0 : OP (C, D, A, B, 17, 0xffff5bb1);
130 0 : OP (B, C, D, A, 22, 0x895cd7be);
131 0 : OP (A, B, C, D, 7, 0x6b901122);
132 0 : OP (D, A, B, C, 12, 0xfd987193);
133 0 : OP (C, D, A, B, 17, 0xa679438e);
134 0 : OP (B, C, D, A, 22, 0x49b40821);
135 :
136 : #undef OP
137 : #define OP(f, a, b, c, d, k, s, T) \
138 : do \
139 : { \
140 : a += f (b, c, d) + correct_words[k] + T; \
141 : a = rol(a, s); \
142 : a += b; \
143 : } \
144 : while (0)
145 :
146 : /* Round 2. */
147 0 : OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
148 0 : OP (FG, D, A, B, C, 6, 9, 0xc040b340);
149 0 : OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
150 0 : OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
151 0 : OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
152 0 : OP (FG, D, A, B, C, 10, 9, 0x02441453);
153 0 : OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
154 0 : OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
155 0 : OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
156 0 : OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
157 0 : OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
158 0 : OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
159 0 : OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
160 0 : OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
161 0 : OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
162 0 : OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
163 :
164 : /* Round 3. */
165 0 : OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
166 0 : OP (FH, D, A, B, C, 8, 11, 0x8771f681);
167 0 : OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
168 0 : OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
169 0 : OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
170 0 : OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
171 0 : OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
172 0 : OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
173 0 : OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
174 0 : OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
175 0 : OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
176 0 : OP (FH, B, C, D, A, 6, 23, 0x04881d05);
177 0 : OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
178 0 : OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
179 0 : OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
180 0 : OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
181 :
182 : /* Round 4. */
183 0 : OP (FI, A, B, C, D, 0, 6, 0xf4292244);
184 0 : OP (FI, D, A, B, C, 7, 10, 0x432aff97);
185 0 : OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
186 0 : OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
187 0 : OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
188 0 : OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
189 0 : OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
190 0 : OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
191 0 : OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
192 0 : OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
193 0 : OP (FI, C, D, A, B, 6, 15, 0xa3014314);
194 0 : OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
195 0 : OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
196 0 : OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
197 0 : OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
198 0 : OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
199 :
200 : /* Put checksum in context given as argument. */
201 0 : ctx->A += A;
202 0 : ctx->B += B;
203 0 : ctx->C += C;
204 0 : ctx->D += D;
205 :
206 0 : return /*burn_stack*/ 80+6*sizeof(void*);
207 : }
208 :
209 :
210 : static unsigned int
211 0 : transform ( void *c, const unsigned char *data, size_t nblks )
212 : {
213 : unsigned int burn;
214 :
215 : do
216 : {
217 0 : burn = transform_blk (c, data);
218 0 : data += 64;
219 : }
220 0 : while (--nblks);
221 :
222 0 : return burn;
223 : }
224 :
225 :
226 : /* The routine final terminates the message-digest computation and
227 : * ends with the desired message digest in mdContext->digest[0...15].
228 : * The handle is prepared for a new MD5 cycle.
229 : * Returns 16 bytes representing the digest.
230 : */
231 :
232 : static void
233 0 : md5_final( void *context)
234 : {
235 0 : MD5_CONTEXT *hd = context;
236 : u32 t, th, msb, lsb;
237 : byte *p;
238 : unsigned int burn;
239 :
240 0 : _gcry_md_block_write(hd, NULL, 0); /* flush */;
241 :
242 0 : t = hd->bctx.nblocks;
243 : if (sizeof t == sizeof hd->bctx.nblocks)
244 : th = hd->bctx.nblocks_high;
245 : else
246 0 : th = hd->bctx.nblocks >> 32;
247 :
248 : /* multiply by 64 to make a byte count */
249 0 : lsb = t << 6;
250 0 : msb = (th << 6) | (t >> 26);
251 : /* add the count */
252 0 : t = lsb;
253 0 : if( (lsb += hd->bctx.count) < t )
254 0 : msb++;
255 : /* multiply by 8 to make a bit count */
256 0 : t = lsb;
257 0 : lsb <<= 3;
258 0 : msb <<= 3;
259 0 : msb |= t >> 29;
260 :
261 0 : if( hd->bctx.count < 56 ) /* enough room */
262 : {
263 0 : hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
264 0 : while( hd->bctx.count < 56 )
265 0 : hd->bctx.buf[hd->bctx.count++] = 0; /* pad */
266 : }
267 : else /* need one extra block */
268 : {
269 0 : hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
270 0 : while( hd->bctx.count < 64 )
271 0 : hd->bctx.buf[hd->bctx.count++] = 0;
272 0 : _gcry_md_block_write(hd, NULL, 0); /* flush */;
273 0 : memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
274 : }
275 : /* append the 64 bit count */
276 0 : buf_put_le32(hd->bctx.buf + 56, lsb);
277 0 : buf_put_le32(hd->bctx.buf + 60, msb);
278 0 : burn = transform ( hd, hd->bctx.buf, 1 );
279 0 : _gcry_burn_stack (burn);
280 :
281 0 : p = hd->bctx.buf;
282 : #define X(a) do { buf_put_le32(p, hd->a); p += 4; } while(0)
283 0 : X(A);
284 0 : X(B);
285 0 : X(C);
286 0 : X(D);
287 : #undef X
288 :
289 0 : }
290 :
291 : static byte *
292 0 : md5_read( void *context )
293 : {
294 0 : MD5_CONTEXT *hd = (MD5_CONTEXT *) context;
295 0 : return hd->bctx.buf;
296 : }
297 :
298 : static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */
299 : { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
300 : 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
301 :
302 : static gcry_md_oid_spec_t oid_spec_md5[] =
303 : {
304 : /* iso.member-body.us.rsadsi.pkcs.pkcs-1.4 (md5WithRSAEncryption) */
305 : { "1.2.840.113549.1.1.4" },
306 : /* RSADSI digestAlgorithm MD5 */
307 : { "1.2.840.113549.2.5" },
308 : { NULL },
309 : };
310 :
311 : gcry_md_spec_t _gcry_digest_spec_md5 =
312 : {
313 : GCRY_MD_MD5, {0, 0},
314 : "MD5", asn, DIM (asn), oid_spec_md5, 16,
315 : md5_init, _gcry_md_block_write, md5_final, md5_read, NULL,
316 : sizeof (MD5_CONTEXT)
317 : };
|