Document not_eol and remove mention of regex.c.
[gnulib.git] / lib / md2.c
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.
3    Copyright (C) 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2005, 2006,
4    2008, 2009, 2010 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
23 #include <config.h>
24
25 #include "md2.h"
26
27 #include <stdlib.h>
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
37 #define BLOCKSIZE 32768
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
57    must be in little endian byte order.  */
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
67    prolog according to the standard and write the result to RESBUF.  */
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
100   char *buffer = malloc (BLOCKSIZE + 72);
101   if (!buffer)
102     return 1;
103
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))
132                 {
133                   free (buffer);
134                   return 1;
135                 }
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);
160   free (buffer);
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 }