/* enc_stub.c - CBC encoder test stub - Don Yang (uguu.org) 01/04/05 */ #include #include #include #include #include #define BLOCK_COUNT 32 #define BLOCK_SIZE (BLOCK_COUNT * 4) #define KEY0 12345 #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 E(unsigned int *d) { unsigned int i; for(i = 0; i < BLOCK_COUNT; i++) d[i] ^= ~0U; } static void WriteBlock(FILE *outfile, unsigned int *d) { #ifdef BIG_ENDIAN unsigned int t[BLOCK_COUNT]; memcpy(t, d, BLOCK_SIZE); Bswap(t); (void)fwrite(t, BLOCK_SIZE, 1, outfile); #else (void)fwrite(d, BLOCK_SIZE, 1, outfile); #endif } int main(int argc, char **argv) { unsigned int d[2][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); /* Generate initialization vector. Because rand() is a common function and time can be guessed, the PRNG is seeded with part of the key to make it more random. */ srand((unsigned)time(NULL) ^ KEY0); for(i = 0; i < BLOCK_COUNT - 1; d[0][i++] = (unsigned int)rand()); /* Get file size, save it in last cell of initial vector. Because block size is random, saving this number at the last cell is better than saving it in the first cell. */ (void)fseek(infile, 0, SEEK_END); d[0][i] = filesize = (unsigned int)ftell(infile); (void)fseek(infile, 0, SEEK_SET); /* Write initialization vector. Because of this block, feeding an empty file to the encoder will easily reveal the block size used. Probably not a big deal depending on how the program will be used though. */ memcpy(d[1], d[0], BLOCK_SIZE); E(d[1]); WriteBlock(outfile, d[1]); b = 0; /* Write padding block */ if( (filesize % BLOCK_SIZE) != 0 ) { for(i = 0; i < BLOCK_COUNT; d[1][i++] = (unsigned int)rand()); i = filesize % BLOCK_SIZE; (void)fread((unsigned char*)d[1] + BLOCK_SIZE - i, (size_t)i, 1, infile); #ifdef BIG_ENDIAN Bswap(d[1]); #endif for(i = 0; i < BLOCK_COUNT; i++) d[1][i] ^= d[0][i]; E(d[b = 1]); WriteBlock(outfile, d[1]); filesize -= filesize % BLOCK_SIZE; } /* Encrypt contents */ assert((filesize % BLOCK_SIZE) == 0); for(; filesize > 0; filesize -= BLOCK_SIZE) { (void)fread(d[b ^= 1], BLOCK_SIZE, 1, infile); for(i = 0; i < BLOCK_COUNT; i++) d[b][i] ^= d[b ^ 1][i]; E(d[b]); WriteBlock(outfile, d[b]); } (void)fclose(infile); (void)fclose(outfile); return 0; }