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 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 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