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