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