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