File:  [ELWIX - Embedded LightWeight unIX -] / libelwix / src / crc.c
Revision 1.6: download - view: text, annotated - select for diffs - revision graph
Mon Dec 30 18:11:16 2019 UTC (4 years, 4 months ago) by misho
Branches: MAIN
CVS tags: elwix5_9, elwix5_8, elwix5_7, elwix5_6, elwix5_5, elwix5_4, elwix5_3, elwix5_2, elwix5_12, elwix5_11, elwix5_10, elwix5_1, elwix5_0, elwix4_26, elwix4_25, elwix4_24, elwix4_23, HEAD, ELWIX5_9, ELWIX5_8, ELWIX5_7, ELWIX5_6, ELWIX5_5, ELWIX5_4, ELWIX5_3, ELWIX5_2, ELWIX5_11, ELWIX5_10, ELWIX5_1, ELWIX5_0, ELWIX4_26, ELWIX4_25, ELWIX4_24, ELWIX4_23, ELWIX4_22
ver 4.22

    1: /*************************************************************************
    2: * (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
    3: *  by Michael Pounov <misho@openbsd-bg.org>
    4: *
    5: * $Author: misho $
    6: * $Id: crc.c,v 1.6 2019/12/30 18:11:16 misho Exp $
    7: *
    8: **************************************************************************
    9: The ELWIX and AITNET software is distributed under the following
   10: terms:
   11: 
   12: All of the documentation and software included in the ELWIX and AITNET
   13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   14: 
   15: Copyright 2004 - 2019
   16: 	by Michael Pounov <misho@elwix.org>.  All rights reserved.
   17: 
   18: Redistribution and use in source and binary forms, with or without
   19: modification, are permitted provided that the following conditions
   20: are met:
   21: 1. Redistributions of source code must retain the above copyright
   22:    notice, this list of conditions and the following disclaimer.
   23: 2. Redistributions in binary form must reproduce the above copyright
   24:    notice, this list of conditions and the following disclaimer in the
   25:    documentation and/or other materials provided with the distribution.
   26: 3. All advertising materials mentioning features or use of this software
   27:    must display the following acknowledgement:
   28: This product includes software developed by Michael Pounov <misho@elwix.org>
   29: ELWIX - Embedded LightWeight unIX and its contributors.
   30: 4. Neither the name of AITNET nor the names of its contributors
   31:    may be used to endorse or promote products derived from this software
   32:    without specific prior written permission.
   33: 
   34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
   35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44: SUCH DAMAGE.
   45: */
   46: #include "global.h"
   47: 
   48: 
   49: /* CRC16 poly */
   50: const u_short crc_16poly = 0x1021;
   51: 
   52: /* Adler module */
   53: const u_int crc_modAdler = 0xFFF1L;
   54: 
   55: /* All known library CRC types ... */
   56: const crcPoly_t crc_Poly[] = {
   57: 	{ 1, (u_int) 0x1, "CRC-1-Parity" }, 
   58: 	{ 4, (u_int) 0x3, "CRC-4-ITU" }, 
   59: 	{ 5, (u_int) 0x15, "CRC-5-ITU" }, 
   60: 	{ 6, (u_int) 0x3, "CRC-6-ITU" }, 
   61: 	{ 7, (u_int) 0x9, "CRC-7-MMC" }, 
   62: 	{ 8, (u_int) 0x8D, "CRC-8-CCITT" }, 
   63: 	{ 10, (u_int) 0x233, "CRC-10" }, 
   64: 	{ 11, (u_int) 0x385, "CRC-11-FlexRay" }, 
   65: 	{ 12, (u_int) 0x80F, "CRC-12-Telco" }, 
   66: 	{ 15, (u_int) 0x4599, "CRC-15-CAN" }, 
   67: 	{ 16, (u_int) 0x8005, "CRC-16-IBM" }, 
   68: 	{ 24, (u_int) 0x864CFB, "CRC-24-Radix64" }, 
   69: 	{ 30, (u_int) 0x2030B9C7, "CRC-30-CDMA" }, 
   70: 	{ 32, (u_int) 0x04C11DB7, "CRC-32-802.3" }
   71: };
   72: 
   73: 
   74: /*
   75:  * crcReflect() - Reflect all bits of number 
   76:  *
   77:  * @crcNum = Number for reflection
   78:  * @crcBits = Number width bits 
   79:  * return: reflecting number
   80:  */
   81: u_int
   82: crcReflect(u_int crcNum, u_char crcBits)
   83: {
   84: 	register u_int i, j = 1, rev = 0;
   85: 
   86: 	for (i = (u_int) 1 << (crcBits - 1); i; i >>= 1, j <<= 1)
   87: 		if (crcNum & i)
   88: 			rev |= j;
   89: 	return rev;
   90: }
   91: 
   92: /*
   93:  * crcCalc() - Generic CRC calculation function for many sub variants of CRC algorithms
   94:  *
   95:  * @psBuf = Data for calculation
   96:  * @bufLen = Length of data
   97:  * @crcBits = CRC algorithm bits (1, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 24, 30, 32)
   98:  * @RevOpts = Options for computation (REVOPTS_REVERTBYTE, REVOPTS_REVERTCRC)
   99:  * @initCRC = Initial CRC value
  100:  * @xorCRC = Last xor CRC value
  101:  * return: CRC checksum
  102:  */
  103: u_int
  104: crcCalc(u_char * __restrict psBuf, u_int bufLen, u_char crcBits, u_char RevOpts, u_int initCRC, u_int xorCRC)
  105: {
  106: 	const u_int bits = sizeof(int) * 8 - crcBits;
  107: 	u_int poly, crchibit, crc;
  108: 	register u_int i, j, b, ch;
  109: 
  110: 	assert(psBuf);
  111: 
  112: 	switch (crcBits) {
  113: 		case 1:
  114: 			poly = crc_Poly[0].poly_num;
  115: 			break;
  116: 		case 4:
  117: 			poly = crc_Poly[1].poly_num;
  118: 			break;
  119: 		case 5:
  120: 			poly = crc_Poly[2].poly_num;
  121: 			break;
  122: 		case 6:
  123: 			poly = crc_Poly[3].poly_num;
  124: 			break;
  125: 		case 7:
  126: 			poly = crc_Poly[4].poly_num;
  127: 			break;
  128: 		case 8:
  129: 			poly = crc_Poly[5].poly_num;
  130: 			break;
  131: 		case 10:
  132: 			poly = crc_Poly[6].poly_num;
  133: 			break;
  134: 		case 11:
  135: 			poly = crc_Poly[7].poly_num;
  136: 			break;
  137: 		case 12:
  138: 			poly = crc_Poly[8].poly_num;
  139: 			break;
  140: 		case 15:
  141: 			poly = crc_Poly[9].poly_num;
  142: 			break;
  143: 		case 16:
  144: 			poly = crc_Poly[10].poly_num;
  145: 			break;
  146: 		case 24:
  147: 			poly = crc_Poly[11].poly_num;
  148: 			break;
  149: 		case 30:
  150: 			poly = crc_Poly[12].poly_num;
  151: 			break;
  152: 		case 32:
  153: 			poly = crc_Poly[13].poly_num;
  154: 			break;
  155: 		default:
  156: 			elwix_SetErr(EINVAL, "crcCalc(): Unsupported CRC method!!!");
  157: 			return -1;
  158: 	}
  159: 	poly <<= bits;
  160: 
  161: 	crchibit = (u_int) 1 << (crcBits - 1);
  162: 	crchibit <<= bits;
  163: 	crc = initCRC << bits;
  164: 
  165: 	for (i = 0; i < bufLen; i++) {
  166: 		ch = (u_int) *psBuf++;
  167: 		if (RevOpts & REVOPTS_REVERTBYTE)
  168: 			ch = crcReflect(ch, 8);
  169: 
  170: 		for (j = 0x80; j; j >>= 1) {
  171: 			b = crc & crchibit;
  172: 			crc <<= 1;
  173: 
  174: 			if (ch & j)
  175: 				b ^= crchibit;
  176: 			if (b)
  177: 				crc ^= poly;
  178: 		}
  179: 	}
  180: 
  181: 	if (RevOpts & REVOPTS_REVERTCRC)
  182: 		crc = crcReflect(crc, sizeof(int) * 8);
  183: 	crc ^= xorCRC << bits;
  184: 	crc &= (((crchibit - 1) << 1) | 1);
  185: 	if (!(RevOpts & REVOPTS_REVERTCRC))
  186: 		crc >>= bits;
  187: 
  188: 	return crc;
  189: }
  190: 
  191: 
  192: /*
  193:  * crc16_ext() - Checksum ver.2 calculation in X/Y modem communication
  194:  *
  195:  * @buf = Data for calculation
  196:  * @bufLen = Length of data
  197:  * return: Checksum
  198:  */
  199: u_short
  200: crc16_ext(u_char * __restrict buf, int bufLen)
  201: {
  202: 	u_short crc, x;
  203: 	register u_short i;
  204: 
  205: 	assert(buf);
  206: 
  207: 	for (crc = 0; bufLen > 0; bufLen--, buf++)
  208: 		for (i = 0x80; i; i >>= 1) {
  209: 			x = crc >> 15;
  210: 			crc <<= 1;
  211: 
  212: 			if (*buf & i)
  213: 				crc++;
  214: 			if (x)
  215: 				crc ^= crc_16poly;
  216: 		}
  217: 
  218: 	for (i = 0; i < 16; i++) {
  219: 		x = crc >> 15;
  220: 		crc <<= 1;
  221: 
  222: 		if (x)
  223: 			crc ^= crc_16poly;
  224: 	}
  225: 
  226: 	return crc;
  227: }
  228: 
  229: /*
  230:  * crc16() - Checksum calculation in X/Y modem communication
  231:  *
  232:  * @buf = Data for calculation
  233:  * @bufLen = Length of data
  234:  * return: Checksum
  235:  */
  236: u_short
  237: crc16(u_char * __restrict buf, int bufLen)
  238: {
  239: 	u_short crc;
  240: 	register u_char i;
  241: 
  242: 	for (crc = 0; bufLen > 0; bufLen--, buf++) {
  243: 		crc ^= (u_short) *buf << 8;
  244: 		for (i = 0x80; i; i >>= 1)
  245: 			if (crc & 0x8000)
  246: 				crc = crc << 1 ^ crc_16poly;
  247: 			else
  248: 				crc <<= 1;
  249: 	}
  250: 
  251: 	return crc;
  252: }
  253: 
  254: /*
  255:  * crcIP() - Checksum in IP communication
  256:  *
  257:  * @buf = Data for calculation
  258:  * @bufLen = Length of data
  259:  * return: Checksum
  260:  */
  261: u_short
  262: crcIP(u_char * __restrict buf, int bufLen)
  263: {
  264: 	register u_int sum;
  265: 	u_short last = 0, *nBuf = (u_short*) buf;
  266: 
  267: 	assert(buf);
  268: 
  269: 	for (sum = 0; bufLen > 1; bufLen -= 2)
  270: 		sum += *nBuf++;
  271: 	if (bufLen == 1) {
  272: 		*(u_char*)(&last) += *(u_char*) nBuf;
  273: 		sum += last;
  274: 	}
  275: 
  276: 	sum = (sum >> 16) + (sum & 0xFFFF);
  277: 	sum += sum >> 16;
  278: 
  279: 	return (u_short) ~sum;
  280: }
  281: 
  282: /*
  283:  * crcTCP() - Checksum for TCP v4 communication
  284:  *
  285:  * @buf = Data for calculation
  286:  * @bufLen = Length of data
  287:  * @th = TCP header
  288:  * return: Checksum
  289:  */
  290: u_short
  291: crcTCP(struct in_addr src, struct in_addr dst, u_char * __restrict th)
  292: {
  293: 	struct psd_tcp {
  294: 		struct in_addr src;
  295: 		struct in_addr dst;
  296: 		u_char pad;
  297: 		u_char proto;
  298: 		u_short tcp_len;
  299: 		u_char tcp[20];
  300: 	} buf;
  301: 
  302: 	buf.src = src;
  303: 	buf.dst = dst;
  304: 	buf.pad = 0;
  305: 	buf.proto = IPPROTO_TCP;
  306: 	buf.tcp_len = htons(sizeof buf.tcp);
  307: 	memcpy(&buf.tcp, th, sizeof buf.tcp);
  308: 
  309: 	return crcIP((u_char*) &buf, sizeof buf);
  310: }
  311: 
  312: /*
  313:  * crcUDP() - Checksum for UDP v4 communication
  314:  *
  315:  * @buf = Data for calculation
  316:  * @bufLen = Length of data
  317:  * @uh = UDP header
  318:  * return: Checksum
  319:  */
  320: u_short
  321: crcUDP(struct in_addr src, struct in_addr dst, u_char * __restrict uh)
  322: {
  323: 	struct psd_udp {
  324: 		struct in_addr src;
  325: 		struct in_addr dst;
  326: 		u_char pad;
  327: 		u_char proto;
  328: 		u_short udp_len;
  329: 		u_char udp[8];
  330: 	} buf;
  331: 
  332: 	buf.src = src;
  333: 	buf.dst = dst;
  334: 	buf.pad = 0;
  335: 	buf.proto = IPPROTO_UDP;
  336: 	buf.udp_len = htons(sizeof buf.udp);
  337: 	memcpy(&buf.udp, uh, sizeof buf.udp);
  338: 
  339: 	return crcIP((u_char*) &buf, sizeof buf);
  340: }
  341: 
  342: 
  343: /*
  344:  * crcFletcher16() - Fletcher-16 Checksum computing
  345:  *
  346:  * @nBuf = Data for calculation
  347:  * @bufLen = Length of data
  348:  * return: Checksum
  349:  */
  350: u_short
  351: crcFletcher16(u_short * __restrict nBuf, int bufLen)
  352: {
  353: 	register u_short s1, s2;
  354: 	register u_int clen;
  355: 
  356: 	assert(nBuf);
  357: 
  358: 	s1 = s2 = 0xFF;
  359: 	while (bufLen) {
  360: 		clen = bufLen > MAX_FLETCHER16_DIGEST ? MAX_FLETCHER16_DIGEST : bufLen;
  361: 		bufLen -= clen;
  362: 
  363: 		do {
  364: 			s1 += (u_short) *nBuf++;
  365: 			s2 += s1;
  366: 		} while (--clen);
  367: 
  368: 		s1 = (s1 >> 8) + (s1 & 0xFF);
  369: 		s2 = (s2 >> 8) + (s2 & 0xFF);
  370: 	}
  371: 
  372: 	return (s2 << 8) | s1;
  373: }
  374: 
  375: /*
  376:  * crcFletcher() - Fletcher-32 Checksum computing
  377:  *
  378:  * @nBuf = Data for calculation
  379:  * @bufLen = Length of data
  380:  * return: Checksum
  381:  */
  382: u_int
  383: crcFletcher(u_short * __restrict nBuf, int bufLen)
  384: {
  385: 	register u_int s1, s2, clen;
  386: 
  387: 	assert(nBuf);
  388: 
  389: 	s1 = s2 = 0xFFFF;
  390: 	while (bufLen) {
  391: 		clen = bufLen > MAX_FLETCHER_DIGEST ? MAX_FLETCHER_DIGEST : bufLen;
  392: 		bufLen -= clen;
  393: 
  394: 		do {
  395: 			s1 += (u_int) *nBuf++;
  396: 			s2 += s1;
  397: 		} while (--clen);
  398: 
  399: 		s1 = (s1 >> 16) + (s1 & 0xFFFF);
  400: 		s2 = (s2 >> 16) + (s2 & 0xFFFF);
  401: 	}
  402: 
  403: 	return (s2 << 16) | s1;
  404: }
  405: 
  406: /*
  407:  * crcAdler() - crcAdler-32 Checksum computing
  408:  *
  409:  * @psBuf = Data for calculation
  410:  * @bufLen = Length of data
  411:  * return: Checksum
  412:  */
  413: u_int
  414: crcAdler(u_char * __restrict psBuf, int bufLen)
  415: {
  416: 	register u_int s1 = 1, s2 = 0, clen;
  417: 
  418: 	assert(psBuf);
  419: 
  420: 	while (bufLen) {
  421: 		clen = bufLen > MAX_ADLER_DIGEST ? MAX_ADLER_DIGEST : bufLen;
  422: 		bufLen -= clen;
  423: 
  424: 		do {
  425: 			s1 += (u_int) *psBuf++;
  426: 			s2 += s1;
  427: 		} while (--clen);
  428: 
  429: 		s1 %= crc_modAdler;
  430: 		s2 %= crc_modAdler;
  431: 	}
  432: 
  433: 	return (s2 << 16) | s1;
  434: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>