cb4c63b2b7d8a86dafff3c6b5514ff4e13cff925
[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,2008
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
23 #include <config.h>
24
25 #include "md2.h"
26
27 #include <string.h>
28 #include <sys/types.h>
29
30 #include <minmax.h>
31
32 #if USE_UNLOCKED_IO
33 # include "unlocked-io.h"
34 #endif
35
36 #define BLOCKSIZE 4096
37 #if BLOCKSIZE % 64 != 0
38 # error "invalid BLOCKSIZE"
39 #endif
40
41 static void md2_update_chksum (struct md2_ctx *md);
42 static void md2_compress (struct md2_ctx *md);
43
44 /* Initialize structure containing state of computation.
45    (RFC 1319, 3.3: Step 3)  */
46 void
47 md2_init_ctx (struct md2_ctx *ctx)
48 {
49   memset (ctx->X, 0, sizeof (ctx->X));
50   memset (ctx->chksum, 0, sizeof (ctx->chksum));
51   memset (ctx->buf, 0, sizeof (ctx->buf));
52   ctx->curlen = 0;
53 }
54
55 /* Put result from CTX in first 16 bytes following RESBUF.  The result
56    must be in little endian byte order.  */
57 void *
58 md2_read_ctx (const struct md2_ctx *ctx, void *resbuf)
59 {
60   memcpy (resbuf, ctx->X, 16);
61
62   return resbuf;
63 }
64
65 /* Process the remaining bytes in the internal buffer and the usual
66    prolog according to the standard and write the result to RESBUF.  */
67 void *
68 md2_finish_ctx (struct md2_ctx *ctx, void *resbuf)
69 {
70   unsigned long i, k;
71
72   /* pad the message */
73   k = 16 - ctx->curlen;
74   for (i = ctx->curlen; i < 16; i++)
75     {
76       ctx->buf[i] = (unsigned char) k;
77     }
78
79   /* hash and update */
80   md2_compress (ctx);
81   md2_update_chksum (ctx);
82
83   /* hash checksum */
84   memcpy (ctx->buf, ctx->chksum, 16);
85   md2_compress (ctx);
86
87   return md2_read_ctx (ctx, resbuf);
88 }
89
90 /* Compute MD2 message digest for bytes read from STREAM.  The
91    resulting message digest number will be written into the 16 bytes
92    beginning at RESBLOCK.  */
93 int
94 md2_stream (FILE *stream, void *resblock)
95 {
96   struct md2_ctx ctx;
97   char buffer[BLOCKSIZE + 72];
98   size_t sum;
99
100   /* Initialize the computation context.  */
101   md2_init_ctx (&ctx);
102
103   /* Iterate over full file contents.  */
104   while (1)
105     {
106       /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
107          computation function processes the whole buffer so that with the
108          next round of the loop another block can be read.  */
109       size_t n;
110       sum = 0;
111
112       /* Read block.  Take care for partial reads.  */
113       while (1)
114         {
115           n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
116
117           sum += n;
118
119           if (sum == BLOCKSIZE)
120             break;
121
122           if (n == 0)
123             {
124               /* Check for the error flag IFF N == 0, so that we don't
125                  exit the loop after a partial read due to e.g., EAGAIN
126                  or EWOULDBLOCK.  */
127               if (ferror (stream))
128                 return 1;
129               goto process_partial_block;
130             }
131
132           /* We've read at least one byte, so ignore errors.  But always
133              check for EOF, since feof may be true even though N > 0.
134              Otherwise, we could end up calling fread after EOF.  */
135           if (feof (stream))
136             goto process_partial_block;
137         }
138
139       /* Process buffer with BLOCKSIZE bytes.  Note that
140          BLOCKSIZE % 64 == 0
141        */
142       md2_process_block (buffer, BLOCKSIZE, &ctx);
143     }
144
145 process_partial_block:;
146
147   /* Process any remaining bytes.  */
148   if (sum > 0)
149     md2_process_bytes (buffer, sum, &ctx);
150
151   /* Construct result in desired memory.  */
152   md2_finish_ctx (&ctx, resblock);
153   return 0;
154 }
155
156 /* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
157    result is always in little endian byte order, so that a byte-wise
158    output yields to the wanted ASCII representation of the message
159    digest.  */
160 void *
161 md2_buffer (const char *buffer, size_t len, void *resblock)
162 {
163   struct md2_ctx ctx;
164
165   /* Initialize the computation context.  */
166   md2_init_ctx (&ctx);
167
168   /* Process whole buffer but last len % 64 bytes.  */
169   md2_process_block (buffer, len, &ctx);
170
171   /* Put result in desired memory area.  */
172   return md2_finish_ctx (&ctx, resblock);
173 }
174
175 void
176 md2_process_bytes (const void *buffer, size_t len, struct md2_ctx *ctx)
177 {
178   const char *in = buffer;
179   unsigned long n;
180
181   while (len > 0)
182     {
183       n = MIN (len, (16 - ctx->curlen));
184       memcpy (ctx->buf + ctx->curlen, in, (size_t) n);
185       ctx->curlen += n;
186       in += n;
187       len -= n;
188
189       /* is 16 bytes full? */
190       if (ctx->curlen == 16)
191         {
192           md2_compress (ctx);
193           md2_update_chksum (ctx);
194           ctx->curlen = 0;
195         }
196     }
197 }
198
199 static const unsigned char PI_SUBST[256] = {
200   41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
201   19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
202   76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
203   138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
204   245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
205   148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
206   39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
207   181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
208   150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
209   112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
210   96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
211   85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
212   234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
213   129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
214   8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
215   203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
216   166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
217   31, 26, 219, 153, 141, 51, 159, 17, 131, 20
218 };
219
220 /* adds 16 bytes to the checksum */
221 static void
222 md2_update_chksum (struct md2_ctx *ctx)
223 {
224   int j;
225   unsigned char L;
226
227   L = ctx->chksum[15];
228   for (j = 0; j < 16; j++)
229     {
230       /* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the
231          reference source code [and test vectors] say otherwise. */
232       L = (ctx->chksum[j] ^= PI_SUBST[(int) (ctx->buf[j] ^ L)] & 255);
233     }
234 }
235
236 static void
237 md2_compress (struct md2_ctx *ctx)
238 {
239   size_t j, k;
240   unsigned char t;
241
242   /* copy block */
243   for (j = 0; j < 16; j++)
244     {
245       ctx->X[16 + j] = ctx->buf[j];
246       ctx->X[32 + j] = ctx->X[j] ^ ctx->X[16 + j];
247     }
248
249   t = (unsigned char) 0;
250
251   /* do 18 rounds */
252   for (j = 0; j < 18; j++)
253     {
254       for (k = 0; k < 48; k++)
255         {
256           t = (ctx->X[k] ^= PI_SUBST[(int) (t & 255)]);
257         }
258       t = (t + (unsigned char) j) & 255;
259     }
260 }
261
262 /* Process LEN bytes of BUFFER, accumulating context into CTX.  */
263 void
264 md2_process_block (const void *buffer, size_t len, struct md2_ctx *ctx)
265 {
266   md2_process_bytes (buffer, len, ctx);
267 }