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