1/* 2 * crc.c -- 3 * 4 * Implements and registers message digest generator CRC. 5 * 6 * 7 * Copyright (c) 1996 Andreas Kupries (a.kupries@westend.com) 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 48static void MDcrc_Start _ANSI_ARGS_ ((VOID* context)); 49static void MDcrc_Update _ANSI_ARGS_ ((VOID* context, unsigned int character)); 50static void MDcrc_UpdateBuf _ANSI_ARGS_ ((VOID* context, unsigned char* buffer, int bufLen)); 51static void MDcrc_Final _ANSI_ARGS_ ((VOID* context, VOID* digest)); 52 53/* 54 * Generator definition. 55 */ 56 57static 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 72static crcword CrcTable [256]; /* THREADING: serialize initialization */ 73 74static void 75GenCrcLookupTable _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 95int 96TrfInit_CRC (interp) 97Tcl_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 123static void 124MDcrc_Start (context) 125VOID* 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 151static void 152MDcrc_Update (context, character) 153VOID* context; 154unsigned 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 191static void 192MDcrc_UpdateBuf (context, buffer, bufLen) 193VOID* context; 194unsigned char* buffer; 195int 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 235static void 236MDcrc_Final (context, digest) 237VOID* context; 238VOID* 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 258static void 259GenCrcLookupTable (poly) 260crcword 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