uchar C++ tests: Fix build error on FreeBSD 12.
[gnulib.git] / lib / md2.c
blob7cb5a33d617c83190b8df6367d549724899f57b8
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-2020 Free Software
4 Foundation, Inc.
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.
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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <https://www.gnu.org/licenses/>. */
19 /* Adapted by Simon Josefsson from public domain Libtomcrypt 1.06 by
20 Tom St Denis. */
22 #include <config.h>
24 #include "md2.h"
26 #include <stdlib.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 32768
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. */
57 void *
58 md2_read_ctx (const struct md2_ctx *ctx, void *resbuf)
60 memcpy (resbuf, ctx->X, 16);
62 return resbuf;
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)
70 unsigned long i, k;
72 /* pad the message */
73 k = 16 - ctx->curlen;
74 for (i = ctx->curlen; i < 16; i++)
76 ctx->buf[i] = (unsigned char) k;
79 /* hash and update */
80 md2_compress (ctx);
81 md2_update_chksum (ctx);
83 /* hash checksum */
84 memcpy (ctx->buf, ctx->chksum, 16);
85 md2_compress (ctx);
87 return md2_read_ctx (ctx, resbuf);
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)
96 struct md2_ctx ctx;
97 size_t sum;
99 char *buffer = malloc (BLOCKSIZE + 72);
100 if (!buffer)
101 return 1;
103 /* Initialize the computation context. */
104 md2_init_ctx (&ctx);
106 /* Iterate over full file contents. */
107 while (1)
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;
115 /* Read block. Take care for partial reads. */
116 while (1)
118 n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
120 sum += n;
122 if (sum == BLOCKSIZE)
123 break;
125 if (n == 0)
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))
132 free (buffer);
133 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 free (buffer);
160 return 0;
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)
170 struct md2_ctx ctx;
172 /* Initialize the computation context. */
173 md2_init_ctx (&ctx);
175 /* Process whole buffer but last len % 64 bytes. */
176 md2_process_block (buffer, len, &ctx);
178 /* Put result in desired memory area. */
179 return md2_finish_ctx (&ctx, resblock);
182 void
183 md2_process_bytes (const void *buffer, size_t len, struct md2_ctx *ctx)
185 const char *in = buffer;
186 unsigned long n;
188 while (len > 0)
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;
196 /* is 16 bytes full? */
197 if (ctx->curlen == 16)
199 md2_compress (ctx);
200 md2_update_chksum (ctx);
201 ctx->curlen = 0;
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
227 /* adds 16 bytes to the checksum */
228 static void
229 md2_update_chksum (struct md2_ctx *ctx)
231 int j;
232 unsigned char L;
234 L = ctx->chksum[15];
235 for (j = 0; j < 16; j++)
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);
243 static void
244 md2_compress (struct md2_ctx *ctx)
246 size_t j, k;
247 unsigned char t;
249 /* copy block */
250 for (j = 0; j < 16; j++)
252 ctx->X[16 + j] = ctx->buf[j];
253 ctx->X[32 + j] = ctx->X[j] ^ ctx->X[16 + j];
256 t = (unsigned char) 0;
258 /* do 18 rounds */
259 for (j = 0; j < 18; j++)
261 for (k = 0; k < 48; k++)
263 t = (ctx->X[k] ^= PI_SUBST[(int) (t & 255)]);
265 t = (t + (unsigned char) j) & 255;
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)
273 md2_process_bytes (buffer, len, ctx);