1 /*
2 * crc.c --
3 *
4 * Implements and registers message digest generator CRC.
5 *
6 *
7 * Copyright (c) 1996 Andreas Kupries (andreas_kupries@users.sourceforge.net)
8 * All rights reserved.
9 *
10 * Permission is hereby granted, without written agreement and without
11 * license or royalty fees, to use, copy, modify, and distribute this
12 * software and its documentation for any purpose, provided that the
13 * above copyright notice and the following two paragraphs appear in
14 * all copies of this software.
15 *
16 * IN NO EVENT SHALL I LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
17 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
18 * SOFTWARE AND ITS DOCUMENTATION, EVEN IF I HAVE BEEN ADVISED OF THE
19 * POSSIBILITY OF SUCH DAMAGE.
20 *
21 * I SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
24 * I HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
25 * ENHANCEMENTS, OR MODIFICATIONS.
26 *
27 * CVS: $Id: crc.c,v 1.4 2000/08/09 19:13:17 aku Exp $
28 */
29
30 #include "transformInt.h"
31 #include "crc.h"
32
33 /*
34 * Generator description
35 * ---------------------
36 *
37 * The CRC algorithm is used to compute a message digest.
38 * The polynomial is taken from PGP (parts of the code too).
39 */
40
41 #define DIGEST_SIZE (CRCBYTES)
42 #define CTX_TYPE crcword
43
44 /*
45 * Declarations of internal procedures.
46 */
47
48 static void MDcrc_Start _ANSI_ARGS_ ((VOID* context));
49 static void MDcrc_Update _ANSI_ARGS_ ((VOID* context, unsigned int character));
50 static void MDcrc_UpdateBuf _ANSI_ARGS_ ((VOID* context, unsigned char* buffer, size_t bufLen));
51 static void MDcrc_Final _ANSI_ARGS_ ((VOID* digest, VOID* context));
52
53 /*
54 * Generator definition.
55 */
56
57 static Trf_MessageDigestDescription mdDescription = {
58 "crc",
59 sizeof (CTX_TYPE),
60 DIGEST_SIZE,
61 MDcrc_Start,
62 MDcrc_Update,
63 MDcrc_UpdateBuf,
64 MDcrc_Final,
65 NULL
66 };
67
68 /*
69 * Additional declarations
70 */
71
72 static crcword CrcTable [256]; /* THREADING: serialize initialization */
73
74 static void
75 GenCrcLookupTable _ANSI_ARGS_ ((crcword polynomial));
76
77 /*
78 *------------------------------------------------------*
79 *
80 * TrfInit_CRC --
81 *
82 * ------------------------------------------------*
83 * Register the generator implemented in this file.
84 * ------------------------------------------------*
85 *
86 * Sideeffects:
87 * As of 'Trf_Register'.
88 *
89 * Result:
90 * A standard Tcl error code.
91 *
92 *------------------------------------------------------*
93 */
94
95 int
TrfInit_CRC(interp)96 TrfInit_CRC (interp)
97 Tcl_Interp* interp;
98 {
99 GenCrcLookupTable (PRZCRC);
100
101 return Trf_RegisterMessageDigest (interp, &mdDescription);
102 }
103
104 /*
105 *------------------------------------------------------*
106 *
107 * MDcrc_Start --
108 *
109 * ------------------------------------------------*
110 * Initialize the internal state of the message
111 * digest generator.
112 * ------------------------------------------------*
113 *
114 * Sideeffects:
115 * As of the called procedure.
116 *
117 * Result:
118 * None.
119 *
120 *------------------------------------------------------*
121 */
122
123 static void
MDcrc_Start(context)124 MDcrc_Start (context)
125 VOID* context;
126 {
127 /* call md specific initialization here */
128
129 *((crcword*) context) = CRCINIT;
130 }
131
132 /*
133 *------------------------------------------------------*
134 *
135 * MDcrc_Update --
136 *
137 * ------------------------------------------------*
138 * Update the internal state of the message digest
139 * generator for a single character.
140 * ------------------------------------------------*
141 *
142 * Sideeffects:
143 * As of the called procedure.
144 *
145 * Result:
146 * None.
147 *
148 *------------------------------------------------------*
149 */
150
151 static void
MDcrc_Update(context,character)152 MDcrc_Update (context, character)
153 VOID* context;
154 unsigned int character;
155 {
156 /* call md specific update here */
157 #define UP(ctx) ((ctx) << 8)
158 #define DOWN(ctx) ((ctx) >> CRCSHIFTS)
159
160 crcword accu;
161 unsigned char buf = character;
162
163 accu = *((crcword*) context);
164 accu = UP (accu) ^ CrcTable [(unsigned char) (DOWN (accu)) ^ buf];
165
166 *((crcword*) context) = accu;
167
168 #undef UP
169 #undef DOWN
170 }
171
172 /*
173 *------------------------------------------------------*
174 *
175 * MDcrc_UpdateBuf --
176 *
177 * ------------------------------------------------*
178 * Update the internal state of the message digest
179 * generator for a character buffer.
180 * ------------------------------------------------*
181 *
182 * Sideeffects:
183 * As of the called procedure.
184 *
185 * Result:
186 * None.
187 *
188 *------------------------------------------------------*
189 */
190
191 static void
MDcrc_UpdateBuf(context,buffer,bufLen)192 MDcrc_UpdateBuf (context, buffer, bufLen)
193 VOID* context;
194 unsigned char* buffer;
195 size_t bufLen;
196 {
197 /* call md specific update here */
198 #define UP(ctx) ((ctx) << 8)
199 #define DOWN(ctx) ((ctx) >> CRCSHIFTS)
200
201 crcword accu;
202 int i;
203
204 accu = *((crcword*) context);
205
206 for (i=0; i < bufLen; i++) {
207 accu = UP (accu) ^ CrcTable [(unsigned char) (DOWN (accu)) ^ (buffer [i])];
208 }
209
210 *((crcword*) context) = accu;
211
212 #undef UP
213 #undef DOWN
214 }
215
216 /*
217 *------------------------------------------------------*
218 *
219 * MDcrc_Final --
220 *
221 * ------------------------------------------------*
222 * Generate the digest from the internal state of
223 * the message digest generator.
224 * ------------------------------------------------*
225 *
226 * Sideeffects:
227 * As of the called procedure.
228 *
229 * Result:
230 * None.
231 *
232 *------------------------------------------------------*
233 */
234
235 static void
MDcrc_Final(digest,context)236 MDcrc_Final (digest, context)
237 VOID* context;
238 VOID* digest;
239 {
240 /* call md specific finalization here */
241
242 crcword crc = maskcrc (* ((crcword*) context));
243 char* out = (char*) digest;
244
245 /* -*- PGP -*-, was outcrc, BIGENDIAN output */
246 /* DEPENDENT on CRCBYTES !!, only a value of 3 is supported here */
247
248 out [0] = (char) ((crc >> 16) & 0xff);
249 out [1] = (char) ((crc >> 8) & 0xff);
250 out [2] = (char) ((crc >> 0) & 0xff);
251 /* -*- PGP -*- */
252 }
253
254 /*
255 * Initialize lookup table for crc calculation.
256 */
257
258 static void
GenCrcLookupTable(poly)259 GenCrcLookupTable (poly)
260 crcword poly;
261 {
262 /* -*- PGP -*-, was 'mk_crctbl' */
263 int i;
264 crcword t, *p, *q;
265
266 TrfLock; /* THREADING: serialize initialization */
267
268 p = q = CrcTable;
269
270 *q++ = 0;
271 *q++ = poly;
272
273 for (i = 1; i < 128; i++)
274 {
275 t = *++p;
276 if (t & CRCHIBIT)
277 {
278 t <<= 1;
279 *q++ = t ^ poly;
280 *q++ = t;
281 }
282 else
283 {
284 t <<= 1;
285 *q++ = t;
286 *q++ = t ^ poly;
287 }
288 }
289
290 TrfUnlock;
291 /* -*- PGP -*- */
292 }
293