1*4a5d661aSToomas Soome /* crc32.c -- compute the CRC-32 of a data stream 2*4a5d661aSToomas Soome * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler 3*4a5d661aSToomas Soome * For conditions of distribution and use, see copyright notice in zlib.h 4*4a5d661aSToomas Soome * 5*4a5d661aSToomas Soome * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster 6*4a5d661aSToomas Soome * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing 7*4a5d661aSToomas Soome * tables for updating the shift register in one step with three exclusive-ors 8*4a5d661aSToomas Soome * instead of four steps with four exclusive-ors. This results in about a 9*4a5d661aSToomas Soome * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. 10*4a5d661aSToomas Soome */ 11*4a5d661aSToomas Soome 12*4a5d661aSToomas Soome /* @(#) $Id$ */ 13*4a5d661aSToomas Soome 14*4a5d661aSToomas Soome /* 15*4a5d661aSToomas Soome Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore 16*4a5d661aSToomas Soome protection on the static variables used to control the first-use generation 17*4a5d661aSToomas Soome of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should 18*4a5d661aSToomas Soome first call get_crc_table() to initialize the tables before allowing more than 19*4a5d661aSToomas Soome one thread to use crc32(). 20*4a5d661aSToomas Soome 21*4a5d661aSToomas Soome DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. 22*4a5d661aSToomas Soome */ 23*4a5d661aSToomas Soome 24*4a5d661aSToomas Soome #ifdef MAKECRCH 25*4a5d661aSToomas Soome # include <stdio.h> 26*4a5d661aSToomas Soome # ifndef DYNAMIC_CRC_TABLE 27*4a5d661aSToomas Soome # define DYNAMIC_CRC_TABLE 28*4a5d661aSToomas Soome # endif /* !DYNAMIC_CRC_TABLE */ 29*4a5d661aSToomas Soome #endif /* MAKECRCH */ 30*4a5d661aSToomas Soome 31*4a5d661aSToomas Soome #include "zutil.h" /* for STDC and FAR definitions */ 32*4a5d661aSToomas Soome 33*4a5d661aSToomas Soome #define local static 34*4a5d661aSToomas Soome 35*4a5d661aSToomas Soome /* Definitions for doing the crc four data bytes at a time. */ 36*4a5d661aSToomas Soome #if !defined(NOBYFOUR) && defined(Z_U4) 37*4a5d661aSToomas Soome # define BYFOUR 38*4a5d661aSToomas Soome #endif 39*4a5d661aSToomas Soome #ifdef BYFOUR 40*4a5d661aSToomas Soome local unsigned long crc32_little OF((unsigned long, 41*4a5d661aSToomas Soome const unsigned char FAR *, unsigned)); 42*4a5d661aSToomas Soome local unsigned long crc32_big OF((unsigned long, 43*4a5d661aSToomas Soome const unsigned char FAR *, unsigned)); 44*4a5d661aSToomas Soome # define TBLS 8 45*4a5d661aSToomas Soome #else 46*4a5d661aSToomas Soome # define TBLS 1 47*4a5d661aSToomas Soome #endif /* BYFOUR */ 48*4a5d661aSToomas Soome 49*4a5d661aSToomas Soome /* Local functions for crc concatenation */ 50*4a5d661aSToomas Soome local unsigned long gf2_matrix_times OF((unsigned long *mat, 51*4a5d661aSToomas Soome unsigned long vec)); 52*4a5d661aSToomas Soome local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); 53*4a5d661aSToomas Soome local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); 54*4a5d661aSToomas Soome 55*4a5d661aSToomas Soome 56*4a5d661aSToomas Soome #ifdef DYNAMIC_CRC_TABLE 57*4a5d661aSToomas Soome 58*4a5d661aSToomas Soome local volatile int crc_table_empty = 1; 59*4a5d661aSToomas Soome local z_crc_t FAR crc_table[TBLS][256]; 60*4a5d661aSToomas Soome local void make_crc_table OF((void)); 61*4a5d661aSToomas Soome #ifdef MAKECRCH 62*4a5d661aSToomas Soome local void write_table OF((FILE *, const z_crc_t FAR *)); 63*4a5d661aSToomas Soome #endif /* MAKECRCH */ 64*4a5d661aSToomas Soome /* 65*4a5d661aSToomas Soome Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: 66*4a5d661aSToomas Soome x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. 67*4a5d661aSToomas Soome 68*4a5d661aSToomas Soome Polynomials over GF(2) are represented in binary, one bit per coefficient, 69*4a5d661aSToomas Soome with the lowest powers in the most significant bit. Then adding polynomials 70*4a5d661aSToomas Soome is just exclusive-or, and multiplying a polynomial by x is a right shift by 71*4a5d661aSToomas Soome one. If we call the above polynomial p, and represent a byte as the 72*4a5d661aSToomas Soome polynomial q, also with the lowest power in the most significant bit (so the 73*4a5d661aSToomas Soome byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, 74*4a5d661aSToomas Soome where a mod b means the remainder after dividing a by b. 75*4a5d661aSToomas Soome 76*4a5d661aSToomas Soome This calculation is done using the shift-register method of multiplying and 77*4a5d661aSToomas Soome taking the remainder. The register is initialized to zero, and for each 78*4a5d661aSToomas Soome incoming bit, x^32 is added mod p to the register if the bit is a one (where 79*4a5d661aSToomas Soome x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by 80*4a5d661aSToomas Soome x (which is shifting right by one and adding x^32 mod p if the bit shifted 81*4a5d661aSToomas Soome out is a one). We start with the highest power (least significant bit) of 82*4a5d661aSToomas Soome q and repeat for all eight bits of q. 83*4a5d661aSToomas Soome 84*4a5d661aSToomas Soome The first table is simply the CRC of all possible eight bit values. This is 85*4a5d661aSToomas Soome all the information needed to generate CRCs on data a byte at a time for all 86*4a5d661aSToomas Soome combinations of CRC register values and incoming bytes. The remaining tables 87*4a5d661aSToomas Soome allow for word-at-a-time CRC calculation for both big-endian and little- 88*4a5d661aSToomas Soome endian machines, where a word is four bytes. 89*4a5d661aSToomas Soome */ 90*4a5d661aSToomas Soome local void make_crc_table() 91*4a5d661aSToomas Soome { 92*4a5d661aSToomas Soome z_crc_t c; 93*4a5d661aSToomas Soome int n, k; 94*4a5d661aSToomas Soome z_crc_t poly; /* polynomial exclusive-or pattern */ 95*4a5d661aSToomas Soome /* terms of polynomial defining this crc (except x^32): */ 96*4a5d661aSToomas Soome static volatile int first = 1; /* flag to limit concurrent making */ 97*4a5d661aSToomas Soome static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; 98*4a5d661aSToomas Soome 99*4a5d661aSToomas Soome /* See if another task is already doing this (not thread-safe, but better 100*4a5d661aSToomas Soome than nothing -- significantly reduces duration of vulnerability in 101*4a5d661aSToomas Soome case the advice about DYNAMIC_CRC_TABLE is ignored) */ 102*4a5d661aSToomas Soome if (first) { 103*4a5d661aSToomas Soome first = 0; 104*4a5d661aSToomas Soome 105*4a5d661aSToomas Soome /* make exclusive-or pattern from polynomial (0xedb88320UL) */ 106*4a5d661aSToomas Soome poly = 0; 107*4a5d661aSToomas Soome for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) 108*4a5d661aSToomas Soome poly |= (z_crc_t)1 << (31 - p[n]); 109*4a5d661aSToomas Soome 110*4a5d661aSToomas Soome /* generate a crc for every 8-bit value */ 111*4a5d661aSToomas Soome for (n = 0; n < 256; n++) { 112*4a5d661aSToomas Soome c = (z_crc_t)n; 113*4a5d661aSToomas Soome for (k = 0; k < 8; k++) 114*4a5d661aSToomas Soome c = c & 1 ? poly ^ (c >> 1) : c >> 1; 115*4a5d661aSToomas Soome crc_table[0][n] = c; 116*4a5d661aSToomas Soome } 117*4a5d661aSToomas Soome 118*4a5d661aSToomas Soome #ifdef BYFOUR 119*4a5d661aSToomas Soome /* generate crc for each value followed by one, two, and three zeros, 120*4a5d661aSToomas Soome and then the byte reversal of those as well as the first table */ 121*4a5d661aSToomas Soome for (n = 0; n < 256; n++) { 122*4a5d661aSToomas Soome c = crc_table[0][n]; 123*4a5d661aSToomas Soome crc_table[4][n] = ZSWAP32(c); 124*4a5d661aSToomas Soome for (k = 1; k < 4; k++) { 125*4a5d661aSToomas Soome c = crc_table[0][c & 0xff] ^ (c >> 8); 126*4a5d661aSToomas Soome crc_table[k][n] = c; 127*4a5d661aSToomas Soome crc_table[k + 4][n] = ZSWAP32(c); 128*4a5d661aSToomas Soome } 129*4a5d661aSToomas Soome } 130*4a5d661aSToomas Soome #endif /* BYFOUR */ 131*4a5d661aSToomas Soome 132*4a5d661aSToomas Soome crc_table_empty = 0; 133*4a5d661aSToomas Soome } 134*4a5d661aSToomas Soome else { /* not first */ 135*4a5d661aSToomas Soome /* wait for the other guy to finish (not efficient, but rare) */ 136*4a5d661aSToomas Soome while (crc_table_empty) 137*4a5d661aSToomas Soome ; 138*4a5d661aSToomas Soome } 139*4a5d661aSToomas Soome 140*4a5d661aSToomas Soome #ifdef MAKECRCH 141*4a5d661aSToomas Soome /* write out CRC tables to crc32.h */ 142*4a5d661aSToomas Soome { 143*4a5d661aSToomas Soome FILE *out; 144*4a5d661aSToomas Soome 145*4a5d661aSToomas Soome out = fopen("crc32.h", "w"); 146*4a5d661aSToomas Soome if (out == NULL) return; 147*4a5d661aSToomas Soome fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); 148*4a5d661aSToomas Soome fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); 149*4a5d661aSToomas Soome fprintf(out, "local const z_crc_t FAR "); 150*4a5d661aSToomas Soome fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); 151*4a5d661aSToomas Soome write_table(out, crc_table[0]); 152*4a5d661aSToomas Soome # ifdef BYFOUR 153*4a5d661aSToomas Soome fprintf(out, "#ifdef BYFOUR\n"); 154*4a5d661aSToomas Soome for (k = 1; k < 8; k++) { 155*4a5d661aSToomas Soome fprintf(out, " },\n {\n"); 156*4a5d661aSToomas Soome write_table(out, crc_table[k]); 157*4a5d661aSToomas Soome } 158*4a5d661aSToomas Soome fprintf(out, "#endif\n"); 159*4a5d661aSToomas Soome # endif /* BYFOUR */ 160*4a5d661aSToomas Soome fprintf(out, " }\n};\n"); 161*4a5d661aSToomas Soome fclose(out); 162*4a5d661aSToomas Soome } 163*4a5d661aSToomas Soome #endif /* MAKECRCH */ 164*4a5d661aSToomas Soome } 165*4a5d661aSToomas Soome 166*4a5d661aSToomas Soome #ifdef MAKECRCH 167*4a5d661aSToomas Soome local void write_table(out, table) 168*4a5d661aSToomas Soome FILE *out; 169*4a5d661aSToomas Soome const z_crc_t FAR *table; 170*4a5d661aSToomas Soome { 171*4a5d661aSToomas Soome int n; 172*4a5d661aSToomas Soome 173*4a5d661aSToomas Soome for (n = 0; n < 256; n++) 174*4a5d661aSToomas Soome fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", 175*4a5d661aSToomas Soome (unsigned long)(table[n]), 176*4a5d661aSToomas Soome n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); 177*4a5d661aSToomas Soome } 178*4a5d661aSToomas Soome #endif /* MAKECRCH */ 179*4a5d661aSToomas Soome 180*4a5d661aSToomas Soome #else /* !DYNAMIC_CRC_TABLE */ 181*4a5d661aSToomas Soome /* ======================================================================== 182*4a5d661aSToomas Soome * Tables of CRC-32s of all single-byte values, made by make_crc_table(). 183*4a5d661aSToomas Soome */ 184*4a5d661aSToomas Soome #include "crc32.h" 185*4a5d661aSToomas Soome #endif /* DYNAMIC_CRC_TABLE */ 186*4a5d661aSToomas Soome 187*4a5d661aSToomas Soome /* ========================================================================= 188*4a5d661aSToomas Soome * This function can be used by asm versions of crc32() 189*4a5d661aSToomas Soome */ 190*4a5d661aSToomas Soome const z_crc_t FAR * ZEXPORT get_crc_table() 191*4a5d661aSToomas Soome { 192*4a5d661aSToomas Soome #ifdef DYNAMIC_CRC_TABLE 193*4a5d661aSToomas Soome if (crc_table_empty) 194*4a5d661aSToomas Soome make_crc_table(); 195*4a5d661aSToomas Soome #endif /* DYNAMIC_CRC_TABLE */ 196*4a5d661aSToomas Soome return (const z_crc_t FAR *)crc_table; 197*4a5d661aSToomas Soome } 198*4a5d661aSToomas Soome 199*4a5d661aSToomas Soome /* ========================================================================= */ 200*4a5d661aSToomas Soome #define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) 201*4a5d661aSToomas Soome #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 202*4a5d661aSToomas Soome 203*4a5d661aSToomas Soome /* ========================================================================= */ 204*4a5d661aSToomas Soome unsigned long ZEXPORT crc32(crc, buf, len) 205*4a5d661aSToomas Soome unsigned long crc; 206*4a5d661aSToomas Soome const unsigned char FAR *buf; 207*4a5d661aSToomas Soome uInt len; 208*4a5d661aSToomas Soome { 209*4a5d661aSToomas Soome if (buf == Z_NULL) return 0UL; 210*4a5d661aSToomas Soome 211*4a5d661aSToomas Soome #ifdef DYNAMIC_CRC_TABLE 212*4a5d661aSToomas Soome if (crc_table_empty) 213*4a5d661aSToomas Soome make_crc_table(); 214*4a5d661aSToomas Soome #endif /* DYNAMIC_CRC_TABLE */ 215*4a5d661aSToomas Soome 216*4a5d661aSToomas Soome #ifdef BYFOUR 217*4a5d661aSToomas Soome if (sizeof(void *) == sizeof(ptrdiff_t)) { 218*4a5d661aSToomas Soome z_crc_t endian; 219*4a5d661aSToomas Soome 220*4a5d661aSToomas Soome endian = 1; 221*4a5d661aSToomas Soome if (*((unsigned char *)(&endian))) 222*4a5d661aSToomas Soome return crc32_little(crc, buf, len); 223*4a5d661aSToomas Soome else 224*4a5d661aSToomas Soome return crc32_big(crc, buf, len); 225*4a5d661aSToomas Soome } 226*4a5d661aSToomas Soome #endif /* BYFOUR */ 227*4a5d661aSToomas Soome crc = crc ^ 0xffffffffUL; 228*4a5d661aSToomas Soome while (len >= 8) { 229*4a5d661aSToomas Soome DO8; 230*4a5d661aSToomas Soome len -= 8; 231*4a5d661aSToomas Soome } 232*4a5d661aSToomas Soome if (len) do { 233*4a5d661aSToomas Soome DO1; 234*4a5d661aSToomas Soome } while (--len); 235*4a5d661aSToomas Soome return crc ^ 0xffffffffUL; 236*4a5d661aSToomas Soome } 237*4a5d661aSToomas Soome 238*4a5d661aSToomas Soome #ifdef BYFOUR 239*4a5d661aSToomas Soome 240*4a5d661aSToomas Soome /* ========================================================================= */ 241*4a5d661aSToomas Soome #define DOLIT4 c ^= *buf4++; \ 242*4a5d661aSToomas Soome c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ 243*4a5d661aSToomas Soome crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] 244*4a5d661aSToomas Soome #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 245*4a5d661aSToomas Soome 246*4a5d661aSToomas Soome /* ========================================================================= */ 247*4a5d661aSToomas Soome local unsigned long crc32_little(crc, buf, len) 248*4a5d661aSToomas Soome unsigned long crc; 249*4a5d661aSToomas Soome const unsigned char FAR *buf; 250*4a5d661aSToomas Soome unsigned len; 251*4a5d661aSToomas Soome { 252*4a5d661aSToomas Soome register z_crc_t c; 253*4a5d661aSToomas Soome register const z_crc_t FAR *buf4; 254*4a5d661aSToomas Soome 255*4a5d661aSToomas Soome c = (z_crc_t)crc; 256*4a5d661aSToomas Soome c = ~c; 257*4a5d661aSToomas Soome while (len && ((ptrdiff_t)buf & 3)) { 258*4a5d661aSToomas Soome c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); 259*4a5d661aSToomas Soome len--; 260*4a5d661aSToomas Soome } 261*4a5d661aSToomas Soome 262*4a5d661aSToomas Soome buf4 = (const z_crc_t FAR *)(const void FAR *)buf; 263*4a5d661aSToomas Soome while (len >= 32) { 264*4a5d661aSToomas Soome DOLIT32; 265*4a5d661aSToomas Soome len -= 32; 266*4a5d661aSToomas Soome } 267*4a5d661aSToomas Soome while (len >= 4) { 268*4a5d661aSToomas Soome DOLIT4; 269*4a5d661aSToomas Soome len -= 4; 270*4a5d661aSToomas Soome } 271*4a5d661aSToomas Soome buf = (const unsigned char FAR *)buf4; 272*4a5d661aSToomas Soome 273*4a5d661aSToomas Soome if (len) do { 274*4a5d661aSToomas Soome c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); 275*4a5d661aSToomas Soome } while (--len); 276*4a5d661aSToomas Soome c = ~c; 277*4a5d661aSToomas Soome return (unsigned long)c; 278*4a5d661aSToomas Soome } 279*4a5d661aSToomas Soome 280*4a5d661aSToomas Soome /* ========================================================================= */ 281*4a5d661aSToomas Soome #define DOBIG4 c ^= *++buf4; \ 282*4a5d661aSToomas Soome c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ 283*4a5d661aSToomas Soome crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] 284*4a5d661aSToomas Soome #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 285*4a5d661aSToomas Soome 286*4a5d661aSToomas Soome /* ========================================================================= */ 287*4a5d661aSToomas Soome local unsigned long crc32_big(crc, buf, len) 288*4a5d661aSToomas Soome unsigned long crc; 289*4a5d661aSToomas Soome const unsigned char FAR *buf; 290*4a5d661aSToomas Soome unsigned len; 291*4a5d661aSToomas Soome { 292*4a5d661aSToomas Soome register z_crc_t c; 293*4a5d661aSToomas Soome register const z_crc_t FAR *buf4; 294*4a5d661aSToomas Soome 295*4a5d661aSToomas Soome c = ZSWAP32((z_crc_t)crc); 296*4a5d661aSToomas Soome c = ~c; 297*4a5d661aSToomas Soome while (len && ((ptrdiff_t)buf & 3)) { 298*4a5d661aSToomas Soome c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); 299*4a5d661aSToomas Soome len--; 300*4a5d661aSToomas Soome } 301*4a5d661aSToomas Soome 302*4a5d661aSToomas Soome buf4 = (const z_crc_t FAR *)(const void FAR *)buf; 303*4a5d661aSToomas Soome buf4--; 304*4a5d661aSToomas Soome while (len >= 32) { 305*4a5d661aSToomas Soome DOBIG32; 306*4a5d661aSToomas Soome len -= 32; 307*4a5d661aSToomas Soome } 308*4a5d661aSToomas Soome while (len >= 4) { 309*4a5d661aSToomas Soome DOBIG4; 310*4a5d661aSToomas Soome len -= 4; 311*4a5d661aSToomas Soome } 312*4a5d661aSToomas Soome buf4++; 313*4a5d661aSToomas Soome buf = (const unsigned char FAR *)buf4; 314*4a5d661aSToomas Soome 315*4a5d661aSToomas Soome if (len) do { 316*4a5d661aSToomas Soome c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); 317*4a5d661aSToomas Soome } while (--len); 318*4a5d661aSToomas Soome c = ~c; 319*4a5d661aSToomas Soome return (unsigned long)(ZSWAP32(c)); 320*4a5d661aSToomas Soome } 321*4a5d661aSToomas Soome 322*4a5d661aSToomas Soome #endif /* BYFOUR */ 323*4a5d661aSToomas Soome 324*4a5d661aSToomas Soome #define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ 325*4a5d661aSToomas Soome 326*4a5d661aSToomas Soome /* ========================================================================= */ 327*4a5d661aSToomas Soome local unsigned long gf2_matrix_times(mat, vec) 328*4a5d661aSToomas Soome unsigned long *mat; 329*4a5d661aSToomas Soome unsigned long vec; 330*4a5d661aSToomas Soome { 331*4a5d661aSToomas Soome unsigned long sum; 332*4a5d661aSToomas Soome 333*4a5d661aSToomas Soome sum = 0; 334*4a5d661aSToomas Soome while (vec) { 335*4a5d661aSToomas Soome if (vec & 1) 336*4a5d661aSToomas Soome sum ^= *mat; 337*4a5d661aSToomas Soome vec >>= 1; 338*4a5d661aSToomas Soome mat++; 339*4a5d661aSToomas Soome } 340*4a5d661aSToomas Soome return sum; 341*4a5d661aSToomas Soome } 342*4a5d661aSToomas Soome 343*4a5d661aSToomas Soome /* ========================================================================= */ 344*4a5d661aSToomas Soome local void gf2_matrix_square(square, mat) 345*4a5d661aSToomas Soome unsigned long *square; 346*4a5d661aSToomas Soome unsigned long *mat; 347*4a5d661aSToomas Soome { 348*4a5d661aSToomas Soome int n; 349*4a5d661aSToomas Soome 350*4a5d661aSToomas Soome for (n = 0; n < GF2_DIM; n++) 351*4a5d661aSToomas Soome square[n] = gf2_matrix_times(mat, mat[n]); 352*4a5d661aSToomas Soome } 353*4a5d661aSToomas Soome 354*4a5d661aSToomas Soome /* ========================================================================= */ 355*4a5d661aSToomas Soome local uLong crc32_combine_(crc1, crc2, len2) 356*4a5d661aSToomas Soome uLong crc1; 357*4a5d661aSToomas Soome uLong crc2; 358*4a5d661aSToomas Soome z_off64_t len2; 359*4a5d661aSToomas Soome { 360*4a5d661aSToomas Soome int n; 361*4a5d661aSToomas Soome unsigned long row; 362*4a5d661aSToomas Soome unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ 363*4a5d661aSToomas Soome unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ 364*4a5d661aSToomas Soome 365*4a5d661aSToomas Soome /* degenerate case (also disallow negative lengths) */ 366*4a5d661aSToomas Soome if (len2 <= 0) 367*4a5d661aSToomas Soome return crc1; 368*4a5d661aSToomas Soome 369*4a5d661aSToomas Soome /* put operator for one zero bit in odd */ 370*4a5d661aSToomas Soome odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ 371*4a5d661aSToomas Soome row = 1; 372*4a5d661aSToomas Soome for (n = 1; n < GF2_DIM; n++) { 373*4a5d661aSToomas Soome odd[n] = row; 374*4a5d661aSToomas Soome row <<= 1; 375*4a5d661aSToomas Soome } 376*4a5d661aSToomas Soome 377*4a5d661aSToomas Soome /* put operator for two zero bits in even */ 378*4a5d661aSToomas Soome gf2_matrix_square(even, odd); 379*4a5d661aSToomas Soome 380*4a5d661aSToomas Soome /* put operator for four zero bits in odd */ 381*4a5d661aSToomas Soome gf2_matrix_square(odd, even); 382*4a5d661aSToomas Soome 383*4a5d661aSToomas Soome /* apply len2 zeros to crc1 (first square will put the operator for one 384*4a5d661aSToomas Soome zero byte, eight zero bits, in even) */ 385*4a5d661aSToomas Soome do { 386*4a5d661aSToomas Soome /* apply zeros operator for this bit of len2 */ 387*4a5d661aSToomas Soome gf2_matrix_square(even, odd); 388*4a5d661aSToomas Soome if (len2 & 1) 389*4a5d661aSToomas Soome crc1 = gf2_matrix_times(even, crc1); 390*4a5d661aSToomas Soome len2 >>= 1; 391*4a5d661aSToomas Soome 392*4a5d661aSToomas Soome /* if no more bits set, then done */ 393*4a5d661aSToomas Soome if (len2 == 0) 394*4a5d661aSToomas Soome break; 395*4a5d661aSToomas Soome 396*4a5d661aSToomas Soome /* another iteration of the loop with odd and even swapped */ 397*4a5d661aSToomas Soome gf2_matrix_square(odd, even); 398*4a5d661aSToomas Soome if (len2 & 1) 399*4a5d661aSToomas Soome crc1 = gf2_matrix_times(odd, crc1); 400*4a5d661aSToomas Soome len2 >>= 1; 401*4a5d661aSToomas Soome 402*4a5d661aSToomas Soome /* if no more bits set, then done */ 403*4a5d661aSToomas Soome } while (len2 != 0); 404*4a5d661aSToomas Soome 405*4a5d661aSToomas Soome /* return combined crc */ 406*4a5d661aSToomas Soome crc1 ^= crc2; 407*4a5d661aSToomas Soome return crc1; 408*4a5d661aSToomas Soome } 409*4a5d661aSToomas Soome 410*4a5d661aSToomas Soome /* ========================================================================= */ 411*4a5d661aSToomas Soome uLong ZEXPORT crc32_combine(crc1, crc2, len2) 412*4a5d661aSToomas Soome uLong crc1; 413*4a5d661aSToomas Soome uLong crc2; 414*4a5d661aSToomas Soome z_off_t len2; 415*4a5d661aSToomas Soome { 416*4a5d661aSToomas Soome return crc32_combine_(crc1, crc2, len2); 417*4a5d661aSToomas Soome } 418*4a5d661aSToomas Soome 419*4a5d661aSToomas Soome uLong ZEXPORT crc32_combine64(crc1, crc2, len2) 420*4a5d661aSToomas Soome uLong crc1; 421*4a5d661aSToomas Soome uLong crc2; 422*4a5d661aSToomas Soome z_off64_t len2; 423*4a5d661aSToomas Soome { 424*4a5d661aSToomas Soome return crc32_combine_(crc1, crc2, len2); 425*4a5d661aSToomas Soome } 426