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 */
make_crc_table()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
write_table(out,table)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 */
get_crc_table()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 /* ========================================================================= */
crc32(crc,buf,len)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 /* ========================================================================= */
crc32_little(crc,buf,len)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 /* ========================================================================= */
crc32_big(crc,buf,len)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 /* ========================================================================= */
gf2_matrix_times(mat,vec)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 /* ========================================================================= */
gf2_matrix_square(square,mat)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 /* ========================================================================= */
crc32_combine_(crc1,crc2,len2)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 /* ========================================================================= */
crc32_combine(crc1,crc2,len2)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
crc32_combine64(crc1,crc2,len2)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