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