crcutils.c revision 11015:0a0751599d31
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#include <string.h>
28#include <limits.h>
29
30#include "crcmodel.h"
31
32#if defined(_LITTLE_ENDIAN)
33
34/* Little-endian architectures need byte-swapping. */
35
36#define	sws(x) (((x >> 8) & 0x00ff) | ((x << 8) & 0xff00))
37#define	swl(x) (sws(x >> 16) | (sws(x) << 16))
38
39#define	swap_short(x) (x = sws(x))
40#define	swap_long(x) (x = swl(x))
41
42#else   /* if !_LITTLE_ENDIAN */
43
44/* Big-endian anchictectures don't need byte-swapping. */
45
46#define	sws(x) (x)
47#define	swl(x) (x)
48
49#define	swap_short(x) (x = sws(x))
50#define	swap_long(x) (x = swl(x))
51
52#endif  /* _LITTLE_ENDIAN */
53
54unsigned char
55compute_crc8(unsigned char *bytes, int length)
56{
57	cm_t crc_mdl;
58	p_cm_t p_crc;
59	int i;
60	unsigned char aCRC;
61
62	p_crc = &crc_mdl;
63
64	p_crc->cm_width = 8;
65	p_crc->cm_poly = 0x107; /* = X^8 + x^2 + x + 1 */
66	p_crc->cm_init = 0;
67	p_crc->cm_refin = TRUE;
68	p_crc->cm_refot = TRUE;
69	p_crc->cm_xorot = 0;
70
71	cm_ini(p_crc);
72
73	for (i = 0; i < length; i++) {
74		cm_nxt(p_crc, bytes[i]);
75	}
76
77	aCRC = (unsigned char)cm_crc(p_crc);
78
79	return (aCRC);
80}
81
82uint32_t
83compute_crc32(unsigned char *bytes, int length)
84{
85	cm_t crc_mdl;
86	p_cm_t p_crc;
87	int i;
88	uint32_t aCRC;
89
90	p_crc = &crc_mdl;
91
92	p_crc->cm_width = 32;
93	p_crc->cm_poly = 0x04c11db7;
94	p_crc->cm_init = 0xffffffff;
95	p_crc->cm_refin = TRUE;
96	p_crc->cm_refot = TRUE;
97	p_crc->cm_xorot = 0xffffffff;
98
99	cm_ini(p_crc);
100
101	for (i = 0; i < length; i++) {
102		cm_nxt(p_crc, bytes[i]);
103	}
104
105	aCRC = (uint32_t)cm_crc(p_crc);
106
107	return (aCRC);
108}
109
110/*
111 * This is the max value an uint32_t value can hold...
112 * Define this for Windows compilers which don't have "limits.h" or equivalant
113 */
114#define	UINT32_T_MAX 0xFFFFFFFF
115
116uint32_t
117compute_checksum32(unsigned char *bytes, int length)
118{
119	uint32_t regval = 0;
120	int i, j, k;
121	uint32_t next4bytes;
122	unsigned char tailbytes[4] = { 0x00, 0x00, 0x00, 0x00 };
123
124	/* Grab bytes in 4-byte chunks */
125	for (i = 0; i < length-4; i += 4) {
126		/* Grab chunk as an int */
127		(void) memcpy(&next4bytes, &(bytes[i]), 4);
128		swap_long(next4bytes);
129
130		if (next4bytes > UINT32_T_MAX - regval) {
131			next4bytes -= UINT32_T_MAX - regval;
132			regval = 0;
133		}
134
135		/* Add intval to regval */
136		regval += next4bytes;
137	}
138
139	/* Grab any remaining bytes at the end */
140	for (j = length-1, k = 3; j >= i; j--, k--) {
141		tailbytes[k] = bytes[j];
142	}
143
144/*
145 * Treat any remaining bytes put into tailbytes as if they were
146 * a left-zero-padded unsigned int (uint32_t == 4 bytes!)
147 */
148	(void) memcpy(&next4bytes, tailbytes, 4);
149	swap_long(next4bytes);
150	if (next4bytes > UINT32_T_MAX - regval) {
151		next4bytes -= UINT32_T_MAX - regval;
152		regval = 0;
153	}
154	regval += next4bytes;
155
156	return ((uint32_t)regval);
157}
158