xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_crc.c (revision bfed486ad8de8b8ebc6345a8e10accae08bf2f45)
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  * Copyright 2000 by Cisco Systems, Inc.  All rights reserved.
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * This file contains CRC-32C code use to verify
27  * iSCSI HeaderDigests and DataDigests.
28  */
29 
30 #include <sys/types.h>	/* standard types */
31 #include "iscsi.h"	/* contains prototypes */
32 
33 /*
34  * This is the CRC-32C table
35  * Generated with:
36  * width = 32 bits
37  * poly = 0x1EDC6F41
38  * reflect input bytes = true
39  * reflect output bytes = true
40  */
41 
42 uint32_t iscsi_crc32c_table[256] =
43 {
44 	0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
45 	0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
46 	0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
47 	0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
48 	0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
49 	0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
50 	0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
51 	0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
52 	0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
53 	0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
54 	0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
55 	0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
56 	0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
57 	0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
58 	0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
59 	0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
60 	0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
61 	0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
62 	0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
63 	0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
64 	0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
65 	0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
66 	0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
67 	0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
68 	0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
69 	0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
70 	0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
71 	0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
72 	0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
73 	0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
74 	0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
75 	0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
76 	0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
77 	0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
78 	0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
79 	0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
80 	0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
81 	0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
82 	0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
83 	0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
84 	0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
85 	0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
86 	0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
87 	0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
88 	0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
89 	0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
90 	0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
91 	0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
92 	0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
93 	0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
94 	0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
95 	0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
96 	0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
97 	0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
98 	0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
99 	0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
100 	0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
101 	0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
102 	0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
103 	0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
104 	0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
105 	0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
106 	0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
107 	0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
108 };
109 
110 /*
111  * iscsi_crc32c - Steps through buffer one byte at at time, calculates
112  * reflected crc using table.
113  */
114 uint32_t
115 iscsi_crc32c(void *address, unsigned long length)
116 {
117 	uint8_t *buffer = address;
118 	uint32_t crc = 0xffffffff, result;
119 #ifdef _BIG_ENDIAN
120 	uint8_t byte0, byte1, byte2, byte3;
121 #endif
122 
123 	ASSERT(address != NULL);
124 
125 	while (length--) {
126 		crc = iscsi_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^
127 		    (crc >> 8);
128 	}
129 	result = crc ^ 0xffffffff;
130 
131 #ifdef	_BIG_ENDIAN
132 	byte0 = (uint8_t)(result & 0xFF);
133 	byte1 = (uint8_t)((result >> 8) & 0xFF);
134 	byte2 = (uint8_t)((result >> 16) & 0xFF);
135 	byte3 = (uint8_t)((result >> 24) & 0xFF);
136 	result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
137 #endif	/* _BIG_ENDIAN */
138 
139 	return (result);
140 }
141 
142 
143 /*
144  * iscsi_crc32c_continued - Continues stepping through buffer one
145  * byte at at time, calculates reflected crc using table.
146  */
147 uint32_t
148 iscsi_crc32c_continued(void *address, unsigned long length, uint32_t crc)
149 {
150 	uint8_t *buffer = address;
151 	uint32_t result;
152 #ifdef	_BIG_ENDIAN
153 	uint8_t byte0, byte1, byte2, byte3;
154 #endif
155 
156 	ASSERT(address != NULL);
157 
158 #ifdef	_BIG_ENDIAN
159 	byte0 = (uint8_t)((crc >> 24) & 0xFF);
160 	byte1 = (uint8_t)((crc >> 16) & 0xFF);
161 	byte2 = (uint8_t)((crc >> 8) & 0xFF);
162 	byte3 = (uint8_t)(crc & 0xFF);
163 	crc = ((byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0);
164 #endif
165 
166 	crc = crc ^ 0xffffffff;
167 	while (length--) {
168 		crc = iscsi_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^
169 		    (crc >> 8);
170 	}
171 	result = crc ^ 0xffffffff;
172 
173 #ifdef	_BIG_ENDIAN
174 	byte0 = (uint8_t)(result & 0xFF);
175 	byte1 = (uint8_t)((result >> 8) & 0xFF);
176 	byte2 = (uint8_t)((result >> 16) & 0xFF);
177 	byte3 = (uint8_t)((result >> 24) & 0xFF);
178 	result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
179 #endif
180 	return (result);
181 }
182