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