Mercurial > hg > octave-kai > gnulib-hg
annotate lib/md2.c @ 12198:e8fbc5424b99
digests, copy-file: increase the IO buffer size from 4KiB to 32KiB
This results in a significant decrease in syscall overhead
giving a 3% speedup to the digest utilities for example
(when processing large files from cache).
Storage is moved from the stack to the heap as some
threaded environments for example can have small stacks.
* lib/copy-file.c (copy_file_preserving): Use a 32KiB malloced buffer
* modules/copy-file: Depend on xalloc
* lib/md2.c: Likewise
* lib/md4.c: Likewise
* lib/md5.c: Likewise
* lib/sha1.c: Likewise
* lib/sha256.c: Likewise
* lib/sha512.c: Likewise
author | Pádraig Brady <P@draigBrady.com> |
---|---|
date | Thu, 22 Oct 2009 17:36:28 +0100 |
parents | 5680cf5b5595 |
children | e8d2c6fc33ad |
rev | line source |
---|---|
6431 | 1 /* Functions to compute MD2 message digest of files or memory blocks. |
2 according to the definition of MD2 in RFC 1319 from April 1992. | |
9659
5680cf5b5595
md2: clarify comments to say that alignment is not required.
Simon Josefsson <simon@josefsson.org>
parents:
7584
diff
changeset
|
3 Copyright (C) 1995,1996,1997,1999,2000,2001,2002,2003,2005,2006,2008 |
6431 | 4 Free Software Foundation, Inc. |
5 | |
6 This program is free software; you can redistribute it and/or modify it | |
7 under the terms of the GNU General Public License as published by the | |
8 Free Software Foundation; either version 2, or (at your option) any | |
9 later version. | |
10 | |
11 This program 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 General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with this program; if not, write to the Free Software Foundation, | |
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | |
19 | |
20 /* Adapted by Simon Josefsson from public domain Libtomcrypt 1.06 by | |
21 Tom St Denis. */ | |
22 | |
7584
a88f85e4728f
* lib/arcfour.c: Assume config.h.
Eric Blake <ebb9@byu.net>
parents:
6431
diff
changeset
|
23 #include <config.h> |
6431 | 24 |
25 #include "md2.h" | |
26 | |
12198
e8fbc5424b99
digests, copy-file: increase the IO buffer size from 4KiB to 32KiB
Pádraig Brady <P@draigBrady.com>
parents:
9659
diff
changeset
|
27 #include <stdlib.h> |
6431 | 28 #include <string.h> |
29 #include <sys/types.h> | |
30 | |
31 #include <minmax.h> | |
32 | |
33 #if USE_UNLOCKED_IO | |
34 # include "unlocked-io.h" | |
35 #endif | |
36 | |
12198
e8fbc5424b99
digests, copy-file: increase the IO buffer size from 4KiB to 32KiB
Pádraig Brady <P@draigBrady.com>
parents:
9659
diff
changeset
|
37 #define BLOCKSIZE 32768 |
6431 | 38 #if BLOCKSIZE % 64 != 0 |
39 # error "invalid BLOCKSIZE" | |
40 #endif | |
41 | |
42 static void md2_update_chksum (struct md2_ctx *md); | |
43 static void md2_compress (struct md2_ctx *md); | |
44 | |
45 /* Initialize structure containing state of computation. | |
46 (RFC 1319, 3.3: Step 3) */ | |
47 void | |
48 md2_init_ctx (struct md2_ctx *ctx) | |
49 { | |
50 memset (ctx->X, 0, sizeof (ctx->X)); | |
51 memset (ctx->chksum, 0, sizeof (ctx->chksum)); | |
52 memset (ctx->buf, 0, sizeof (ctx->buf)); | |
53 ctx->curlen = 0; | |
54 } | |
55 | |
56 /* Put result from CTX in first 16 bytes following RESBUF. The result | |
9659
5680cf5b5595
md2: clarify comments to say that alignment is not required.
Simon Josefsson <simon@josefsson.org>
parents:
7584
diff
changeset
|
57 must be in little endian byte order. */ |
6431 | 58 void * |
59 md2_read_ctx (const struct md2_ctx *ctx, void *resbuf) | |
60 { | |
61 memcpy (resbuf, ctx->X, 16); | |
62 | |
63 return resbuf; | |
64 } | |
65 | |
66 /* Process the remaining bytes in the internal buffer and the usual | |
9659
5680cf5b5595
md2: clarify comments to say that alignment is not required.
Simon Josefsson <simon@josefsson.org>
parents:
7584
diff
changeset
|
67 prolog according to the standard and write the result to RESBUF. */ |
6431 | 68 void * |
69 md2_finish_ctx (struct md2_ctx *ctx, void *resbuf) | |
70 { | |
71 unsigned long i, k; | |
72 | |
73 /* pad the message */ | |
74 k = 16 - ctx->curlen; | |
75 for (i = ctx->curlen; i < 16; i++) | |
76 { | |
77 ctx->buf[i] = (unsigned char) k; | |
78 } | |
79 | |
80 /* hash and update */ | |
81 md2_compress (ctx); | |
82 md2_update_chksum (ctx); | |
83 | |
84 /* hash checksum */ | |
85 memcpy (ctx->buf, ctx->chksum, 16); | |
86 md2_compress (ctx); | |
87 | |
88 return md2_read_ctx (ctx, resbuf); | |
89 } | |
90 | |
91 /* Compute MD2 message digest for bytes read from STREAM. The | |
92 resulting message digest number will be written into the 16 bytes | |
93 beginning at RESBLOCK. */ | |
94 int | |
95 md2_stream (FILE *stream, void *resblock) | |
96 { | |
97 struct md2_ctx ctx; | |
98 size_t sum; | |
99 | |
12198
e8fbc5424b99
digests, copy-file: increase the IO buffer size from 4KiB to 32KiB
Pádraig Brady <P@draigBrady.com>
parents:
9659
diff
changeset
|
100 char *buffer = malloc (BLOCKSIZE + 72); |
e8fbc5424b99
digests, copy-file: increase the IO buffer size from 4KiB to 32KiB
Pádraig Brady <P@draigBrady.com>
parents:
9659
diff
changeset
|
101 if (!buffer) |
e8fbc5424b99
digests, copy-file: increase the IO buffer size from 4KiB to 32KiB
Pádraig Brady <P@draigBrady.com>
parents:
9659
diff
changeset
|
102 return 1; |
e8fbc5424b99
digests, copy-file: increase the IO buffer size from 4KiB to 32KiB
Pádraig Brady <P@draigBrady.com>
parents:
9659
diff
changeset
|
103 |
6431 | 104 /* Initialize the computation context. */ |
105 md2_init_ctx (&ctx); | |
106 | |
107 /* Iterate over full file contents. */ | |
108 while (1) | |
109 { | |
110 /* We read the file in blocks of BLOCKSIZE bytes. One call of the | |
111 computation function processes the whole buffer so that with the | |
112 next round of the loop another block can be read. */ | |
113 size_t n; | |
114 sum = 0; | |
115 | |
116 /* Read block. Take care for partial reads. */ | |
117 while (1) | |
118 { | |
119 n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); | |
120 | |
121 sum += n; | |
122 | |
123 if (sum == BLOCKSIZE) | |
124 break; | |
125 | |
126 if (n == 0) | |
127 { | |
128 /* Check for the error flag IFF N == 0, so that we don't | |
129 exit the loop after a partial read due to e.g., EAGAIN | |
130 or EWOULDBLOCK. */ | |
131 if (ferror (stream)) | |
12198
e8fbc5424b99
digests, copy-file: increase the IO buffer size from 4KiB to 32KiB
Pádraig Brady <P@draigBrady.com>
parents:
9659
diff
changeset
|
132 { |
e8fbc5424b99
digests, copy-file: increase the IO buffer size from 4KiB to 32KiB
Pádraig Brady <P@draigBrady.com>
parents:
9659
diff
changeset
|
133 free (buffer); |
e8fbc5424b99
digests, copy-file: increase the IO buffer size from 4KiB to 32KiB
Pádraig Brady <P@draigBrady.com>
parents:
9659
diff
changeset
|
134 return 1; |
e8fbc5424b99
digests, copy-file: increase the IO buffer size from 4KiB to 32KiB
Pádraig Brady <P@draigBrady.com>
parents:
9659
diff
changeset
|
135 } |
6431 | 136 goto process_partial_block; |
137 } | |
138 | |
139 /* We've read at least one byte, so ignore errors. But always | |
140 check for EOF, since feof may be true even though N > 0. | |
141 Otherwise, we could end up calling fread after EOF. */ | |
142 if (feof (stream)) | |
143 goto process_partial_block; | |
144 } | |
145 | |
146 /* Process buffer with BLOCKSIZE bytes. Note that | |
147 BLOCKSIZE % 64 == 0 | |
148 */ | |
149 md2_process_block (buffer, BLOCKSIZE, &ctx); | |
150 } | |
151 | |
152 process_partial_block:; | |
153 | |
154 /* Process any remaining bytes. */ | |
155 if (sum > 0) | |
156 md2_process_bytes (buffer, sum, &ctx); | |
157 | |
158 /* Construct result in desired memory. */ | |
159 md2_finish_ctx (&ctx, resblock); | |
12198
e8fbc5424b99
digests, copy-file: increase the IO buffer size from 4KiB to 32KiB
Pádraig Brady <P@draigBrady.com>
parents:
9659
diff
changeset
|
160 free (buffer); |
6431 | 161 return 0; |
162 } | |
163 | |
164 /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The | |
165 result is always in little endian byte order, so that a byte-wise | |
166 output yields to the wanted ASCII representation of the message | |
167 digest. */ | |
168 void * | |
169 md2_buffer (const char *buffer, size_t len, void *resblock) | |
170 { | |
171 struct md2_ctx ctx; | |
172 | |
173 /* Initialize the computation context. */ | |
174 md2_init_ctx (&ctx); | |
175 | |
176 /* Process whole buffer but last len % 64 bytes. */ | |
177 md2_process_block (buffer, len, &ctx); | |
178 | |
179 /* Put result in desired memory area. */ | |
180 return md2_finish_ctx (&ctx, resblock); | |
181 } | |
182 | |
183 void | |
184 md2_process_bytes (const void *buffer, size_t len, struct md2_ctx *ctx) | |
185 { | |
186 const char *in = buffer; | |
187 unsigned long n; | |
188 | |
189 while (len > 0) | |
190 { | |
191 n = MIN (len, (16 - ctx->curlen)); | |
192 memcpy (ctx->buf + ctx->curlen, in, (size_t) n); | |
193 ctx->curlen += n; | |
194 in += n; | |
195 len -= n; | |
196 | |
197 /* is 16 bytes full? */ | |
198 if (ctx->curlen == 16) | |
199 { | |
200 md2_compress (ctx); | |
201 md2_update_chksum (ctx); | |
202 ctx->curlen = 0; | |
203 } | |
204 } | |
205 } | |
206 | |
207 static const unsigned char PI_SUBST[256] = { | |
208 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, | |
209 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, | |
210 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, | |
211 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, | |
212 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, | |
213 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, | |
214 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, | |
215 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, | |
216 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, | |
217 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, | |
218 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, | |
219 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, | |
220 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, | |
221 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, | |
222 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, | |
223 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, | |
224 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, | |
225 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 | |
226 }; | |
227 | |
228 /* adds 16 bytes to the checksum */ | |
229 static void | |
230 md2_update_chksum (struct md2_ctx *ctx) | |
231 { | |
232 int j; | |
233 unsigned char L; | |
234 | |
235 L = ctx->chksum[15]; | |
236 for (j = 0; j < 16; j++) | |
237 { | |
238 /* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the | |
239 reference source code [and test vectors] say otherwise. */ | |
240 L = (ctx->chksum[j] ^= PI_SUBST[(int) (ctx->buf[j] ^ L)] & 255); | |
241 } | |
242 } | |
243 | |
244 static void | |
245 md2_compress (struct md2_ctx *ctx) | |
246 { | |
247 size_t j, k; | |
248 unsigned char t; | |
249 | |
250 /* copy block */ | |
251 for (j = 0; j < 16; j++) | |
252 { | |
253 ctx->X[16 + j] = ctx->buf[j]; | |
254 ctx->X[32 + j] = ctx->X[j] ^ ctx->X[16 + j]; | |
255 } | |
256 | |
257 t = (unsigned char) 0; | |
258 | |
259 /* do 18 rounds */ | |
260 for (j = 0; j < 18; j++) | |
261 { | |
262 for (k = 0; k < 48; k++) | |
263 { | |
264 t = (ctx->X[k] ^= PI_SUBST[(int) (t & 255)]); | |
265 } | |
266 t = (t + (unsigned char) j) & 255; | |
267 } | |
268 } | |
269 | |
270 /* Process LEN bytes of BUFFER, accumulating context into CTX. */ | |
271 void | |
272 md2_process_block (const void *buffer, size_t len, struct md2_ctx *ctx) | |
273 { | |
274 md2_process_bytes (buffer, len, ctx); | |
275 } |