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