/* dec_stub.c - CBC decoder test stub - Don Yang (uguu.org) 01/04/05 */ #include #include #include #include #define BLOCK_COUNT 32 #define BLOCK_SIZE (BLOCK_COUNT * 4) #ifdef BIG_ENDIAN static void Bswap(unsigned int *d) { int i; for(i = 0; i < BLOCK_COUNT; i++) { *d = ((*d >> 24) & 0x000000ff) | ((*d >> 8) & 0x0000ff00) | ((*d << 8) & 0x00ff0000) | ((*d << 24) & 0xff000000); d++; } } #endif static void D(unsigned int *d) { unsigned int i; for(i = 0; i < BLOCK_COUNT; i++) d[i] ^= ~0U; } static void ReadBlock(FILE *infile, /*@out@*/unsigned int *d) { (void)fread(d, BLOCK_SIZE, 1, infile); #ifdef BIG_ENDIAN Bswap(d); #endif } int main(int argc, char **argv) { unsigned int d[2][BLOCK_COUNT], p[BLOCK_COUNT], filesize, i, b; FILE *infile, *outfile; if( argc < 3 ) return printf("%s \n", *argv); if( (infile = fopen(*++argv, "rb")) == NULL ) return printf("Can not open %s\n", *argv); if( (outfile = fopen(*++argv, "wb+")) == NULL ) return printf("Can not create %s\n", *argv); /* Get file size */ (void)fseek(infile, 0, SEEK_END); filesize = (unsigned int)ftell(infile); (void)fseek(infile, 0, SEEK_SET); if( filesize < BLOCK_SIZE || (filesize % BLOCK_SIZE) != 0 ) return puts("Decrypt error"); /* Read initialization vector */ ReadBlock(infile, d[0]); D(d[b = 0]); memcpy(p, d[0], BLOCK_SIZE); /* Check file size */ if( p[BLOCK_COUNT - 1] <= filesize - BLOCK_SIZE * 2 || p[BLOCK_COUNT - 1] > filesize - BLOCK_SIZE ) return puts("Decrypt error"); filesize = p[BLOCK_COUNT - 1]; /* Read padding */ if( (filesize % BLOCK_SIZE) != 0 ) { ReadBlock(infile, d[1]); memcpy(p, d[b = 1], BLOCK_SIZE); D(p); for(i = 0; i < BLOCK_COUNT; i++) p[i] ^= d[0][i]; i = filesize % BLOCK_SIZE; #ifdef BIG_ENDIAN Bswap(p); #endif (void)fwrite((unsigned char*)p + BLOCK_SIZE - i, (size_t)i, 1, outfile); filesize -= i; } /* Decrypt contents */ assert((filesize % BLOCK_SIZE) == 0); for(; filesize > 0; filesize -= BLOCK_SIZE) { ReadBlock(infile, d[b ^= 1]); memcpy(p, d[b], BLOCK_SIZE); D(p); for(i = 0; i < BLOCK_COUNT; i++) p[i] ^= d[b ^ 1][i]; (void)fwrite(p, BLOCK_SIZE, 1, outfile); } (void)fclose(infile); (void)fclose(outfile); return 0; }