2 * This is an implementation of the CRC-24Q cyclic redundancy checksum
3 * used by Qualcomm, RTCM104V3, and PGP 6.5.1. According to the RTCM104V3
4 * standard, it uses the error polynomial
6 * x^24+ x^23+ x^18+ x^17+ x^14+ x^11+ x^10+ x^7+ x^6+ x^5+ x^4+ x^3+ x+1
8 * This corresponds to a mask of 0x1864CFB. For a primer on CRC theory,
9 * including detailed discussion of how and why the error polynomial is
10 * expressed by this mask, see <http://www.ross.net/crc/>.
12 * 1) It detects all single bit errors per 24-bit code word.
13 * 2) It detects all double bit error combinations in a code word.
14 * 3) It detects any odd number of errors.
15 * 4) It detects any burst error for which the length of the burst is less than
16 * or equal to 24 bits.
17 * 5) It detects most large error bursts with length greater than 24 bits;
18 * the odds of a false positive are at most 2^-23.
20 * This hash should not be considered cryptographically secure, but it
21 * is extremely good at detecting noise errors.
23 * Note that this version has a seed of 0 wired in. The RTCM104V3 standard
26 * This file is Copyright (c) 2008,2010 by the GPSD project
27 * BSD terms apply: see the file COPYING in the distribution root for details.
33 #ifdef REBUILD_CRC_TABLE
35 * The crc24q code table below can be regenerated with the following code:
42 #define CRCSEED 0 /* could be NZ to detect leading zeros */
43 #define CRCPOLY 0x1864CFB /* encodes all info about the polynomial */
45 static void crc_init(unsigned table[256])
51 table[1] = h = CRCPOLY;
53 for (i = 2; i < 256; i *= 2) {
54 if ((h <<= 1) & 0x1000000)
56 for (j = 0; j < i; j++)
57 table[i + j] = table[j] ^ h;
61 int main(int argc, char *argv[])
67 for (i = 0; i < 256; i++) {
68 printf("0x%08X, ", table[i]);
77 static const unsigned crc24q[256] = {
78 0x00000000, 0x01864CFB, 0x028AD50D, 0x030C99F6,
79 0x0493E6E1, 0x0515AA1A, 0x061933EC, 0x079F7F17,
80 0x08A18139, 0x0927CDC2, 0x0A2B5434, 0x0BAD18CF,
81 0x0C3267D8, 0x0DB42B23, 0x0EB8B2D5, 0x0F3EFE2E,
82 0x10C54E89, 0x11430272, 0x124F9B84, 0x13C9D77F,
83 0x1456A868, 0x15D0E493, 0x16DC7D65, 0x175A319E,
84 0x1864CFB0, 0x19E2834B, 0x1AEE1ABD, 0x1B685646,
85 0x1CF72951, 0x1D7165AA, 0x1E7DFC5C, 0x1FFBB0A7,
86 0x200CD1E9, 0x218A9D12, 0x228604E4, 0x2300481F,
87 0x249F3708, 0x25197BF3, 0x2615E205, 0x2793AEFE,
88 0x28AD50D0, 0x292B1C2B, 0x2A2785DD, 0x2BA1C926,
89 0x2C3EB631, 0x2DB8FACA, 0x2EB4633C, 0x2F322FC7,
90 0x30C99F60, 0x314FD39B, 0x32434A6D, 0x33C50696,
91 0x345A7981, 0x35DC357A, 0x36D0AC8C, 0x3756E077,
92 0x38681E59, 0x39EE52A2, 0x3AE2CB54, 0x3B6487AF,
93 0x3CFBF8B8, 0x3D7DB443, 0x3E712DB5, 0x3FF7614E,
94 0x4019A3D2, 0x419FEF29, 0x429376DF, 0x43153A24,
95 0x448A4533, 0x450C09C8, 0x4600903E, 0x4786DCC5,
96 0x48B822EB, 0x493E6E10, 0x4A32F7E6, 0x4BB4BB1D,
97 0x4C2BC40A, 0x4DAD88F1, 0x4EA11107, 0x4F275DFC,
98 0x50DCED5B, 0x515AA1A0, 0x52563856, 0x53D074AD,
99 0x544F0BBA, 0x55C94741, 0x56C5DEB7, 0x5743924C,
100 0x587D6C62, 0x59FB2099, 0x5AF7B96F, 0x5B71F594,
101 0x5CEE8A83, 0x5D68C678, 0x5E645F8E, 0x5FE21375,
102 0x6015723B, 0x61933EC0, 0x629FA736, 0x6319EBCD,
103 0x648694DA, 0x6500D821, 0x660C41D7, 0x678A0D2C,
104 0x68B4F302, 0x6932BFF9, 0x6A3E260F, 0x6BB86AF4,
105 0x6C2715E3, 0x6DA15918, 0x6EADC0EE, 0x6F2B8C15,
106 0x70D03CB2, 0x71567049, 0x725AE9BF, 0x73DCA544,
107 0x7443DA53, 0x75C596A8, 0x76C90F5E, 0x774F43A5,
108 0x7871BD8B, 0x79F7F170, 0x7AFB6886, 0x7B7D247D,
109 0x7CE25B6A, 0x7D641791, 0x7E688E67, 0x7FEEC29C,
110 0x803347A4, 0x81B50B5F, 0x82B992A9, 0x833FDE52,
111 0x84A0A145, 0x8526EDBE, 0x862A7448, 0x87AC38B3,
112 0x8892C69D, 0x89148A66, 0x8A181390, 0x8B9E5F6B,
113 0x8C01207C, 0x8D876C87, 0x8E8BF571, 0x8F0DB98A,
114 0x90F6092D, 0x917045D6, 0x927CDC20, 0x93FA90DB,
115 0x9465EFCC, 0x95E3A337, 0x96EF3AC1, 0x9769763A,
116 0x98578814, 0x99D1C4EF, 0x9ADD5D19, 0x9B5B11E2,
117 0x9CC46EF5, 0x9D42220E, 0x9E4EBBF8, 0x9FC8F703,
118 0xA03F964D, 0xA1B9DAB6, 0xA2B54340, 0xA3330FBB,
119 0xA4AC70AC, 0xA52A3C57, 0xA626A5A1, 0xA7A0E95A,
120 0xA89E1774, 0xA9185B8F, 0xAA14C279, 0xAB928E82,
121 0xAC0DF195, 0xAD8BBD6E, 0xAE872498, 0xAF016863,
122 0xB0FAD8C4, 0xB17C943F, 0xB2700DC9, 0xB3F64132,
123 0xB4693E25, 0xB5EF72DE, 0xB6E3EB28, 0xB765A7D3,
124 0xB85B59FD, 0xB9DD1506, 0xBAD18CF0, 0xBB57C00B,
125 0xBCC8BF1C, 0xBD4EF3E7, 0xBE426A11, 0xBFC426EA,
126 0xC02AE476, 0xC1ACA88D, 0xC2A0317B, 0xC3267D80,
127 0xC4B90297, 0xC53F4E6C, 0xC633D79A, 0xC7B59B61,
128 0xC88B654F, 0xC90D29B4, 0xCA01B042, 0xCB87FCB9,
129 0xCC1883AE, 0xCD9ECF55, 0xCE9256A3, 0xCF141A58,
130 0xD0EFAAFF, 0xD169E604, 0xD2657FF2, 0xD3E33309,
131 0xD47C4C1E, 0xD5FA00E5, 0xD6F69913, 0xD770D5E8,
132 0xD84E2BC6, 0xD9C8673D, 0xDAC4FECB, 0xDB42B230,
133 0xDCDDCD27, 0xDD5B81DC, 0xDE57182A, 0xDFD154D1,
134 0xE026359F, 0xE1A07964, 0xE2ACE092, 0xE32AAC69,
135 0xE4B5D37E, 0xE5339F85, 0xE63F0673, 0xE7B94A88,
136 0xE887B4A6, 0xE901F85D, 0xEA0D61AB, 0xEB8B2D50,
137 0xEC145247, 0xED921EBC, 0xEE9E874A, 0xEF18CBB1,
138 0xF0E37B16, 0xF16537ED, 0xF269AE1B, 0xF3EFE2E0,
139 0xF4709DF7, 0xF5F6D10C, 0xF6FA48FA, 0xF77C0401,
140 0xF842FA2F, 0xF9C4B6D4, 0xFAC82F22, 0xFB4E63D9,
141 0xFCD11CCE, 0xFD575035, 0xFE5BC9C3, 0xFFDD8538,
144 unsigned crc24q_hash(unsigned char *data, int len)
149 for (i = 0; i < len; i++) {
150 crc = (crc << 8) ^ crc24q[data[i] ^ (unsigned char)(crc >> 16)];
153 crc = (crc & 0x00ffffff);
158 #define LO(x) (unsigned char)((x) & 0xff)
159 #define MID(x) (unsigned char)(((x) >> 8) & 0xff)
160 #define HI(x) (unsigned char)(((x) >> 16) & 0xff)
162 void crc24q_sign(unsigned char *data, int len)
164 unsigned crc = crc24q_hash(data, len);
167 data[len + 1] = MID(crc);
168 data[len + 2] = LO(crc);
171 bool crc24q_check(unsigned char *data, int len)
173 unsigned crc = crc24q_hash(data, len - 3);
175 return (((data[len - 3] == HI(crc)) &&
176 (data[len - 2] == MID(crc)) && (data[len - 1] == LO(crc))));