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
43uint32_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 */
116static 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 */
122uint32_t
123iscsi_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 */
165uint32_t
166iscsi_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