git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@820 77e5149b-7576-45b1-b177-96237e5ba77b
Tomasz Kojm authored on 2004/09/01 23:14:21... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Wed Sep 1 16:11:40 CEST 2004 (tk) |
|
2 |
+---------------------------------- |
|
3 |
+ * libclamav: replace current MD5 implementation with another one |
|
4 |
+ |
|
1 | 5 |
Wed Sep 1 03:32:28 CEST 2004 (tk) |
2 | 6 |
---------------------------------- |
3 | 7 |
* libclamav/cvd.c: display warning if loaded database is older than 7 days |
... | ... |
@@ -288,7 +288,7 @@ int cli_cvdverify(FILE *fd, struct cl_cvd *cvdpt) |
288 | 288 |
if(cvdpt) |
289 | 289 |
memcpy(cvdpt, cvd, sizeof(struct cl_cvd)); |
290 | 290 |
|
291 |
- md5 = cli_md5stream(fd); |
|
291 |
+ md5 = cli_md5stream(fd, NULL); |
|
292 | 292 |
cli_dbgmsg("MD5(.tar.gz) = %s\n", md5); |
293 | 293 |
|
294 | 294 |
if(strncmp(md5, cvd->md5, 32)) { |
... | ... |
@@ -80,8 +80,8 @@ int cli_scandesc(int desc, const char **virname, long int *scanned, const struct |
80 | 80 |
char *buffer, *buff, *endbl, *pt; |
81 | 81 |
int bytes, buffsize, length, ret, *partcnt, type = CL_CLEAN; |
82 | 82 |
unsigned long int *partoff, offset = 0; |
83 |
- struct md5_ctx ctx; |
|
84 |
- unsigned char md5buff[16]; |
|
83 |
+ struct MD5Context ctx; |
|
84 |
+ unsigned char digest[16]; |
|
85 | 85 |
struct cli_md5_node *md5_node; |
86 | 86 |
|
87 | 87 |
|
... | ... |
@@ -111,7 +111,7 @@ int cli_scandesc(int desc, const char **virname, long int *scanned, const struct |
111 | 111 |
} |
112 | 112 |
|
113 | 113 |
if(root->md5_hlist) |
114 |
- md5_init_ctx (&ctx); |
|
114 |
+ MD5Init(&ctx); |
|
115 | 115 |
|
116 | 116 |
buff = buffer; |
117 | 117 |
buff += root->maxpatlen; /* pointer to read data block */ |
... | ... |
@@ -119,7 +119,7 @@ int cli_scandesc(int desc, const char **virname, long int *scanned, const struct |
119 | 119 |
* length of root->maxpatlen |
120 | 120 |
*/ |
121 | 121 |
|
122 |
- pt= buff; |
|
122 |
+ pt = buff; |
|
123 | 123 |
length = SCANBUFF; |
124 | 124 |
while((bytes = read(desc, buff, SCANBUFF)) > 0) { |
125 | 125 |
|
... | ... |
@@ -149,25 +149,8 @@ int cli_scandesc(int desc, const char **virname, long int *scanned, const struct |
149 | 149 |
pt = buffer; |
150 | 150 |
length = buffsize; |
151 | 151 |
|
152 |
- /* compute MD5 */ |
|
153 |
- |
|
154 |
- if(root->md5_hlist) { |
|
155 |
- if(bytes % 64 == 0) { |
|
156 |
- md5_process_block(buff, bytes, &ctx); |
|
157 |
- } else { |
|
158 |
- int block = bytes; |
|
159 |
- char *mpt = buff; |
|
160 |
- |
|
161 |
- while(block >= MD5_BLOCKSIZE) { |
|
162 |
- md5_process_block(mpt, MD5_BLOCKSIZE, &ctx); |
|
163 |
- mpt += MD5_BLOCKSIZE; |
|
164 |
- block -= MD5_BLOCKSIZE; |
|
165 |
- } |
|
166 |
- |
|
167 |
- if(block) |
|
168 |
- md5_process_bytes(mpt, block, &ctx); |
|
169 |
- } |
|
170 |
- } |
|
152 |
+ if(root->md5_hlist) |
|
153 |
+ MD5Update(&ctx, buff, bytes); |
|
171 | 154 |
} |
172 | 155 |
|
173 | 156 |
free(buffer); |
... | ... |
@@ -175,9 +158,9 @@ int cli_scandesc(int desc, const char **virname, long int *scanned, const struct |
175 | 175 |
free(partoff); |
176 | 176 |
|
177 | 177 |
if(root->md5_hlist) { |
178 |
- md5_finish_ctx(&ctx, &md5buff); |
|
178 |
+ MD5Final(digest, &ctx); |
|
179 | 179 |
|
180 |
- if((md5_node = cli_vermd5(md5buff, root))) { |
|
180 |
+ if((md5_node = cli_vermd5(digest, root))) { |
|
181 | 181 |
struct stat sb; |
182 | 182 |
|
183 | 183 |
if(fstat(desc, &sb)) |
... | ... |
@@ -1,434 +1,236 @@ |
1 |
-/* Functions to compute MD5 message digest of files or memory blocks. |
|
2 |
- according to the definition of MD5 in RFC 1321 from April 1992. |
|
3 |
- Copyright (C) 1995, 1996, 1997, 1999, 2000 Free Software Foundation, Inc. |
|
4 |
- This file is part of the GNU C Library. |
|
5 |
- |
|
6 |
- The GNU C Library is free software; you can redistribute it and/or |
|
7 |
- modify it under the terms of the GNU Library General Public License as |
|
8 |
- published by the Free Software Foundation; either version 2 of the |
|
9 |
- License, or (at your option) any later version. |
|
10 |
- |
|
11 |
- The GNU C Library 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 GNU |
|
14 |
- Library General Public License for more details. |
|
15 |
- |
|
16 |
- You should have received a copy of the GNU Library General Public |
|
17 |
- License along with the GNU C Library; see the file COPYING.LIB. If not, |
|
18 |
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
19 |
- Boston, MA 02111-1307, USA. */ |
|
20 |
- |
|
21 |
-/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */ |
|
22 |
- |
|
23 |
-#ifdef HAVE_CONFIG_H |
|
24 |
-# include <clamav-config.h> |
|
1 |
+/* |
|
2 |
+ * This code implements the MD5 message-digest algorithm. |
|
3 |
+ * The algorithm is due to Ron Rivest. This code was |
|
4 |
+ * written by Colin Plumb in 1993, no copyright is claimed. |
|
5 |
+ * This code is in the public domain; do with it what you wish. |
|
6 |
+ * |
|
7 |
+ * Equivalent code is available from RSA Data Security, Inc. |
|
8 |
+ * This code has been tested against that, and is equivalent, |
|
9 |
+ * except that you don't need to include two pages of legalese |
|
10 |
+ * with every copy. |
|
11 |
+ * |
|
12 |
+ * To compute the message digest of a chunk of bytes, declare an |
|
13 |
+ * MD5Context structure, pass it to MD5Init, call MD5Update as |
|
14 |
+ * needed on buffers full of bytes, and then call MD5Final, which |
|
15 |
+ * will fill a supplied 16-byte array with the digest. |
|
16 |
+ * |
|
17 |
+ */ |
|
18 |
+ |
|
19 |
+#if HAVE_CONFIG_H |
|
20 |
+#include "clamav-config.h" |
|
25 | 21 |
#endif |
26 | 22 |
|
27 |
-#include <sys/types.h> |
|
28 |
- |
|
29 |
-#if STDC_HEADERS || defined _LIBC |
|
30 |
-# include <stdlib.h> |
|
31 |
-# include <string.h> |
|
32 |
-#else |
|
33 |
-# ifndef HAVE_MEMCPY |
|
34 |
-# define memcpy(d, s, n) bcopy ((s), (d), (n)) |
|
35 |
-# endif |
|
36 |
-#endif |
|
23 |
+#include <string.h> /* for memcpy() */ |
|
24 |
+#include <sys/types.h> /* for stupid systems */ |
|
25 |
+#include <netinet/in.h> /* for ntohl() */ |
|
37 | 26 |
|
38 | 27 |
#include "md5.h" |
39 | 28 |
|
40 |
-/* Not needed, since endianess is already taken care of by configure |
|
41 |
-#ifdef _LIBC |
|
42 |
-# include <endian.h> |
|
43 |
-# if __BYTE_ORDER == __BIG_ENDIAN |
|
44 |
-# define WORDS_BIGENDIAN 1 |
|
45 |
-# endif |
|
46 |
-#endif |
|
47 |
-*/ |
|
48 |
- |
|
49 | 29 |
#if WORDS_BIGENDIAN |
50 |
-# define SWAP(n) \ |
|
51 |
- (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) |
|
52 |
-#else |
|
53 |
-# define SWAP(n) (n) |
|
54 |
-#endif |
|
55 |
- |
|
56 |
- |
|
57 |
-/* This array contains the bytes used to pad the buffer to the next |
|
58 |
- 64-byte boundary. (RFC 1321, 3.1: Step 1) */ |
|
59 |
-static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; |
|
60 |
- |
|
61 |
- |
|
62 |
-/* Initialize structure containing state of computation. |
|
63 |
- (RFC 1321, 3.3: Step 3) */ |
|
64 | 30 |
void |
65 |
-md5_init_ctx (ctx) |
|
66 |
- struct md5_ctx *ctx; |
|
67 |
-{ |
|
68 |
- ctx->A = 0x67452301; |
|
69 |
- ctx->B = 0xefcdab89; |
|
70 |
- ctx->C = 0x98badcfe; |
|
71 |
- ctx->D = 0x10325476; |
|
72 |
- |
|
73 |
- ctx->total[0] = ctx->total[1] = 0; |
|
74 |
- ctx->buflen = 0; |
|
75 |
-} |
|
76 |
- |
|
77 |
-/* Put result from CTX in first 16 bytes following RESBUF. The result |
|
78 |
- must be in little endian byte order. |
|
79 |
- |
|
80 |
- IMPORTANT: On some systems it is required that RESBUF is correctly |
|
81 |
- aligned for a 32 bits value. */ |
|
82 |
-void * |
|
83 |
-md5_read_ctx (ctx, resbuf) |
|
84 |
- const struct md5_ctx *ctx; |
|
85 |
- void *resbuf; |
|
31 |
+byteSwap(uint32_t *buf, unsigned words) |
|
86 | 32 |
{ |
87 |
- ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); |
|
88 |
- ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); |
|
89 |
- ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); |
|
90 |
- ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); |
|
33 |
+ md5byte *p = (md5byte *)buf; |
|
91 | 34 |
|
92 |
- return resbuf; |
|
35 |
+ do { |
|
36 |
+ *buf++ = (uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 | |
|
37 |
+ ((unsigned)p[1] << 8 | p[0]); |
|
38 |
+ p += 4; |
|
39 |
+ } while (--words); |
|
93 | 40 |
} |
41 |
+#else |
|
42 |
+#define byteSwap(buf,words) |
|
43 |
+#endif |
|
94 | 44 |
|
95 |
-/* Process the remaining bytes in the internal buffer and the usual |
|
96 |
- prolog according to the standard and write the result to RESBUF. |
|
97 |
- |
|
98 |
- IMPORTANT: On some systems it is required that RESBUF is correctly |
|
99 |
- aligned for a 32 bits value. */ |
|
100 |
-void * |
|
101 |
-md5_finish_ctx (ctx, resbuf) |
|
102 |
- struct md5_ctx *ctx; |
|
103 |
- void *resbuf; |
|
45 |
+/* |
|
46 |
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious |
|
47 |
+ * initialization constants. |
|
48 |
+ */ |
|
49 |
+void |
|
50 |
+MD5Init(struct MD5Context *ctx) |
|
104 | 51 |
{ |
105 |
- /* Take yet unprocessed bytes into account. */ |
|
106 |
- md5_uint32 bytes = ctx->buflen; |
|
107 |
- size_t pad; |
|
108 |
- |
|
109 |
- /* Now count remaining bytes. */ |
|
110 |
- ctx->total[0] += bytes; |
|
111 |
- if (ctx->total[0] < bytes) |
|
112 |
- ++ctx->total[1]; |
|
113 |
- |
|
114 |
- pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; |
|
115 |
- memcpy (&ctx->buffer[bytes], fillbuf, pad); |
|
52 |
+ ctx->buf[0] = 0x67452301; |
|
53 |
+ ctx->buf[1] = 0xefcdab89; |
|
54 |
+ ctx->buf[2] = 0x98badcfe; |
|
55 |
+ ctx->buf[3] = 0x10325476; |
|
116 | 56 |
|
117 |
- /* Put the 64-bit file length in *bits* at the end of the buffer. */ |
|
118 |
- *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); |
|
119 |
- *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | |
|
120 |
- (ctx->total[0] >> 29)); |
|
121 |
- |
|
122 |
- /* Process last bytes. */ |
|
123 |
- md5_process_block (ctx->buffer, bytes + pad + 8, ctx); |
|
124 |
- |
|
125 |
- return md5_read_ctx (ctx, resbuf); |
|
57 |
+ ctx->bytes[0] = 0; |
|
58 |
+ ctx->bytes[1] = 0; |
|
126 | 59 |
} |
127 | 60 |
|
128 |
-/* Compute MD5 message digest for bytes read from STREAM. The |
|
129 |
- resulting message digest number will be written into the 16 bytes |
|
130 |
- beginning at RESBLOCK. */ |
|
131 |
-int |
|
132 |
-md5_stream (stream, resblock) |
|
133 |
- FILE *stream; |
|
134 |
- void *resblock; |
|
61 |
+/* |
|
62 |
+ * Update context to reflect the concatenation of another buffer full |
|
63 |
+ * of bytes. |
|
64 |
+ */ |
|
65 |
+void |
|
66 |
+MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) |
|
135 | 67 |
{ |
136 |
- /* Important: BLOCKSIZE must be a multiple of 64. */ |
|
137 |
-#define BLOCKSIZE 4096 |
|
138 |
- struct md5_ctx ctx; |
|
139 |
- char buffer[BLOCKSIZE + 72]; |
|
140 |
- size_t sum; |
|
68 |
+ uint32_t t; |
|
141 | 69 |
|
142 |
- /* Initialize the computation context. */ |
|
143 |
- md5_init_ctx (&ctx); |
|
70 |
+ /* Update byte count */ |
|
144 | 71 |
|
145 |
- /* Iterate over full file contents. */ |
|
146 |
- while (1) |
|
147 |
- { |
|
148 |
- /* We read the file in blocks of BLOCKSIZE bytes. One call of the |
|
149 |
- computation function processes the whole buffer so that with the |
|
150 |
- next round of the loop another block can be read. */ |
|
151 |
- size_t n; |
|
152 |
- sum = 0; |
|
72 |
+ t = ctx->bytes[0]; |
|
73 |
+ if ((ctx->bytes[0] = t + len) < t) |
|
74 |
+ ctx->bytes[1]++; /* Carry from low to high */ |
|
153 | 75 |
|
154 |
- /* Read block. Take care for partial reads. */ |
|
155 |
- do |
|
156 |
- { |
|
157 |
- n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); |
|
158 |
- |
|
159 |
- sum += n; |
|
76 |
+ t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */ |
|
77 |
+ if (t > len) { |
|
78 |
+ memcpy((md5byte *)ctx->in + 64 - t, buf, len); |
|
79 |
+ return; |
|
80 |
+ } |
|
81 |
+ /* First chunk is an odd size */ |
|
82 |
+ memcpy((md5byte *)ctx->in + 64 - t, buf, t); |
|
83 |
+ byteSwap(ctx->in, 16); |
|
84 |
+ MD5Transform(ctx->buf, ctx->in); |
|
85 |
+ buf += t; |
|
86 |
+ len -= t; |
|
87 |
+ |
|
88 |
+ /* Process data in 64-byte chunks */ |
|
89 |
+ while (len >= 64) { |
|
90 |
+ memcpy(ctx->in, buf, 64); |
|
91 |
+ byteSwap(ctx->in, 16); |
|
92 |
+ MD5Transform(ctx->buf, ctx->in); |
|
93 |
+ buf += 64; |
|
94 |
+ len -= 64; |
|
160 | 95 |
} |
161 |
- while (sum < BLOCKSIZE && n != 0); |
|
162 |
- if (n == 0 && ferror (stream)) |
|
163 |
- return 1; |
|
164 |
- |
|
165 |
- /* If end of file is reached, end the loop. */ |
|
166 |
- if (n == 0) |
|
167 |
- break; |
|
168 |
- |
|
169 |
- /* Process buffer with BLOCKSIZE bytes. Note that |
|
170 |
- BLOCKSIZE % 64 == 0 |
|
171 |
- */ |
|
172 |
- md5_process_block (buffer, BLOCKSIZE, &ctx); |
|
173 |
- } |
|
174 |
- |
|
175 |
- /* Add the last bytes if necessary. */ |
|
176 |
- if (sum > 0) |
|
177 |
- md5_process_bytes (buffer, sum, &ctx); |
|
178 |
- |
|
179 |
- /* Construct result in desired memory. */ |
|
180 |
- md5_finish_ctx (&ctx, resblock); |
|
181 |
- return 0; |
|
182 |
-} |
|
183 |
- |
|
184 |
-/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The |
|
185 |
- result is always in little endian byte order, so that a byte-wise |
|
186 |
- output yields to the wanted ASCII representation of the message |
|
187 |
- digest. */ |
|
188 |
-void * |
|
189 |
-md5_buffer (buffer, len, resblock) |
|
190 |
- const char *buffer; |
|
191 |
- size_t len; |
|
192 |
- void *resblock; |
|
193 |
-{ |
|
194 |
- struct md5_ctx ctx; |
|
195 |
- |
|
196 |
- /* Initialize the computation context. */ |
|
197 |
- md5_init_ctx (&ctx); |
|
198 |
- |
|
199 |
- /* Process whole buffer but last len % 64 bytes. */ |
|
200 |
- md5_process_bytes (buffer, len, &ctx); |
|
201 | 96 |
|
202 |
- /* Put result in desired memory area. */ |
|
203 |
- return md5_finish_ctx (&ctx, resblock); |
|
97 |
+ /* Handle any remaining bytes of data. */ |
|
98 |
+ memcpy(ctx->in, buf, len); |
|
204 | 99 |
} |
205 | 100 |
|
206 |
- |
|
101 |
+/* |
|
102 |
+ * Final wrapup - pad to 64-byte boundary with the bit pattern |
|
103 |
+ * 1 0* (64-bit count of bits processed, MSB-first) |
|
104 |
+ */ |
|
207 | 105 |
void |
208 |
-md5_process_bytes (buffer, len, ctx) |
|
209 |
- const void *buffer; |
|
210 |
- size_t len; |
|
211 |
- struct md5_ctx *ctx; |
|
106 |
+MD5Final(md5byte *digest, struct MD5Context *ctx) |
|
212 | 107 |
{ |
213 |
- /* When we already have some bits in our internal buffer concatenate |
|
214 |
- both inputs first. */ |
|
215 |
- if (ctx->buflen != 0) |
|
216 |
- { |
|
217 |
- size_t left_over = ctx->buflen; |
|
218 |
- size_t add = 128 - left_over > len ? len : 128 - left_over; |
|
108 |
+ int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */ |
|
109 |
+ md5byte *p = (md5byte *)ctx->in + count; |
|
219 | 110 |
|
220 |
- /* Only put full words in the buffer. */ |
|
221 |
- add -= add % __alignof__ (md5_uint32); |
|
111 |
+ /* Set the first char of padding to 0x80. There is always room. */ |
|
112 |
+ *p++ = 0x80; |
|
222 | 113 |
|
223 |
- memcpy (&ctx->buffer[left_over], buffer, add); |
|
224 |
- ctx->buflen += add; |
|
114 |
+ /* Bytes of padding needed to make 56 bytes (-8..55) */ |
|
115 |
+ count = 56 - 1 - count; |
|
225 | 116 |
|
226 |
- if (ctx->buflen > 64) |
|
227 |
- { |
|
228 |
- md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); |
|
229 |
- |
|
230 |
- ctx->buflen &= 63; |
|
231 |
- /* The regions in the following copy operation cannot overlap. */ |
|
232 |
- memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], |
|
233 |
- ctx->buflen); |
|
117 |
+ if (count < 0) { /* Padding forces an extra block */ |
|
118 |
+ memset(p, 0, count + 8); |
|
119 |
+ byteSwap(ctx->in, 16); |
|
120 |
+ MD5Transform(ctx->buf, ctx->in); |
|
121 |
+ p = (md5byte *)ctx->in; |
|
122 |
+ count = 56; |
|
234 | 123 |
} |
124 |
+ memset(p, 0, count); |
|
125 |
+ byteSwap(ctx->in, 14); |
|
235 | 126 |
|
236 |
- buffer = (const char *) buffer + add; |
|
237 |
- len -= add; |
|
238 |
- } |
|
239 |
- |
|
240 |
- /* Process available complete blocks. */ |
|
241 |
- if (len > 64) |
|
242 |
- { |
|
243 |
- md5_process_block (buffer, len & ~63, ctx); |
|
244 |
- buffer = (const char *) buffer + (len & ~63); |
|
245 |
- len &= 63; |
|
246 |
- } |
|
247 |
- |
|
248 |
- /* Move remaining bytes in internal buffer. */ |
|
249 |
- if (len > 0) |
|
250 |
- { |
|
251 |
- size_t left_over = ctx->buflen; |
|
127 |
+ /* Append length in bits and transform */ |
|
128 |
+ ctx->in[14] = ctx->bytes[0] << 3; |
|
129 |
+ ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29; |
|
130 |
+ MD5Transform(ctx->buf, ctx->in); |
|
252 | 131 |
|
253 |
- memcpy (&ctx->buffer[left_over], buffer, len); |
|
254 |
- left_over += len; |
|
255 |
- if (left_over >= 64) |
|
256 |
- { |
|
257 |
- md5_process_block (ctx->buffer, 64, ctx); |
|
258 |
- left_over -= 64; |
|
259 |
- memcpy (ctx->buffer, &ctx->buffer[64], left_over); |
|
260 |
- } |
|
261 |
- ctx->buflen = left_over; |
|
262 |
- } |
|
132 |
+ byteSwap(ctx->buf, 4); |
|
133 |
+ memcpy(digest, ctx->buf, 16); |
|
134 |
+ memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ |
|
263 | 135 |
} |
264 | 136 |
|
137 |
+/* The four core functions - F1 is optimized somewhat */ |
|
265 | 138 |
|
266 |
-/* These are the four functions used in the four steps of the MD5 algorithm |
|
267 |
- and defined in the RFC 1321. The first function is a little bit optimized |
|
268 |
- (as found in Colin Plumbs public domain implementation). */ |
|
269 |
-/* #define FF(b, c, d) ((b & c) | (~b & d)) */ |
|
270 |
-#define FF(b, c, d) (d ^ (b & (c ^ d))) |
|
271 |
-#define FG(b, c, d) FF (d, b, c) |
|
272 |
-#define FH(b, c, d) (b ^ c ^ d) |
|
273 |
-#define FI(b, c, d) (c ^ (b | ~d)) |
|
139 |
+/* #define F1(x, y, z) (x & y | ~x & z) */ |
|
140 |
+#define F1(x, y, z) (z ^ (x & (y ^ z))) |
|
141 |
+#define F2(x, y, z) F1(z, x, y) |
|
142 |
+#define F3(x, y, z) (x ^ y ^ z) |
|
143 |
+#define F4(x, y, z) (y ^ (x | ~z)) |
|
274 | 144 |
|
275 |
-/* Process LEN bytes of BUFFER, accumulating context into CTX. |
|
276 |
- It is assumed that LEN % 64 == 0. */ |
|
145 |
+/* This is the central step in the MD5 algorithm. */ |
|
146 |
+#define MD5STEP(f,w,x,y,z,in,s) \ |
|
147 |
+ (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x) |
|
277 | 148 |
|
149 |
+/* |
|
150 |
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to |
|
151 |
+ * reflect the addition of 16 longwords of new data. MD5Update blocks |
|
152 |
+ * the data and converts bytes into longwords for this routine. |
|
153 |
+ */ |
|
278 | 154 |
void |
279 |
-md5_process_block (buffer, len, ctx) |
|
280 |
- const void *buffer; |
|
281 |
- size_t len; |
|
282 |
- struct md5_ctx *ctx; |
|
155 |
+MD5Transform(uint32_t buf[4], uint32_t const in[16]) |
|
283 | 156 |
{ |
284 |
- md5_uint32 correct_words[16]; |
|
285 |
- const md5_uint32 *words = buffer; |
|
286 |
- size_t nwords = len / sizeof (md5_uint32); |
|
287 |
- const md5_uint32 *endp = words + nwords; |
|
288 |
- md5_uint32 A = ctx->A; |
|
289 |
- md5_uint32 B = ctx->B; |
|
290 |
- md5_uint32 C = ctx->C; |
|
291 |
- md5_uint32 D = ctx->D; |
|
292 |
- |
|
293 |
- /* First increment the byte count. RFC 1321 specifies the possible |
|
294 |
- length of the file up to 2^64 bits. Here we only compute the |
|
295 |
- number of bytes. Do a double word increment. */ |
|
296 |
- ctx->total[0] += len; |
|
297 |
- if (ctx->total[0] < len) |
|
298 |
- ++ctx->total[1]; |
|
299 |
- |
|
300 |
- /* Process all bytes in the buffer with 64 bytes in each round of |
|
301 |
- the loop. */ |
|
302 |
- while (words < endp) |
|
303 |
- { |
|
304 |
- md5_uint32 *cwp = correct_words; |
|
305 |
- md5_uint32 A_save = A; |
|
306 |
- md5_uint32 B_save = B; |
|
307 |
- md5_uint32 C_save = C; |
|
308 |
- md5_uint32 D_save = D; |
|
309 |
- |
|
310 |
- /* First round: using the given function, the context and a constant |
|
311 |
- the next context is computed. Because the algorithms processing |
|
312 |
- unit is a 32-bit word and it is determined to work on words in |
|
313 |
- little endian byte order we perhaps have to change the byte order |
|
314 |
- before the computation. To reduce the work for the next steps |
|
315 |
- we store the swapped words in the array CORRECT_WORDS. */ |
|
316 |
- |
|
317 |
-#define OP(a, b, c, d, s, T) \ |
|
318 |
- do \ |
|
319 |
- { \ |
|
320 |
- a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ |
|
321 |
- ++words; \ |
|
322 |
- CYCLIC (a, s); \ |
|
323 |
- a += b; \ |
|
324 |
- } \ |
|
325 |
- while (0) |
|
326 |
- |
|
327 |
- /* It is unfortunate that C does not provide an operator for |
|
328 |
- cyclic rotation. Hope the C compiler is smart enough. */ |
|
329 |
-#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) |
|
330 |
- |
|
331 |
- /* Before we start, one word to the strange constants. |
|
332 |
- They are defined in RFC 1321 as |
|
333 |
- |
|
334 |
- T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 |
|
335 |
- */ |
|
336 |
- |
|
337 |
- /* Round 1. */ |
|
338 |
- OP (A, B, C, D, 7, 0xd76aa478); |
|
339 |
- OP (D, A, B, C, 12, 0xe8c7b756); |
|
340 |
- OP (C, D, A, B, 17, 0x242070db); |
|
341 |
- OP (B, C, D, A, 22, 0xc1bdceee); |
|
342 |
- OP (A, B, C, D, 7, 0xf57c0faf); |
|
343 |
- OP (D, A, B, C, 12, 0x4787c62a); |
|
344 |
- OP (C, D, A, B, 17, 0xa8304613); |
|
345 |
- OP (B, C, D, A, 22, 0xfd469501); |
|
346 |
- OP (A, B, C, D, 7, 0x698098d8); |
|
347 |
- OP (D, A, B, C, 12, 0x8b44f7af); |
|
348 |
- OP (C, D, A, B, 17, 0xffff5bb1); |
|
349 |
- OP (B, C, D, A, 22, 0x895cd7be); |
|
350 |
- OP (A, B, C, D, 7, 0x6b901122); |
|
351 |
- OP (D, A, B, C, 12, 0xfd987193); |
|
352 |
- OP (C, D, A, B, 17, 0xa679438e); |
|
353 |
- OP (B, C, D, A, 22, 0x49b40821); |
|
354 |
- |
|
355 |
- /* For the second to fourth round we have the possibly swapped words |
|
356 |
- in CORRECT_WORDS. Redefine the macro to take an additional first |
|
357 |
- argument specifying the function to use. */ |
|
358 |
-#undef OP |
|
359 |
-#define OP(f, a, b, c, d, k, s, T) \ |
|
360 |
- do \ |
|
361 |
- { \ |
|
362 |
- a += f (b, c, d) + correct_words[k] + T; \ |
|
363 |
- CYCLIC (a, s); \ |
|
364 |
- a += b; \ |
|
365 |
- } \ |
|
366 |
- while (0) |
|
367 |
- |
|
368 |
- /* Round 2. */ |
|
369 |
- OP (FG, A, B, C, D, 1, 5, 0xf61e2562); |
|
370 |
- OP (FG, D, A, B, C, 6, 9, 0xc040b340); |
|
371 |
- OP (FG, C, D, A, B, 11, 14, 0x265e5a51); |
|
372 |
- OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); |
|
373 |
- OP (FG, A, B, C, D, 5, 5, 0xd62f105d); |
|
374 |
- OP (FG, D, A, B, C, 10, 9, 0x02441453); |
|
375 |
- OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); |
|
376 |
- OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); |
|
377 |
- OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); |
|
378 |
- OP (FG, D, A, B, C, 14, 9, 0xc33707d6); |
|
379 |
- OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); |
|
380 |
- OP (FG, B, C, D, A, 8, 20, 0x455a14ed); |
|
381 |
- OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); |
|
382 |
- OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); |
|
383 |
- OP (FG, C, D, A, B, 7, 14, 0x676f02d9); |
|
384 |
- OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); |
|
385 |
- |
|
386 |
- /* Round 3. */ |
|
387 |
- OP (FH, A, B, C, D, 5, 4, 0xfffa3942); |
|
388 |
- OP (FH, D, A, B, C, 8, 11, 0x8771f681); |
|
389 |
- OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); |
|
390 |
- OP (FH, B, C, D, A, 14, 23, 0xfde5380c); |
|
391 |
- OP (FH, A, B, C, D, 1, 4, 0xa4beea44); |
|
392 |
- OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); |
|
393 |
- OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); |
|
394 |
- OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); |
|
395 |
- OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); |
|
396 |
- OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); |
|
397 |
- OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); |
|
398 |
- OP (FH, B, C, D, A, 6, 23, 0x04881d05); |
|
399 |
- OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); |
|
400 |
- OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); |
|
401 |
- OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); |
|
402 |
- OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); |
|
403 |
- |
|
404 |
- /* Round 4. */ |
|
405 |
- OP (FI, A, B, C, D, 0, 6, 0xf4292244); |
|
406 |
- OP (FI, D, A, B, C, 7, 10, 0x432aff97); |
|
407 |
- OP (FI, C, D, A, B, 14, 15, 0xab9423a7); |
|
408 |
- OP (FI, B, C, D, A, 5, 21, 0xfc93a039); |
|
409 |
- OP (FI, A, B, C, D, 12, 6, 0x655b59c3); |
|
410 |
- OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); |
|
411 |
- OP (FI, C, D, A, B, 10, 15, 0xffeff47d); |
|
412 |
- OP (FI, B, C, D, A, 1, 21, 0x85845dd1); |
|
413 |
- OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); |
|
414 |
- OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); |
|
415 |
- OP (FI, C, D, A, B, 6, 15, 0xa3014314); |
|
416 |
- OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); |
|
417 |
- OP (FI, A, B, C, D, 4, 6, 0xf7537e82); |
|
418 |
- OP (FI, D, A, B, C, 11, 10, 0xbd3af235); |
|
419 |
- OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); |
|
420 |
- OP (FI, B, C, D, A, 9, 21, 0xeb86d391); |
|
421 |
- |
|
422 |
- /* Add the starting values of the context. */ |
|
423 |
- A += A_save; |
|
424 |
- B += B_save; |
|
425 |
- C += C_save; |
|
426 |
- D += D_save; |
|
427 |
- } |
|
428 |
- |
|
429 |
- /* Put checksum in context given as argument. */ |
|
430 |
- ctx->A = A; |
|
431 |
- ctx->B = B; |
|
432 |
- ctx->C = C; |
|
433 |
- ctx->D = D; |
|
157 |
+ uint32_t a, b, c, d; |
|
158 |
+ |
|
159 |
+ a = buf[0]; |
|
160 |
+ b = buf[1]; |
|
161 |
+ c = buf[2]; |
|
162 |
+ d = buf[3]; |
|
163 |
+ |
|
164 |
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); |
|
165 |
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); |
|
166 |
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); |
|
167 |
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); |
|
168 |
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); |
|
169 |
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); |
|
170 |
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); |
|
171 |
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); |
|
172 |
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); |
|
173 |
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); |
|
174 |
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); |
|
175 |
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); |
|
176 |
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); |
|
177 |
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); |
|
178 |
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); |
|
179 |
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); |
|
180 |
+ |
|
181 |
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); |
|
182 |
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); |
|
183 |
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); |
|
184 |
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); |
|
185 |
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); |
|
186 |
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); |
|
187 |
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); |
|
188 |
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); |
|
189 |
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); |
|
190 |
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); |
|
191 |
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); |
|
192 |
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); |
|
193 |
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); |
|
194 |
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); |
|
195 |
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); |
|
196 |
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); |
|
197 |
+ |
|
198 |
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); |
|
199 |
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); |
|
200 |
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); |
|
201 |
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); |
|
202 |
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); |
|
203 |
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); |
|
204 |
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); |
|
205 |
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); |
|
206 |
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); |
|
207 |
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); |
|
208 |
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); |
|
209 |
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); |
|
210 |
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); |
|
211 |
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); |
|
212 |
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); |
|
213 |
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); |
|
214 |
+ |
|
215 |
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); |
|
216 |
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); |
|
217 |
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); |
|
218 |
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); |
|
219 |
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); |
|
220 |
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); |
|
221 |
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); |
|
222 |
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); |
|
223 |
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); |
|
224 |
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); |
|
225 |
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); |
|
226 |
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); |
|
227 |
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); |
|
228 |
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); |
|
229 |
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); |
|
230 |
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); |
|
231 |
+ |
|
232 |
+ buf[0] += a; |
|
233 |
+ buf[1] += b; |
|
234 |
+ buf[2] += c; |
|
235 |
+ buf[3] += d; |
|
434 | 236 |
} |
... | ... |
@@ -1,164 +1,37 @@ |
1 |
-/* Declaration of functions and data types used for MD5 sum computing |
|
2 |
- library functions. |
|
3 |
- Copyright (C) 1995, 1996, 1997, 1999, 2000 Free Software Foundation, Inc. |
|
4 |
- This file is part of the GNU C Library. |
|
5 |
- |
|
6 |
- The GNU C Library is free software; you can redistribute it and/or |
|
7 |
- modify it under the terms of the GNU Library General Public License as |
|
8 |
- published by the Free Software Foundation; either version 2 of the |
|
9 |
- License, or (at your option) any later version. |
|
10 |
- |
|
11 |
- The GNU C Library 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 GNU |
|
14 |
- Library General Public License for more details. |
|
15 |
- |
|
16 |
- You should have received a copy of the GNU Library General Public |
|
17 |
- License along with the GNU C Library; see the file COPYING.LIB. If not, |
|
18 |
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
19 |
- Boston, MA 02111-1307, USA. */ |
|
20 |
- |
|
21 |
-#ifndef _MD5_H |
|
22 |
-#define _MD5_H 1 |
|
23 |
- |
|
24 |
-#include <stdio.h> |
|
25 |
- |
|
26 |
-#if defined HAVE_LIMITS_H || _LIBC |
|
27 |
-# include <limits.h> |
|
28 |
-#endif |
|
29 |
- |
|
30 |
-/* The following contortions are an attempt to use the C preprocessor |
|
31 |
- to determine an unsigned integral type that is 32 bits wide. An |
|
32 |
- alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but |
|
33 |
- doing that would require that the configure script compile and *run* |
|
34 |
- the resulting executable. Locally running cross-compiled executables |
|
35 |
- is usually not possible. */ |
|
36 |
- |
|
37 |
-#ifdef _LIBC |
|
38 |
-# include <sys/types.h> |
|
39 |
-typedef u_int32_t md5_uint32; |
|
40 |
-#else |
|
41 |
-# if defined __STDC__ && __STDC__ |
|
42 |
-# define UINT_MAX_32_BITS 4294967295U |
|
43 |
-# else |
|
44 |
-# define UINT_MAX_32_BITS 0xFFFFFFFF |
|
45 |
-# endif |
|
46 |
- |
|
47 |
-/* If UINT_MAX isn't defined, assume it's a 32-bit type. |
|
48 |
- This should be valid for all systems GNU cares about because |
|
49 |
- that doesn't include 16-bit systems, and only modern systems |
|
50 |
- (that certainly have <limits.h>) have 64+-bit integral types. */ |
|
51 |
- |
|
52 |
-# ifndef UINT_MAX |
|
53 |
-# define UINT_MAX UINT_MAX_32_BITS |
|
54 |
-# endif |
|
55 |
- |
|
56 |
-# if UINT_MAX == UINT_MAX_32_BITS |
|
57 |
- typedef unsigned int md5_uint32; |
|
58 |
-# else |
|
59 |
-# if USHRT_MAX == UINT_MAX_32_BITS |
|
60 |
- typedef unsigned short md5_uint32; |
|
61 |
-# else |
|
62 |
-# if ULONG_MAX == UINT_MAX_32_BITS |
|
63 |
- typedef unsigned long md5_uint32; |
|
64 |
-# else |
|
65 |
- /* The following line is intended to evoke an error. |
|
66 |
- Using #error is not portable enough. */ |
|
67 |
- "Cannot determine unsigned 32-bit data type." |
|
68 |
-# endif |
|
69 |
-# endif |
|
70 |
-# endif |
|
71 |
-#endif |
|
72 |
- |
|
73 |
-#undef __P |
|
74 |
-#if defined (__STDC__) && __STDC__ |
|
75 |
-# define __P(x) x |
|
76 |
-#else |
|
77 |
-# define __P(x) () |
|
78 |
-#endif |
|
79 |
- |
|
80 |
-/* Structure to save state of computation between the single steps. */ |
|
81 |
-struct md5_ctx |
|
82 |
-{ |
|
83 |
- md5_uint32 A; |
|
84 |
- md5_uint32 B; |
|
85 |
- md5_uint32 C; |
|
86 |
- md5_uint32 D; |
|
87 |
- |
|
88 |
- md5_uint32 total[2]; |
|
89 |
- md5_uint32 buflen; |
|
90 |
-#ifndef __attribute__ |
|
91 |
- char buffer[128]; |
|
92 |
-#else |
|
93 |
- char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); |
|
94 |
-#endif |
|
95 |
-}; |
|
96 |
- |
|
97 |
-#ifndef __attribute__ |
|
98 |
-#define __alignof__(a) sizeof(a) |
|
99 |
-#endif |
|
100 |
- |
|
101 | 1 |
/* |
102 |
- * The following three functions are build up the low level used in |
|
103 |
- * the functions `md5_stream' and `md5_buffer'. |
|
2 |
+ * This is the header file for the MD5 message-digest algorithm. |
|
3 |
+ * The algorithm is due to Ron Rivest. This code was |
|
4 |
+ * written by Colin Plumb in 1993, no copyright is claimed. |
|
5 |
+ * This code is in the public domain; do with it what you wish. |
|
6 |
+ * |
|
7 |
+ * Equivalent code is available from RSA Data Security, Inc. |
|
8 |
+ * This code has been tested against that, and is equivalent, |
|
9 |
+ * except that you don't need to include two pages of legalese |
|
10 |
+ * with every copy. |
|
11 |
+ * |
|
12 |
+ * To compute the message digest of a chunk of bytes, declare an |
|
13 |
+ * MD5Context structure, pass it to MD5Init, call MD5Update as |
|
14 |
+ * needed on buffers full of bytes, and then call MD5Final, which |
|
15 |
+ * will fill a supplied 16-byte array with the digest. |
|
16 |
+ * |
|
104 | 17 |
*/ |
105 | 18 |
|
106 |
-/* Initialize structure containing state of computation. |
|
107 |
- (RFC 1321, 3.3: Step 3) */ |
|
108 |
-extern void __md5_init_ctx __P ((struct md5_ctx *ctx)); |
|
109 |
- |
|
110 |
-/* Starting with the result of former calls of this function (or the |
|
111 |
- initialization function update the context for the next LEN bytes |
|
112 |
- starting at BUFFER. |
|
113 |
- It is necessary that LEN is a multiple of 64!!! */ |
|
114 |
-extern void __md5_process_block __P ((const void *buffer, size_t len, |
|
115 |
- struct md5_ctx *ctx)); |
|
116 |
- |
|
117 |
-/* Starting with the result of former calls of this function (or the |
|
118 |
- initialization function update the context for the next LEN bytes |
|
119 |
- starting at BUFFER. |
|
120 |
- It is NOT required that LEN is a multiple of 64. */ |
|
121 |
-extern void __md5_process_bytes __P ((const void *buffer, size_t len, |
|
122 |
- struct md5_ctx *ctx)); |
|
19 |
+#ifndef __MD5_H |
|
20 |
+#define __MD5_H |
|
123 | 21 |
|
124 |
-/* Process the remaining bytes in the buffer and put result from CTX |
|
125 |
- in first 16 bytes following RESBUF. The result is always in little |
|
126 |
- endian byte order, so that a byte-wise output yields to the wanted |
|
127 |
- ASCII representation of the message digest. |
|
22 |
+#define md5byte unsigned char |
|
128 | 23 |
|
129 |
- IMPORTANT: On some systems it is required that RESBUF is correctly |
|
130 |
- aligned for a 32 bits value. */ |
|
131 |
-extern void *__md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf)); |
|
132 |
- |
|
133 |
- |
|
134 |
-/* Put result from CTX in first 16 bytes following RESBUF. The result is |
|
135 |
- always in little endian byte order, so that a byte-wise output yields |
|
136 |
- to the wanted ASCII representation of the message digest. |
|
137 |
- |
|
138 |
- IMPORTANT: On some systems it is required that RESBUF is correctly |
|
139 |
- aligned for a 32 bits value. */ |
|
140 |
-extern void *__md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf)); |
|
141 |
- |
|
142 |
- |
|
143 |
-/* Compute MD5 message digest for bytes read from STREAM. The |
|
144 |
- resulting message digest number will be written into the 16 bytes |
|
145 |
- beginning at RESBLOCK. */ |
|
146 |
-extern int __md5_stream __P ((FILE *stream, void *resblock)); |
|
147 |
- |
|
148 |
-/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The |
|
149 |
- result is always in little endian byte order, so that a byte-wise |
|
150 |
- output yields to the wanted ASCII representation of the message |
|
151 |
- digest. */ |
|
152 |
-extern void *__md5_buffer __P ((const char *buffer, size_t len, |
|
153 |
- void *resblock)); |
|
24 |
+#include "cltypes.h" |
|
154 | 25 |
|
26 |
+struct MD5Context { |
|
27 |
+ uint32_t buf[4]; |
|
28 |
+ uint32_t bytes[2]; |
|
29 |
+ uint32_t in[16]; |
|
30 |
+}; |
|
155 | 31 |
|
156 |
-# define md5_init_ctx __md5_init_ctx |
|
157 |
-# define md5_process_block __md5_process_block |
|
158 |
-# define md5_process_bytes __md5_process_bytes |
|
159 |
-# define md5_finish_ctx __md5_finish_ctx |
|
160 |
-# define md5_read_ctx __md5_read_ctx |
|
161 |
-# define md5_stream __md5_stream |
|
162 |
-# define md5_buffer __md5_buffer |
|
32 |
+void MD5Init(struct MD5Context *context); |
|
33 |
+void MD5Update(struct MD5Context *context, md5byte const *buf, unsigned len); |
|
34 |
+void MD5Final(unsigned char *digest, struct MD5Context *context); |
|
35 |
+void MD5Transform(uint32_t buf[4], uint32_t const in[16]); |
|
163 | 36 |
|
164 |
-#endif /* md5.h */ |
|
37 |
+#endif |
... | ... |
@@ -163,65 +163,77 @@ const char *cl_perror(int clerror) |
163 | 163 |
return cl_strerror(clerror); |
164 | 164 |
} |
165 | 165 |
|
166 |
-char *cli_md5stream(FILE *fd) |
|
166 |
+char *cli_md5stream(FILE *fs, unsigned char *digcpy) |
|
167 | 167 |
{ |
168 |
- unsigned char buffer[16]; |
|
169 |
- char *md5str; |
|
170 |
- int i, cnt=0; |
|
168 |
+ unsigned char digest[16]; |
|
169 |
+ char buff[FILEBUFF]; |
|
170 |
+ struct MD5Context ctx; |
|
171 |
+ char *md5str, *pt; |
|
172 |
+ int i, bytes; |
|
173 |
+ |
|
174 |
+ |
|
175 |
+ MD5Init(&ctx); |
|
176 |
+ |
|
177 |
+ while((bytes = fread(buff, 1, FILEBUFF, fs))) |
|
178 |
+ MD5Update(&ctx, buff, bytes); |
|
171 | 179 |
|
172 |
- md5_stream(fd, &buffer); |
|
180 |
+ MD5Final(digest, &ctx); |
|
173 | 181 |
|
174 |
- md5str = (char*) calloc(32 + 1, sizeof(char)); |
|
182 |
+ if(!(md5str = (char *) cli_calloc(32 + 1, sizeof(char)))) |
|
183 |
+ return NULL; |
|
184 |
+ |
|
185 |
+ pt = md5str; |
|
186 |
+ for(i = 0; i < 16; i++) { |
|
187 |
+ sprintf(pt, "%02x", digest[i]); |
|
188 |
+ pt += 2; |
|
189 |
+ } |
|
175 | 190 |
|
176 |
- for(i=0; i<16; i++) |
|
177 |
- cnt += sprintf(md5str + cnt, "%02x", buffer[i]); |
|
191 |
+ if(digcpy) |
|
192 |
+ memcpy(digcpy, digest, 16); |
|
178 | 193 |
|
179 |
- return(md5str); |
|
194 |
+ return md5str; |
|
180 | 195 |
} |
181 | 196 |
|
182 | 197 |
char *cli_md5file(const char *filename) |
183 | 198 |
{ |
184 |
- FILE *fd; |
|
185 |
- unsigned char buffer[16]; |
|
199 |
+ FILE *fs; |
|
186 | 200 |
char *md5str; |
187 |
- int i, cnt=0; |
|
188 | 201 |
|
189 | 202 |
|
190 |
- if((fd = fopen(filename, "rb")) == NULL) { |
|
203 |
+ if((fs = fopen(filename, "rb")) == NULL) { |
|
191 | 204 |
cli_errmsg("cli_md5file(): Can't read file %s\n", filename); |
192 | 205 |
return NULL; |
193 | 206 |
} |
194 | 207 |
|
195 |
- md5_stream(fd, &buffer); |
|
196 |
- fclose(fd); |
|
208 |
+ md5str = cli_md5stream(fs, NULL); |
|
209 |
+ fclose(fs); |
|
197 | 210 |
|
198 |
- md5str = (char*) calloc(32 + 1, sizeof(char)); |
|
199 |
- |
|
200 |
- for(i=0; i<16; i++) |
|
201 |
- cnt += sprintf(md5str + cnt, "%02x", buffer[i]); |
|
202 |
- |
|
203 |
- return(md5str); |
|
211 |
+ return md5str; |
|
204 | 212 |
} |
205 | 213 |
|
206 | 214 |
static char *cli_md5buff(const char *buffer, unsigned int len) |
207 | 215 |
{ |
208 |
- unsigned char md5buff[16]; |
|
209 |
- char *md5str; |
|
210 |
- struct md5_ctx ctx; |
|
211 |
- int i, cnt=0; |
|
216 |
+ unsigned char digest[16]; |
|
217 |
+ char *md5str, *pt; |
|
218 |
+ struct MD5Context ctx; |
|
219 |
+ int i; |
|
212 | 220 |
|
213 | 221 |
|
214 |
- md5_init_ctx(&ctx); |
|
215 |
- md5_process_bytes(buffer, len, &ctx); |
|
216 |
- md5_finish_ctx(&ctx, &md5buff); |
|
217 |
- memcpy(oldmd5buff, md5buff, 16); |
|
222 |
+ MD5Init(&ctx); |
|
223 |
+ MD5Update(&ctx, buffer, len); |
|
224 |
+ MD5Final(digest, &ctx); |
|
225 |
+ memcpy(oldmd5buff, digest, 16); |
|
218 | 226 |
|
219 |
- md5str = (char*) cli_calloc(32 + 1, sizeof(char)); |
|
227 |
+ if(!(md5str = (char *) cli_calloc(32 + 1, sizeof(char)))) |
|
228 |
+ return NULL; |
|
220 | 229 |
|
221 |
- for(i=0; i<16; i++) |
|
222 |
- cnt += sprintf(md5str + cnt, "%02x", md5buff[i]); |
|
230 |
+ pt = md5str; |
|
231 |
+ for(i = 0; i < 16; i++) { |
|
232 |
+ sprintf(pt, "%02x", digest[i]); |
|
233 |
+ pt += 2; |
|
234 |
+ } |
|
223 | 235 |
|
224 |
- return(md5str); |
|
236 |
+ return md5str; |
|
225 | 237 |
} |
226 | 238 |
|
227 | 239 |
void *cli_malloc(size_t size) |
... | ... |
@@ -30,13 +30,13 @@ void *cli_malloc(size_t nmemb); |
30 | 30 |
void *cli_calloc(size_t nmemb, size_t size); |
31 | 31 |
void *cli_realloc(void *ptr, size_t size); |
32 | 32 |
int cli_rmdirs(const char *dirname); |
33 |
-char *cli_md5stream(FILE *fd); |
|
33 |
+char *cli_md5stream(FILE *fs, unsigned char *digcpy); |
|
34 |
+char *cli_md5file(const char *filename); |
|
34 | 35 |
int cli_readn(int fd, void *buff, unsigned int count); |
35 | 36 |
int cli_writen(int fd, void *buff, unsigned int count); |
36 | 37 |
int32_t cli_readint32(const char *buff); |
37 | 38 |
char *cli_gentemp(const char *dir); |
38 | 39 |
unsigned int cli_rndnum(unsigned int max); |
39 |
-char *cli_md5file(const char *filename); |
|
40 | 40 |
int cli_memstr(const char *haystack, int hs, const char *needle, int ns); |
41 | 41 |
|
42 | 42 |
#endif |
... | ... |
@@ -123,7 +123,7 @@ void sigtool(struct optstruct *opt) |
123 | 123 |
|
124 | 124 |
} else { |
125 | 125 |
|
126 |
- md5 = cli_md5stream(stdin); |
|
126 |
+ md5 = cli_md5stream(stdin, NULL); |
|
127 | 127 |
mprintf("%s\n", md5); |
128 | 128 |
free(md5); |
129 | 129 |
} |
... | ... |
@@ -365,8 +365,9 @@ int build(struct optstruct *opt) |
365 | 365 |
|
366 | 366 |
/* digital signature */ |
367 | 367 |
fd = fopen(gzfile, "rb"); |
368 |
- __md5_stream(fd, &buffer); |
|
368 |
+ pt = cli_md5stream(fd, buffer); |
|
369 | 369 |
fclose(fd); |
370 |
+ free(pt); |
|
370 | 371 |
if(!(pt = getdsig(getargl(opt, "server"), smbuff, buffer))) { |
371 | 372 |
mprintf("No digital signature - no CVD file...\n"); |
372 | 373 |
unlink(gzfile); |