Updated `NEWS'.
[gnutls.git] / lgl / md2.c
blob63033ef56895c1ceb7805e762916f16df5ea1b8b
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.
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2.1, or (at your option) any
9 later version.
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 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser 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. */
20 /* Adapted by Simon Josefsson from public domain Libtomcrypt 1.06 by
21 Tom St Denis. */
23 #include <config.h>
25 #include "md2.h"
27 #include <string.h>
28 #include <sys/types.h>
30 #include <minmax.h>
32 #if USE_UNLOCKED_IO
33 # include "unlocked-io.h"
34 #endif
36 #define BLOCKSIZE 4096
37 #if BLOCKSIZE % 64 != 0
38 # error "invalid BLOCKSIZE"
39 #endif
41 static void md2_update_chksum (struct md2_ctx *md);
42 static void md2_compress (struct md2_ctx *md);
44 /* Initialize structure containing state of computation.
45 (RFC 1319, 3.3: Step 3) */
46 void
47 md2_init_ctx (struct md2_ctx *ctx)
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;
55 /* Put result from CTX in first 16 bytes following RESBUF. The result
56 must be in little endian byte order.
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)
63 memcpy (resbuf, ctx->X, 16);
65 return resbuf;
68 /* Process the remaining bytes in the internal buffer and the usual
69 prolog according to the standard and write the result to RESBUF.
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)
76 unsigned long i, k;
78 /* pad the message */
79 k = 16 - ctx->curlen;
80 for (i = ctx->curlen; i < 16; i++)
82 ctx->buf[i] = (unsigned char) k;
85 /* hash and update */
86 md2_compress (ctx);
87 md2_update_chksum (ctx);
89 /* hash checksum */
90 memcpy (ctx->buf, ctx->chksum, 16);
91 md2_compress (ctx);
93 return md2_read_ctx (ctx, resbuf);
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)
102 struct md2_ctx ctx;
103 char buffer[BLOCKSIZE + 72];
104 size_t sum;
106 /* Initialize the computation context. */
107 md2_init_ctx (&ctx);
109 /* Iterate over full file contents. */
110 while (1)
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;
118 /* Read block. Take care for partial reads. */
119 while (1)
121 n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
123 sum += n;
125 if (sum == BLOCKSIZE)
126 break;
128 if (n == 0)
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;
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;
145 /* Process buffer with BLOCKSIZE bytes. Note that
146 BLOCKSIZE % 64 == 0
148 md2_process_block (buffer, BLOCKSIZE, &ctx);
151 process_partial_block:;
153 /* Process any remaining bytes. */
154 if (sum > 0)
155 md2_process_bytes (buffer, sum, &ctx);
157 /* Construct result in desired memory. */
158 md2_finish_ctx (&ctx, resblock);
159 return 0;
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)
169 struct md2_ctx ctx;
171 /* Initialize the computation context. */
172 md2_init_ctx (&ctx);
174 /* Process whole buffer but last len % 64 bytes. */
175 md2_process_block (buffer, len, &ctx);
177 /* Put result in desired memory area. */
178 return md2_finish_ctx (&ctx, resblock);
181 void
182 md2_process_bytes (const void *buffer, size_t len, struct md2_ctx *ctx)
184 const char *in = buffer;
185 unsigned long n;
187 while (len > 0)
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;
195 /* is 16 bytes full? */
196 if (ctx->curlen == 16)
198 md2_compress (ctx);
199 md2_update_chksum (ctx);
200 ctx->curlen = 0;
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
226 /* adds 16 bytes to the checksum */
227 static void
228 md2_update_chksum (struct md2_ctx *ctx)
230 int j;
231 unsigned char L;
233 L = ctx->chksum[15];
234 for (j = 0; j < 16; j++)
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);
242 static void
243 md2_compress (struct md2_ctx *ctx)
245 size_t j, k;
246 unsigned char t;
248 /* copy block */
249 for (j = 0; j < 16; j++)
251 ctx->X[16 + j] = ctx->buf[j];
252 ctx->X[32 + j] = ctx->X[j] ^ ctx->X[16 + j];
255 t = (unsigned char) 0;
257 /* do 18 rounds */
258 for (j = 0; j < 18; j++)
260 for (k = 0; k < 48; k++)
262 t = (ctx->X[k] ^= PI_SUBST[(int) (t & 255)]);
264 t = (t + (unsigned char) j) & 255;
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)
272 md2_process_bytes (buffer, len, ctx);