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 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 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 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 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 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 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