crcutils.c revision 11015:0a0751599d31
138494Sobrien/*
2174294Sobrien * CDDL HEADER START
338494Sobrien *
438494Sobrien * The contents of this file are subject to the terms of the
538494Sobrien * Common Development and Distribution License (the "License").
638494Sobrien * You may not use this file except in compliance with the License.
738494Sobrien *
838494Sobrien * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
938494Sobrien * or http://www.opensolaris.org/os/licensing.
1038494Sobrien * See the License for the specific language governing permissions
1138494Sobrien * and limitations under the License.
1238494Sobrien *
1338494Sobrien * When distributing Covered Code, include this CDDL HEADER in each
1438494Sobrien * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1538494Sobrien * If applicable, add the following below this CDDL HEADER, with the
1638494Sobrien * fields enclosed by brackets "[]" replaced with your own identifying
1738494Sobrien * information: Portions Copyright [yyyy] [name of copyright owner]
1838494Sobrien *
1938494Sobrien * CDDL HEADER END
2042629Sobrien */
2138494Sobrien
2238494Sobrien/*
2338494Sobrien * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2438494Sobrien * Use is subject to license terms.
2538494Sobrien */
2638494Sobrien
2738494Sobrien#include <string.h>
2838494Sobrien#include <limits.h>
2938494Sobrien
3038494Sobrien#include "crcmodel.h"
3138494Sobrien
3238494Sobrien#if defined(_LITTLE_ENDIAN)
3338494Sobrien
3438494Sobrien/* Little-endian architectures need byte-swapping. */
3538494Sobrien
3638494Sobrien#define	sws(x) (((x >> 8) & 0x00ff) | ((x << 8) & 0xff00))
3738494Sobrien#define	swl(x) (sws(x >> 16) | (sws(x) << 16))
3838494Sobrien
3938494Sobrien#define	swap_short(x) (x = sws(x))
40174294Sobrien#define	swap_long(x) (x = swl(x))
4138494Sobrien
4238494Sobrien#else   /* if !_LITTLE_ENDIAN */
4338494Sobrien
4438494Sobrien/* Big-endian anchictectures don't need byte-swapping. */
4538494Sobrien
4638494Sobrien#define	sws(x) (x)
4738494Sobrien#define	swl(x) (x)
4838494Sobrien
4938494Sobrien#define	swap_short(x) (x = sws(x))
5038494Sobrien#define	swap_long(x) (x = swl(x))
5138494Sobrien
5238494Sobrien#endif  /* _LITTLE_ENDIAN */
5338494Sobrien
5438494Sobrienunsigned char
5582794Sobriencompute_crc8(unsigned char *bytes, int length)
5638494Sobrien{
5738494Sobrien	cm_t crc_mdl;
5838494Sobrien	p_cm_t p_crc;
5938494Sobrien	int i;
6038494Sobrien	unsigned char aCRC;
6138494Sobrien
6238494Sobrien	p_crc = &crc_mdl;
6338494Sobrien
6482794Sobrien	p_crc->cm_width = 8;
6538494Sobrien	p_crc->cm_poly = 0x107; /* = X^8 + x^2 + x + 1 */
6682794Sobrien	p_crc->cm_init = 0;
6738494Sobrien	p_crc->cm_refin = TRUE;
6838494Sobrien	p_crc->cm_refot = TRUE;
6938494Sobrien	p_crc->cm_xorot = 0;
7038494Sobrien
7182794Sobrien	cm_ini(p_crc);
7238494Sobrien
7382794Sobrien	for (i = 0; i < length; i++) {
7482794Sobrien		cm_nxt(p_crc, bytes[i]);
7538494Sobrien	}
7682794Sobrien
7782794Sobrien	aCRC = (unsigned char)cm_crc(p_crc);
7838494Sobrien
7982794Sobrien	return (aCRC);
8082794Sobrien}
8138494Sobrien
8282794Sobrienuint32_t
8382794Sobriencompute_crc32(unsigned char *bytes, int length)
8438494Sobrien{
8582794Sobrien	cm_t crc_mdl;
8682794Sobrien	p_cm_t p_crc;
8738494Sobrien	int i;
8882794Sobrien	uint32_t aCRC;
8938494Sobrien
9038494Sobrien	p_crc = &crc_mdl;
9138494Sobrien
9238494Sobrien	p_crc->cm_width = 32;
9338494Sobrien	p_crc->cm_poly = 0x04c11db7;
9438494Sobrien	p_crc->cm_init = 0xffffffff;
9538494Sobrien	p_crc->cm_refin = TRUE;
9638494Sobrien	p_crc->cm_refot = TRUE;
9738494Sobrien	p_crc->cm_xorot = 0xffffffff;
9838494Sobrien
9938494Sobrien	cm_ini(p_crc);
10038494Sobrien
10138494Sobrien	for (i = 0; i < length; i++) {
10238494Sobrien		cm_nxt(p_crc, bytes[i]);
10338494Sobrien	}
10438494Sobrien
10538494Sobrien	aCRC = (uint32_t)cm_crc(p_crc);
10638494Sobrien
10738494Sobrien	return (aCRC);
10838494Sobrien}
10938494Sobrien
11038494Sobrien/*
11138494Sobrien * This is the max value an uint32_t value can hold...
11238494Sobrien * Define this for Windows compilers which don't have "limits.h" or equivalant
11338494Sobrien */
11438494Sobrien#define	UINT32_T_MAX 0xFFFFFFFF
11538494Sobrien
11638494Sobrienuint32_t
11738494Sobriencompute_checksum32(unsigned char *bytes, int length)
11838494Sobrien{
11938494Sobrien	uint32_t regval = 0;
12038494Sobrien	int i, j, k;
12138494Sobrien	uint32_t next4bytes;
12238494Sobrien	unsigned char tailbytes[4] = { 0x00, 0x00, 0x00, 0x00 };
12338494Sobrien
12438494Sobrien	/* Grab bytes in 4-byte chunks */
125174294Sobrien	for (i = 0; i < length-4; i += 4) {
12638494Sobrien		/* Grab chunk as an int */
12738494Sobrien		(void) memcpy(&next4bytes, &(bytes[i]), 4);
12838494Sobrien		swap_long(next4bytes);
129119679Smbr
13038494Sobrien		if (next4bytes > UINT32_T_MAX - regval) {
13182794Sobrien			next4bytes -= UINT32_T_MAX - regval;
13238494Sobrien			regval = 0;
13382794Sobrien		}
13482794Sobrien
13538494Sobrien		/* Add intval to regval */
13682794Sobrien		regval += next4bytes;
13782794Sobrien	}
13838494Sobrien
13982794Sobrien	/* Grab any remaining bytes at the end */
14082794Sobrien	for (j = length-1, k = 3; j >= i; j--, k--) {
14138494Sobrien		tailbytes[k] = bytes[j];
14282794Sobrien	}
14338494Sobrien
14438494Sobrien/*
14538494Sobrien * Treat any remaining bytes put into tailbytes as if they were
14638494Sobrien * a left-zero-padded unsigned int (uint32_t == 4 bytes!)
14738494Sobrien */
148174294Sobrien	(void) memcpy(&next4bytes, tailbytes, 4);
14938494Sobrien	swap_long(next4bytes);
15038494Sobrien	if (next4bytes > UINT32_T_MAX - regval) {
151174294Sobrien		next4bytes -= UINT32_T_MAX - regval;
15238494Sobrien		regval = 0;
15338494Sobrien	}
15438494Sobrien	regval += next4bytes;
155174294Sobrien
15638494Sobrien	return ((uint32_t)regval);
157174294Sobrien}
158174294Sobrien