exp2l: Work around a NetBSD 10.0/i386 bug.
[gnulib.git] / lib / md2.c
blob28fff1f133e04aa10bd2efd2a49fa519f75f25bd
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-2024 Free Software
4 Foundation, Inc.
6 This file is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 This file 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, 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 /* Specification. */
25 #include "md2.h"
27 #include <string.h>
28 #include <sys/types.h>
30 #include <minmax.h>
32 static void md2_update_chksum (struct md2_ctx *md);
33 static void md2_compress (struct md2_ctx *md);
35 /* Initialize structure containing state of computation.
36 (RFC 1319, 3.3: Step 3) */
37 void
38 md2_init_ctx (struct md2_ctx *ctx)
40 memset (ctx->X, 0, sizeof (ctx->X));
41 memset (ctx->chksum, 0, sizeof (ctx->chksum));
42 memset (ctx->buf, 0, sizeof (ctx->buf));
43 ctx->curlen = 0;
46 /* Put result from CTX in first 16 bytes following RESBUF. The result
47 must be in little endian byte order. */
48 void *
49 md2_read_ctx (const struct md2_ctx *ctx, void *resbuf)
51 memcpy (resbuf, ctx->X, 16);
53 return resbuf;
56 /* Process the remaining bytes in the internal buffer and the usual
57 prolog according to the standard and write the result to RESBUF. */
58 void *
59 md2_finish_ctx (struct md2_ctx *ctx, void *resbuf)
61 unsigned long i, k;
63 /* pad the message */
64 k = 16 - ctx->curlen;
65 for (i = ctx->curlen; i < 16; i++)
67 ctx->buf[i] = (unsigned char) k;
70 /* hash and update */
71 md2_compress (ctx);
72 md2_update_chksum (ctx);
74 /* hash checksum */
75 memcpy (ctx->buf, ctx->chksum, 16);
76 md2_compress (ctx);
78 return md2_read_ctx (ctx, resbuf);
81 /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
82 result is always in little endian byte order, so that a byte-wise
83 output yields to the wanted ASCII representation of the message
84 digest. */
85 void *
86 md2_buffer (const char *buffer, size_t len, void *resblock)
88 struct md2_ctx ctx;
90 /* Initialize the computation context. */
91 md2_init_ctx (&ctx);
93 /* Process whole buffer but last len % 64 bytes. */
94 md2_process_block (buffer, len, &ctx);
96 /* Put result in desired memory area. */
97 return md2_finish_ctx (&ctx, resblock);
100 void
101 md2_process_bytes (const void *buffer, size_t len, struct md2_ctx *ctx)
103 const char *in = buffer;
104 unsigned long n;
106 while (len > 0)
108 n = MIN (len, (16 - ctx->curlen));
109 memcpy (ctx->buf + ctx->curlen, in, (size_t) n);
110 ctx->curlen += n;
111 in += n;
112 len -= n;
114 /* is 16 bytes full? */
115 if (ctx->curlen == 16)
117 md2_compress (ctx);
118 md2_update_chksum (ctx);
119 ctx->curlen = 0;
124 static const unsigned char PI_SUBST[256] = {
125 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
126 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
127 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
128 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
129 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
130 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
131 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
132 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
133 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
134 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
135 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
136 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
137 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
138 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
139 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
140 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
141 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
142 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
145 /* adds 16 bytes to the checksum */
146 static void
147 md2_update_chksum (struct md2_ctx *ctx)
149 int j;
150 unsigned char L;
152 L = ctx->chksum[15];
153 for (j = 0; j < 16; j++)
155 /* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the
156 reference source code [and test vectors] say otherwise. */
157 L = (ctx->chksum[j] ^= PI_SUBST[(int) (ctx->buf[j] ^ L)] & 255);
161 static void
162 md2_compress (struct md2_ctx *ctx)
164 size_t j, k;
165 unsigned char t;
167 /* copy block */
168 for (j = 0; j < 16; j++)
170 ctx->X[16 + j] = ctx->buf[j];
171 ctx->X[32 + j] = ctx->X[j] ^ ctx->X[16 + j];
174 t = (unsigned char) 0;
176 /* do 18 rounds */
177 for (j = 0; j < 18; j++)
179 for (k = 0; k < 48; k++)
181 t = (ctx->X[k] ^= PI_SUBST[(int) (t & 255)]);
183 t = (t + (unsigned char) j) & 255;
187 /* Process LEN bytes of BUFFER, accumulating context into CTX. */
188 void
189 md2_process_block (const void *buffer, size_t len, struct md2_ctx *ctx)
191 md2_process_bytes (buffer, len, ctx);