#include static unsigned long crctable[256]; static unsigned char crcinvtable[256]; void calc_crc_table(void) { unsigned long poly = 0xedb88320, value, idx, i; for (idx = 0 ; idx < 256 ; idx++) { for (value = idx, i = 0 ; i < 8 ; i++) { if (value & 1) { value >>= 1; value ^= poly; } else { value >>= 1; } } crctable[idx] = value; crcinvtable[value >> 24] = idx & 0xff; } } unsigned long calc_crc(char *buf, unsigned long buflen) { unsigned long crc = 0xffffffff; while (buflen--) crc = (crc >> 8) ^ crctable[*buf++ ^ crc & 0xff]; return ~crc; } static inline unsigned char l2c(unsigned long l, int nr) { return (l >> (8*(nr-1))) & 0xff; } void solve(char *buf, unsigned long buflen, unsigned long wcrc, unsigned char *a, unsigned char *b, unsigned char *c, unsigned char *d) { unsigned long crc = 0xffffffff; while (buflen--) crc = (crc >> 8) ^ crctable[*buf++ ^ crc & 0xff]; wcrc = ~wcrc; // sequence of crc's we must have to finish with wcrc unsigned long c1, c2, c3, c4; c4 = crctable[ crcinvtable[ l2c(wcrc, 4) ] ]; c3 = crctable[ crcinvtable[ l2c(wcrc, 3) ^ l2c(c4, 3) ] ]; c2 = crctable[ crcinvtable[ l2c(wcrc, 2) ^ l2c(c4, 2) ^ l2c(c3, 3) ] ]; c1 = crctable[ crcinvtable[ l2c(wcrc, 1) ^ l2c(c4, 1) ^ l2c(c3, 2) ^ l2c(c2, 3) ] ]; *a = crcinvtable[l2c(c1, 4)] ^ l2c(crc, 1); crc = (crc >> 8) ^ crctable[*a ^ crc & 0xff]; *b = crcinvtable[l2c(c2, 4)] ^ l2c(crc, 1); crc = (crc >> 8) ^ crctable[*b ^ crc & 0xff]; *c = crcinvtable[l2c(c3, 4)] ^ l2c(crc, 1); crc = (crc >> 8) ^ crctable[*c ^ crc & 0xff]; *d = crcinvtable[l2c(c4, 4)] ^ l2c(crc, 1); crc = (crc >> 8) ^ crctable[*d ^ crc & 0xff]; } static unsigned char mkhex(char c) { char oc = c; if (c < '0') goto err; c -= '0'; if (c <= 9) return c; if (c < 'A'-'0') goto err; c -= 'A'-'0'; if (c <= 6) return 10+c; if (c < 'a'-'A') goto err; c -= 'a' - 'A'; if (c <= 6) return 10+c; err: fprintf(stderr, "invalid character %c (%hhx)\n", oc, oc); exit(1); } static unsigned long interpol(char *src, char *dst, const unsigned long dstlen) { unsigned long i=0; register char c; while (*src && i < dstlen) { if ((c = *src++) == '\\') if ((c = *src++) == 'x') { c = mkhex(*src++) << 4; c |= mkhex(*src++); } else if (!c) break; dst[i++] = c; } return i; } static void test(void) { printf("crcinv for 0x28: %.8lX\n", crctable[crcinvtable[0x28]]); printf("decomp of 0x12345678: %.2X, %.2X, %.2X, %.2X\n", l2c(0x12345678, 4), l2c(0x12345678, 3), l2c(0x12345678, 2), l2c(0x12345678, 1)); printf("\n"); } int main(int argc, char **argv) { int i; char buf[256]; unsigned long buflen = 256; unsigned long wishcrc = 0; calc_crc_table(); if (argc < 2) { printf("usage: calc \n"); exit(0); } buflen = interpol(argv[1], buf, buflen); for (i=0 ; i<8 ; i++) wishcrc = wishcrc << 4 | mkhex(argv[2][i]); unsigned char a, b, c, d; solve(buf, buflen, wishcrc, &a, &b, &c, &d); printf("padding: %.2X %.2X %.2X %.2X\n", a, b, c, d); return 0; }