1*8275SEric Cheng /*
2*8275SEric Cheng * CDDL HEADER START
3*8275SEric Cheng *
4*8275SEric Cheng * The contents of this file are subject to the terms of the
5*8275SEric Cheng * Common Development and Distribution License (the "License").
6*8275SEric Cheng * You may not use this file except in compliance with the License.
7*8275SEric Cheng *
8*8275SEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*8275SEric Cheng * or http://www.opensolaris.org/os/licensing.
10*8275SEric Cheng * See the License for the specific language governing permissions
11*8275SEric Cheng * and limitations under the License.
12*8275SEric Cheng *
13*8275SEric Cheng * When distributing Covered Code, include this CDDL HEADER in each
14*8275SEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*8275SEric Cheng * If applicable, add the following below this CDDL HEADER, with the
16*8275SEric Cheng * fields enclosed by brackets "[]" replaced with your own identifying
17*8275SEric Cheng * information: Portions Copyright [yyyy] [name of copyright owner]
18*8275SEric Cheng *
19*8275SEric Cheng * CDDL HEADER END
20*8275SEric Cheng */
21*8275SEric Cheng /*
22*8275SEric Cheng * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23*8275SEric Cheng * Use is subject to license terms.
24*8275SEric Cheng */
25*8275SEric Cheng
26*8275SEric Cheng #include <sys/types.h>
27*8275SEric Cheng
28*8275SEric Cheng /*
29*8275SEric Cheng * Fast CRC32 calculation algorithm suggested by Ferenc Rakoczi
30*8275SEric Cheng * (ferenc.rakoczi@sun.com). The basic idea is to look at it
31*8275SEric Cheng * four bytes (one word) at a time, using four tables. The
32*8275SEric Cheng * standard algorithm in RFC 3309 uses one table.
33*8275SEric Cheng */
34*8275SEric Cheng
35*8275SEric Cheng /*
36*8275SEric Cheng * SCTP uses reflected/reverse polynomial CRC32 with generating
37*8275SEric Cheng * polynomial 0x1EDC6F41L
38*8275SEric Cheng */
39*8275SEric Cheng #define SCTP_POLY 0x1EDC6F41L
40*8275SEric Cheng
41*8275SEric Cheng /* The four CRC tables. */
42*8275SEric Cheng static uint32_t crctab[4][256];
43*8275SEric Cheng
44*8275SEric Cheng static uint32_t
reflect_32(uint32_t b)45*8275SEric Cheng reflect_32(uint32_t b)
46*8275SEric Cheng {
47*8275SEric Cheng int i;
48*8275SEric Cheng uint32_t rw = 0;
49*8275SEric Cheng
50*8275SEric Cheng for (i = 0; i < 32; i++) {
51*8275SEric Cheng if (b & 1) {
52*8275SEric Cheng rw |= 1 << (31 - i);
53*8275SEric Cheng }
54*8275SEric Cheng b >>= 1;
55*8275SEric Cheng }
56*8275SEric Cheng return (rw);
57*8275SEric Cheng }
58*8275SEric Cheng
59*8275SEric Cheng #ifdef _BIG_ENDIAN
60*8275SEric Cheng
61*8275SEric Cheng /*
62*8275SEric Cheng * This function is only used for big endian processor.
63*8275SEric Cheng */
64*8275SEric Cheng static uint32_t
flip32(uint32_t w)65*8275SEric Cheng flip32(uint32_t w)
66*8275SEric Cheng {
67*8275SEric Cheng return (((w >> 24) | ((w >> 8) & 0xff00) | ((w << 8) & 0xff0000) |
68*8275SEric Cheng (w << 24)));
69*8275SEric Cheng }
70*8275SEric Cheng
71*8275SEric Cheng #endif
72*8275SEric Cheng
73*8275SEric Cheng void
sctp_crc32_init(void)74*8275SEric Cheng sctp_crc32_init(void)
75*8275SEric Cheng {
76*8275SEric Cheng uint32_t i, j, k, crc;
77*8275SEric Cheng
78*8275SEric Cheng for (i = 0; i < 256; i++) {
79*8275SEric Cheng crc = reflect_32(i);
80*8275SEric Cheng for (k = 0; k < 4; k++) {
81*8275SEric Cheng for (j = 0; j < 8; j++) {
82*8275SEric Cheng crc = (crc & 0x80000000) ?
83*8275SEric Cheng (crc << 1) ^ SCTP_POLY : crc << 1;
84*8275SEric Cheng }
85*8275SEric Cheng #ifdef _BIG_ENDIAN
86*8275SEric Cheng crctab[3 - k][i] = flip32(reflect_32(crc));
87*8275SEric Cheng #else
88*8275SEric Cheng crctab[k][i] = reflect_32(crc);
89*8275SEric Cheng #endif
90*8275SEric Cheng }
91*8275SEric Cheng }
92*8275SEric Cheng }
93*8275SEric Cheng
94*8275SEric Cheng static void
sctp_crc_byte(uint32_t * crcptr,const uint8_t * buf,int len)95*8275SEric Cheng sctp_crc_byte(uint32_t *crcptr, const uint8_t *buf, int len)
96*8275SEric Cheng {
97*8275SEric Cheng uint32_t crc;
98*8275SEric Cheng int i;
99*8275SEric Cheng
100*8275SEric Cheng crc = *crcptr;
101*8275SEric Cheng for (i = 0; i < len; i++) {
102*8275SEric Cheng #ifdef _BIG_ENDIAN
103*8275SEric Cheng crc = (crc << 8) ^ crctab[3][buf[i] ^ (crc >> 24)];
104*8275SEric Cheng #else
105*8275SEric Cheng crc = (crc >> 8) ^ crctab[0][buf[i] ^ (crc & 0xff)];
106*8275SEric Cheng #endif
107*8275SEric Cheng }
108*8275SEric Cheng *crcptr = crc;
109*8275SEric Cheng }
110*8275SEric Cheng
111*8275SEric Cheng static void
sctp_crc_word(uint32_t * crcptr,const uint32_t * buf,int len)112*8275SEric Cheng sctp_crc_word(uint32_t *crcptr, const uint32_t *buf, int len)
113*8275SEric Cheng {
114*8275SEric Cheng uint32_t w, crc;
115*8275SEric Cheng int i;
116*8275SEric Cheng
117*8275SEric Cheng crc = *crcptr;
118*8275SEric Cheng for (i = 0; i < len; i++) {
119*8275SEric Cheng w = crc ^ buf[i];
120*8275SEric Cheng crc = crctab[0][w >> 24] ^ crctab[1][(w >> 16) & 0xff] ^
121*8275SEric Cheng crctab[2][(w >> 8) & 0xff] ^ crctab[3][w & 0xff];
122*8275SEric Cheng }
123*8275SEric Cheng *crcptr = crc;
124*8275SEric Cheng }
125*8275SEric Cheng
126*8275SEric Cheng uint32_t
sctp_crc32(uint32_t crc32,const uint8_t * buf,int len)127*8275SEric Cheng sctp_crc32(uint32_t crc32, const uint8_t *buf, int len)
128*8275SEric Cheng {
129*8275SEric Cheng int rem;
130*8275SEric Cheng
131*8275SEric Cheng rem = 4 - ((uintptr_t)buf) & 3;
132*8275SEric Cheng if (rem != 0) {
133*8275SEric Cheng if (len < rem) {
134*8275SEric Cheng rem = len;
135*8275SEric Cheng }
136*8275SEric Cheng sctp_crc_byte(&crc32, buf, rem);
137*8275SEric Cheng buf = buf + rem;
138*8275SEric Cheng len = len - rem;
139*8275SEric Cheng }
140*8275SEric Cheng
141*8275SEric Cheng if (len > 3) {
142*8275SEric Cheng sctp_crc_word(&crc32, (const uint32_t *)buf, len / 4);
143*8275SEric Cheng }
144*8275SEric Cheng
145*8275SEric Cheng rem = len & 3;
146*8275SEric Cheng if (rem != 0) {
147*8275SEric Cheng sctp_crc_byte(&crc32, buf + len - rem, rem);
148*8275SEric Cheng }
149*8275SEric Cheng return (crc32);
150*8275SEric Cheng }
151