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.5.28.1 2019/12/18 20:00:18 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() - Checksum 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(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: * crcIP() - Checksum in IP communication
231: *
232: * @buf = Data for calculation
233: * @bufLen = Length of data
234: * return: Checksum
235: */
236: u_short
237: crcIP(u_char * __restrict buf, int bufLen)
238: {
239: register u_int sum;
240: u_short last = 0, *nBuf = (u_short*) buf;
241:
242: assert(buf);
243:
244: for (sum = 0; bufLen > 1; bufLen -= 2)
245: sum += *nBuf++;
246: if (bufLen == 1) {
247: *(u_char*)(&last) += *(u_char*) nBuf;
248: sum += last;
249: }
250:
251: sum = (sum >> 16) + (sum & 0xFFFF);
252: sum += sum >> 16;
253:
254: return (u_short) ~sum;
255: }
256:
257: /*
258: * crcTCP() - Checksum for TCP v4 communication
259: *
260: * @buf = Data for calculation
261: * @bufLen = Length of data
262: * @th = TCP header
263: * return: Checksum
264: */
265: u_short
266: crcTCP(struct in_addr src, struct in_addr dst, u_char * __restrict th)
267: {
268: struct psd_tcp {
269: struct in_addr src;
270: struct in_addr dst;
271: u_char pad;
272: u_char proto;
273: u_short tcp_len;
274: u_char tcp[20];
275: } buf;
276:
277: buf.src = src;
278: buf.dst = dst;
279: buf.pad = 0;
280: buf.proto = IPPROTO_TCP;
281: buf.tcp_len = htons(sizeof buf.tcp);
282: memcpy(&buf.tcp, th, sizeof buf.tcp);
283:
284: return crcIP((u_char*) &buf, sizeof buf);
285: }
286:
287: /*
288: * crcUDP() - Checksum for UDP v4 communication
289: *
290: * @buf = Data for calculation
291: * @bufLen = Length of data
292: * @uh = UDP header
293: * return: Checksum
294: */
295: u_short
296: crcUDP(struct in_addr src, struct in_addr dst, u_char * __restrict uh)
297: {
298: struct psd_udp {
299: struct in_addr src;
300: struct in_addr dst;
301: u_char pad;
302: u_char proto;
303: u_short udp_len;
304: u_char udp[8];
305: } buf;
306:
307: buf.src = src;
308: buf.dst = dst;
309: buf.pad = 0;
310: buf.proto = IPPROTO_UDP;
311: buf.udp_len = htons(sizeof buf.udp);
312: memcpy(&buf.udp, uh, sizeof buf.udp);
313:
314: return crcIP((u_char*) &buf, sizeof buf);
315: }
316:
317:
318: /*
319: * crcFletcher16() - Fletcher-16 Checksum computing
320: *
321: * @nBuf = Data for calculation
322: * @bufLen = Length of data
323: * return: Checksum
324: */
325: u_short
326: crcFletcher16(u_short * __restrict nBuf, int bufLen)
327: {
328: register u_short s1, s2;
329: register u_int clen;
330:
331: assert(nBuf);
332:
333: s1 = s2 = 0xFF;
334: while (bufLen) {
335: clen = bufLen > MAX_FLETCHER16_DIGEST ? MAX_FLETCHER16_DIGEST : bufLen;
336: bufLen -= clen;
337:
338: do {
339: s1 += (u_short) *nBuf++;
340: s2 += s1;
341: } while (--clen);
342:
343: s1 = (s1 >> 8) + (s1 & 0xFF);
344: s2 = (s2 >> 8) + (s2 & 0xFF);
345: }
346:
347: return (s2 << 8) | s1;
348: }
349:
350: /*
351: * crcFletcher() - Fletcher-32 Checksum computing
352: *
353: * @nBuf = Data for calculation
354: * @bufLen = Length of data
355: * return: Checksum
356: */
357: u_int
358: crcFletcher(u_short * __restrict nBuf, int bufLen)
359: {
360: register u_int s1, s2, clen;
361:
362: assert(nBuf);
363:
364: s1 = s2 = 0xFFFF;
365: while (bufLen) {
366: clen = bufLen > MAX_FLETCHER_DIGEST ? MAX_FLETCHER_DIGEST : bufLen;
367: bufLen -= clen;
368:
369: do {
370: s1 += (u_int) *nBuf++;
371: s2 += s1;
372: } while (--clen);
373:
374: s1 = (s1 >> 16) + (s1 & 0xFFFF);
375: s2 = (s2 >> 16) + (s2 & 0xFFFF);
376: }
377:
378: return (s2 << 16) | s1;
379: }
380:
381: /*
382: * crcAdler() - crcAdler-32 Checksum computing
383: *
384: * @psBuf = Data for calculation
385: * @bufLen = Length of data
386: * return: Checksum
387: */
388: u_int
389: crcAdler(u_char * __restrict psBuf, int bufLen)
390: {
391: register u_int s1 = 1, s2 = 0, clen;
392:
393: assert(psBuf);
394:
395: while (bufLen) {
396: clen = bufLen > MAX_ADLER_DIGEST ? MAX_ADLER_DIGEST : bufLen;
397: bufLen -= clen;
398:
399: do {
400: s1 += (u_int) *psBuf++;
401: s2 += s1;
402: } while (--clen);
403:
404: s1 %= crc_modAdler;
405: s2 %= crc_modAdler;
406: }
407:
408: return (s2 << 16) | s1;
409: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>