1 //author: Victor Mu~noz (vmunoz@ingenieria-inversa.cl
2 //license: the very same than radare, blah, blah
3 //some definitions and test cases borrowed from http://www.nightmare.com/~ryb/code/CrcMoose.py (Ray Burr)
4 
5 #include <r_hash.h>
6 
crc_init(R_CRC_CTX * ctx,utcrc crc,ut32 size,int reflect,utcrc poly,utcrc xout)7 void crc_init (R_CRC_CTX *ctx, utcrc crc, ut32 size, int reflect, utcrc poly, utcrc xout) {
8 	ctx->crc = crc;
9 	ctx->size = size;
10 	ctx->reflect = reflect;
11 	ctx->poly = poly;
12 	ctx->xout = xout;
13 }
14 
crc_update(R_CRC_CTX * ctx,const ut8 * data,ut32 sz)15 void crc_update (R_CRC_CTX *ctx, const ut8 *data, ut32 sz) {
16 	utcrc crc, d;
17 	int i, j;
18 
19 	crc = ctx->crc;
20 	for (i = 0; i < sz; i++) {
21 		d = data[i];
22 		if (ctx->reflect) {
23 			for (j = 0; j < 4; j++) {
24 				if (((d >> j) ^ (d >> (7 - j))) & 1) {
25 					d ^= (1 << j) ^ (1 << (7 - j));
26 				}
27 			}
28 		}
29 		crc ^= d << (ctx->size - 8);
30 		for (j = 0; j < 8; j++) {
31 			crc = ((crc >> (ctx->size - 1)) & 1? ctx->poly: 0) ^ (crc << 1);
32 		}
33 	}
34 	ctx->crc = crc;
35 }
36 
crc_final(R_CRC_CTX * ctx,utcrc * r)37 static void crc_final (R_CRC_CTX *ctx, utcrc *r) {
38 	utcrc crc;
39 	int i;
40 
41 	crc = ctx->crc;
42 	crc &= (((UTCRC_C(1) << (ctx->size - 1)) - 1) << 1) | 1;
43 	if (ctx->reflect) {
44 		for (i = 0; i < (ctx->size >> 1); i++) {
45 			if (((crc >> i) ^ (crc >> (ctx->size - 1 - i))) & 1) {
46 				crc ^= (UTCRC_C(1) << i) ^ (UTCRC_C(1) << (ctx->size - 1 - i));
47 			}
48 		}
49 	}
50 
51 	*r = crc ^ ctx->xout;
52 }
53 
54 /* preset initializer to provide compatibility */
55 #define CRC_PRESET(crc, size, reflect, poly, xout) \
56 	{ UTCRC_C(crc), (size), (reflect), UTCRC_C(poly), UTCRC_C(xout) }
57 
58 /* NOTE: Run `rahash2 -a <algo> -s 123456789` to test CRC. */
59 R_CRC_CTX crc_presets[] = {
60 	CRC_PRESET (0x00      ,  8, 0, 0x07      , 0x00 ),       //CRC-8-SMBUS, test vector for "1234567892: f4
61 #if R_HAVE_CRC8_EXTRA
62 	CRC_PRESET (0xFF      ,  8, 0, 0x9B      , 0x00 ),       //CRC-8/CDMA2000,     test vector for "123456789": 0xda
63 	CRC_PRESET (0x00      ,  8, 1, 0x39      , 0x00 ),       //CRC-8/DARC,         test vector for "123456789": 0x15
64 	CRC_PRESET (0x00      ,  8, 0, 0xD5      , 0x00 ),       //CRC-8/DVB-S2,       test vector for "123456789": 0xbc
65 	CRC_PRESET (0xFF      ,  8, 1, 0x1D      , 0x00 ),       //CRC-8/EBU,          test vector for "123456789": 0x97
66 	CRC_PRESET (0xFD      ,  8, 0, 0x1D      , 0x00 ),       //CRC-8/I-CODE,       test vector for "123456789": 0x7e
67 	CRC_PRESET (0x00      ,  8, 0, 0x07      , 0x55 ),       //CRC-8/ITU,          test vector for "123456789": 0xa1
68 	CRC_PRESET (0x00      ,  8, 1, 0x31      , 0x00 ),       //CRC-8/MAXIM,        test vector for "123456789": 0xa1
69 	CRC_PRESET (0xFF      ,  8, 1, 0x07      , 0x00 ),       //CRC-8/ROHC,         test vector for "123456789": 0xd0
70 	CRC_PRESET (0x00      ,  8, 1, 0x9B      , 0x00 ),       //CRC-8/WCDMA,        test vector for "123456789": 0x25
71 #endif /* #if R_HAVE_CRC8_EXTRA */
72 
73 #if R_HAVE_CRC15_EXTRA
74 	CRC_PRESET (0x0000    , 15, 0, 0x4599    , 0x0000 ),     //CRC-15-CAN, test vector for "1234567892: 059e
75 #endif /* #if R_HAVE_CRC15_EXTRA */
76 
77 	CRC_PRESET (0x0000    , 16, 1, 0x8005    , 0x0000 ),     //CRC-16-IBM (CRC-16/ARC), test vector for "1234567892: bb3d
78 	CRC_PRESET (0xFFFF    , 16, 0, 0x1021    , 0x0000 ),     //CRC-16-CITT (CRC-16/CCITT-FALSE), test vector for "1234567892: 29b1
79 	CRC_PRESET (0xFFFF    , 16, 1, 0x8005    , 0xFFFF ),     //CRC-16-USB, test vector for "1234567892:  b4c8
80 	CRC_PRESET (0xFFFF    , 16, 1, 0x1021    , 0xFFFF ),     //CRC-HDLC, test vector for "1234567892: 906e
81 #if R_HAVE_CRC16_EXTRA
82 	CRC_PRESET (0x1D0F    , 16, 0, 0x1021    , 0x0000 ),     //CRC-16/AUG-CCITT,   test vector for "123456789": 0xe5cc
83 	CRC_PRESET (0x0000    , 16, 0, 0x8005    , 0x0000 ),     //CRC-16/BUYPASS,     test vector for "123456789": 0xfee8
84 	CRC_PRESET (0xFFFF    , 16, 0, 0xC867    , 0x0000 ),     //CRC-16/CDMA2000,    test vector for "123456789": 0x4c06
85 	CRC_PRESET (0x800D    , 16, 0, 0x8005    , 0x0000 ),     //CRC-16/DDS110,      test vector for "123456789": 0x9ecf
86 	CRC_PRESET (0x0000    , 16, 0, 0x0589    , 0x0001 ),     //CRC-16/DECT-R,      test vector for "123456789": 0x007e
87 	CRC_PRESET (0x0000    , 16, 0, 0x0589    , 0x0000 ),     //CRC-16/DECT-X,      test vector for "123456789": 0x007f
88 	CRC_PRESET (0x0000    , 16, 1, 0x3D65    , 0xFFFF ),     //CRC-16/DNP,         test vector for "123456789": 0xea82
89 	CRC_PRESET (0x0000    , 16, 0, 0x3D65    , 0xFFFF ),     //CRC-16/EN-13757,    test vector for "123456789": 0xc2b7
90 	CRC_PRESET (0xFFFF    , 16, 0, 0x1021    , 0xFFFF ),     //CRC-16/GENIBUS,     test vector for "123456789": 0xd64e
91 	CRC_PRESET (0x0000    , 16, 1, 0x8005    , 0xFFFF ),     //CRC-16/MAXIM,       test vector for "123456789": 0x44c2
92 	CRC_PRESET (0xFFFF    , 16, 1, 0x1021    , 0x0000 ),     //CRC-16/MCRF4XX,     test vector for "123456789": 0x6f91
93 	CRC_PRESET (0xB2AA    , 16, 1, 0x1021    , 0x0000 ),     //CRC-16/RIELLO,      test vector for "123456789": 0x63d0
94 	CRC_PRESET (0x0000    , 16, 0, 0x8BB7    , 0x0000 ),     //CRC-16/T10-DIF,     test vector for "123456789": 0xd0db
95 	CRC_PRESET (0x0000    , 16, 0, 0xA097    , 0x0000 ),     //CRC-16/TELEDISK,    test vector for "123456789": 0x0fb3
96 	CRC_PRESET (0x89EC    , 16, 1, 0x1021    , 0x0000 ),     //CRC-16/TMS37157,    test vector for "123456789": 0x26b1
97 	CRC_PRESET (0xC6C6    , 16, 1, 0x1021    , 0x0000 ),     //CRC-A,              test vector for "123456789": 0xbf05
98 	CRC_PRESET (0x0000    , 16, 1, 0x1021    , 0x0000 ),     //CRC-16/KERMIT,      test vector for "123456789": 0x2189
99 	CRC_PRESET (0xFFFF    , 16, 1, 0x8005    , 0x0000 ),     //CRC-16/MODBUS,      test vector for "123456789": 0x4b37
100 	CRC_PRESET (0xFFFF    , 16, 1, 0x1021    , 0xFFFF ),     //CRC-16/X-25,        test vector for "123456789": 0x906e
101 	CRC_PRESET (0x0000    , 16, 0, 0x1021    , 0x0000 ),     //CRC-16/XMODEM,      test vector for "123456789": 0x31c3
102 #endif /* #if R_HAVE_CRC16_EXTRA */
103 
104 #if R_HAVE_CRC24
105 	CRC_PRESET (0xB704CE  , 24, 0, 0x864CFB  , 0x000000 ),   //CRC-24, test vector for "1234567892: 21cf02
106 #endif /* #if R_HAVE_CRC24 */
107 
108 	CRC_PRESET (0xFFFFFFFF, 32, 1, 0x04C11DB7, 0xFFFFFFFF ), //CRC-32, test vector for "1234567892: cbf43926
109 	CRC_PRESET (0x00000000, 32, 0, 0x80000011, 0x00000000 ), //CRC-32-ECMA-267 (EDC for DVD sectors), test vector for "1234567892: b27ce117
110 	CRC_PRESET (0xFFFFFFFF, 32, 1, 0x1EDC6F41, 0xFFFFFFFF ), //CRC-32C, test vector for "1234567892: e3069283
111 #if R_HAVE_CRC32_EXTRA
112 	CRC_PRESET (0xFFFFFFFF, 32, 0, 0x04C11DB7, 0xFFFFFFFF ), //CRC-32/BZIP2,       test vector for "123456789": 0xfc891918
113 	CRC_PRESET (0xFFFFFFFF, 32, 1, 0xA833982B, 0xFFFFFFFF ), //CRC-32D,            test vector for "123456789": 0x87315576
114 	CRC_PRESET (0xFFFFFFFF, 32, 0, 0x04C11DB7, 0x00000000 ), //CRC-32/MPEG2,       test vector for "123456789": 0x0376e6e7
115 	CRC_PRESET (0x00000000, 32, 0, 0x04C11DB7, 0xFFFFFFFF ), //CRC-32/POSIX,       test vector for "123456789": 0x765e7680
116 	CRC_PRESET (0x00000000, 32, 0, 0x814141AB, 0x00000000 ), //CRC-32Q,            test vector for "123456789": 0x3010bf7f
117 	CRC_PRESET (0xFFFFFFFF, 32, 1, 0x04C11DB7, 0x00000000 ), //CRC-32/JAMCRC,      test vector for "123456789": 0x340bc6d9
118 	CRC_PRESET (0x00000000, 32, 0, 0x000000AF, 0x00000000 ), //CRC-32/XFER,        test vector for "123456789": 0xbd0be338
119 #endif /* #if R_HAVE_CRC32_EXTRA */
120 
121 #if R_HAVE_CRC64
122 	CRC_PRESET (0x0000000000000000, 64, 0, 0x42F0E1EBA9EA3693, 0x0000000000000000 ), //CRC-64, check: 0x6c40df5f0b497347
123 #endif /* #if R_HAVE_CRC64 */
124 #if R_HAVE_CRC64_EXTRA
125 	CRC_PRESET (0x0000000000000000, 64, 0, 0x42F0E1EBA9EA3693, 0x0000000000000000 ), //CRC-64/ECMA-182, check: 0x6c40df5f0b497347
126 	CRC_PRESET (0xFFFFFFFFFFFFFFFF, 64, 0, 0x42F0E1EBA9EA3693, 0xFFFFFFFFFFFFFFFF ), //CRC-64/WE, check: 0x62ec59e3f1a4f00a
127 	CRC_PRESET (0xFFFFFFFFFFFFFFFF, 64, 1, 0x42F0E1EBA9EA3693, 0xFFFFFFFFFFFFFFFF ), //CRC-64/XZ, check: 0x995dc9bbdf1939fa
128 	CRC_PRESET (0xFFFFFFFFFFFFFFFF, 64, 1, 0x000000000000001b, 0xFFFFFFFFFFFFFFFF ), //CRC-64/ISO, check: 0xb90956c775a41001
129 #endif /* #if R_HAVE_CRC64_EXTRA */
130 };
131 
crc_init_preset(R_CRC_CTX * ctx,enum CRC_PRESETS preset)132 void crc_init_preset (R_CRC_CTX *ctx, enum CRC_PRESETS preset) {
133 	ctx->crc = crc_presets[preset].crc;
134 	ctx->size = crc_presets[preset].size;
135 	ctx->reflect = crc_presets[preset].reflect;
136 	ctx->poly = crc_presets[preset].poly;
137 	ctx->xout = crc_presets[preset].xout;
138 }
139 
r_hash_crc_preset(const ut8 * data,ut32 size,enum CRC_PRESETS preset)140 utcrc r_hash_crc_preset (const ut8 *data, ut32 size, enum CRC_PRESETS preset) {
141 	if (!data || !size || preset >= CRC_PRESET_SIZE) {
142 		return 0;
143 	}
144 	utcrc r;
145 	R_CRC_CTX crcctx;
146 	crc_init_preset (&crcctx, preset);
147 	crc_update (&crcctx, data, size);
148 	crc_final (&crcctx, &r);
149 	return r;
150 }
151 
152 
153 
154