static void blowfish_lsb_decrypt_cbc(unsigned char *blk, int len, BlowfishContext * ctx) { word32 xL, xR, out[2], iv0, iv1; assert((len & 7) == 0); iv0 = ctx->iv0; iv1 = ctx->iv1; while (len > 0) { xL = GET_32BIT_LSB_FIRST(blk); xR = GET_32BIT_LSB_FIRST(blk + 4); blowfish_decrypt(xL, xR, out, ctx); iv0 ^= out[0]; iv1 ^= out[1]; PUT_32BIT_LSB_FIRST(blk, iv0); PUT_32BIT_LSB_FIRST(blk + 4, iv1); iv0 = xL; iv1 = xR; blk += 8; len -= 8; } ctx->iv0 = iv0; ctx->iv1 = iv1; }
void blowfish_decrypt_cbc(uint8 *blk, int len, BlowfishContext *ctx) { uint32 xL, xR, out[2], iv0, iv1; Assert((len & 7) == 0); iv0 = ctx->iv0; iv1 = ctx->iv1; while (len > 0) { xL = GET_32BIT_MSB_FIRST(blk); xR = GET_32BIT_MSB_FIRST(blk + 4); blowfish_decrypt(xL, xR, out, ctx); iv0 ^= out[0]; iv1 ^= out[1]; PUT_32BIT_MSB_FIRST(blk, iv0); PUT_32BIT_MSB_FIRST(blk + 4, iv1); iv0 = xL; iv1 = xR; blk += 8; len -= 8; } ctx->iv0 = iv0; ctx->iv1 = iv1; }
DECLARE_TEST(blowfish, random_data) { uint64_t plaintext[2][1024]; uint64_t keytext[32]; unsigned int i, j; blowfish_t* blowfish; uint64_t init_vector; blowfish = blowfish_allocate(); for (i = 0; i < 1024; ++i) { for (j = 0; j < 32; ++j) keytext[j] = random64(); for (j = 0; j < 1024; ++j) { plaintext[0][j] = random64(); plaintext[1][j] = plaintext[0][j]; } init_vector = random64(); blowfish_initialize(blowfish, keytext, random32_range(1, 32 * 8)); blowfish_encrypt(blowfish, plaintext[0], 1024 * 8, BLOCKCIPHER_ECB, init_vector); blowfish_decrypt(blowfish, plaintext[0], 1024 * 8, BLOCKCIPHER_ECB, init_vector); EXPECT_EQ(memcmp(plaintext[0], plaintext[1], 1024 * 8), 0); blowfish_encrypt(blowfish, plaintext[0], 1024 * 8, BLOCKCIPHER_CBC, init_vector); blowfish_decrypt(blowfish, plaintext[0], 1024 * 8, BLOCKCIPHER_CBC, init_vector); EXPECT_EQ(memcmp(plaintext[0], plaintext[1], 1024 * 8), 0); blowfish_encrypt(blowfish, plaintext[0], 1024 * 8, BLOCKCIPHER_CFB, init_vector); blowfish_decrypt(blowfish, plaintext[0], 1024 * 8, BLOCKCIPHER_CFB, init_vector); EXPECT_EQ(memcmp(plaintext[0], plaintext[1], 1024 * 8), 0); blowfish_encrypt(blowfish, plaintext[0], 1024 * 8, BLOCKCIPHER_OFB, init_vector); blowfish_decrypt(blowfish, plaintext[0], 1024 * 8, BLOCKCIPHER_OFB, init_vector); EXPECT_EQ(memcmp(plaintext[0], plaintext[1], 1024 * 8), 0); } blowfish_deallocate(blowfish); return 0; }
/*********************** FUNCTION DEFINITIONS ***********************/ int blowfish_test(void) { BYTE key1[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; BYTE key2[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; BYTE key3[24] = {0xF0,0xE1,0xD2,0xC3,0xB4,0xA5,0x96,0x87, 0x78,0x69,0x5A,0x4B,0x3C,0x2D,0x1E,0x0F, 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; BYTE p1[BLOWFISH_BLOCK_SIZE] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; BYTE p2[BLOWFISH_BLOCK_SIZE] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; BYTE p3[BLOWFISH_BLOCK_SIZE] = {0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10}; BYTE c1[BLOWFISH_BLOCK_SIZE] = {0x4e,0xf9,0x97,0x45,0x61,0x98,0xdd,0x78}; BYTE c2[BLOWFISH_BLOCK_SIZE] = {0x51,0x86,0x6f,0xd5,0xb8,0x5e,0xcb,0x8a}; BYTE c3[BLOWFISH_BLOCK_SIZE] = {0x05,0x04,0x4b,0x62,0xfa,0x52,0xd0,0x80}; BYTE enc_buf[BLOWFISH_BLOCK_SIZE]; BLOWFISH_KEY key; int pass = 1; // Test vector 1. blowfish_key_setup(key1, &key, BLOWFISH_BLOCK_SIZE); blowfish_encrypt(p1, enc_buf, &key); pass = pass && !memcmp(c1, enc_buf, BLOWFISH_BLOCK_SIZE); blowfish_decrypt(c1, enc_buf, &key); pass = pass && !memcmp(p1, enc_buf, BLOWFISH_BLOCK_SIZE); // Test vector 2. blowfish_key_setup(key2, &key, BLOWFISH_BLOCK_SIZE); blowfish_encrypt(p2, enc_buf, &key); pass = pass && !memcmp(c2, enc_buf, BLOWFISH_BLOCK_SIZE); blowfish_decrypt(c2, enc_buf, &key); pass = pass && !memcmp(p2, enc_buf, BLOWFISH_BLOCK_SIZE); // Test vector 3. blowfish_key_setup(key3, &key, 24); blowfish_encrypt(p3, enc_buf, &key); pass = pass && !memcmp(c3, enc_buf, BLOWFISH_BLOCK_SIZE); blowfish_decrypt(c3, enc_buf, &key); pass = pass && !memcmp(p3, enc_buf, BLOWFISH_BLOCK_SIZE); return(pass); }
DECLARE_TEST(blowfish, known_data) { unsigned char plaintext[2][NUM_VARIABLEKEYTESTS * 8]; unsigned int i; blowfish_t* blowfish; uint64_t init_vector = 0x54A23F87BE3147C3; blowfish = blowfish_allocate(); for (i = 0; i < NUM_VARIABLEKEYTESTS; ++i) { memcpy(&plaintext[0][(8 * i) + 0 ], &_test_plaintext_left[i], 4); memcpy(&plaintext[0][(8 * i) + 4 ], &_test_plaintext_right[i], 4); } memcpy(plaintext[1], plaintext[0], NUM_VARIABLEKEYTESTS * 8); for (i = 0; i < NUM_VARIABLEKEYTESTS; ++i) { blowfish_initialize(blowfish, _test_key_variable[i], 8); //Add some unalignment to size of buffer to test re-alignment in implementation blowfish_encrypt(blowfish, plaintext[0], 1 + NUM_VARIABLEKEYTESTS * 8, BLOCKCIPHER_ECB, init_vector); blowfish_decrypt(blowfish, plaintext[0], 2 + NUM_VARIABLEKEYTESTS * 8, BLOCKCIPHER_ECB, init_vector); EXPECT_EQ(memcmp(plaintext[0], plaintext[1], NUM_VARIABLEKEYTESTS * 8), 0); blowfish_encrypt(blowfish, plaintext[0], 3 + NUM_VARIABLEKEYTESTS * 8, BLOCKCIPHER_CBC, init_vector); blowfish_decrypt(blowfish, plaintext[0], 4 + NUM_VARIABLEKEYTESTS * 8, BLOCKCIPHER_CBC, init_vector); EXPECT_EQ(memcmp(plaintext[0], plaintext[1], NUM_VARIABLEKEYTESTS * 8), 0); blowfish_encrypt(blowfish, plaintext[0], 5 + NUM_VARIABLEKEYTESTS * 8, BLOCKCIPHER_CFB, init_vector); blowfish_decrypt(blowfish, plaintext[0], 6 + NUM_VARIABLEKEYTESTS * 8, BLOCKCIPHER_CFB, init_vector); EXPECT_EQ(memcmp(plaintext[0], plaintext[1], NUM_VARIABLEKEYTESTS * 8), 0); blowfish_encrypt(blowfish, plaintext[0], 7 + NUM_VARIABLEKEYTESTS * 8, BLOCKCIPHER_OFB, init_vector); blowfish_decrypt(blowfish, plaintext[0], NUM_VARIABLEKEYTESTS * 8, BLOCKCIPHER_OFB, init_vector); EXPECT_EQ(memcmp(plaintext[0], plaintext[1], NUM_VARIABLEKEYTESTS * 8), 0); init_vector *= (uintptr_t)blowfish; } blowfish_deallocate(blowfish); return 0; }
void blowfish_decrypt_ecb(uint8 *blk, int len, BlowfishContext *ctx) { uint32 xL, xR, out[2]; Assert((len & 7) == 0); while (len > 0) { xL = GET_32BIT_MSB_FIRST(blk); xR = GET_32BIT_MSB_FIRST(blk + 4); blowfish_decrypt(xL, xR, out, ctx); PUT_32BIT_MSB_FIRST(blk, out[0]); PUT_32BIT_MSB_FIRST(blk + 4, out[1]); blk += 8; len -= 8; } }
IoObject *IoBlowfish_process(IoBlowfish *self, IoObject *locals, IoMessage *m) { /*doc Blowfish process Process the inputBuffer and appends the result to the outputBuffer. The processed inputBuffer is empties except for the spare bytes at the end which don't fit into a cipher block. */ blowfish_ctx *context = &(DATA(self)->context); int isEncrypting = DATA(self)->isEncrypting; UArray *input = IoObject_rawGetMutableUArraySlot(self, locals, m, IOSYMBOL("inputBuffer")); UArray *output = IoObject_rawGetMutableUArraySlot(self, locals, m, IOSYMBOL("outputBuffer")); const unsigned char *inputBytes = (uint8_t *)UArray_bytes(input); size_t inputSize = UArray_sizeInBytes(input); unsigned long lr[2]; size_t i, runs = inputSize / sizeof(lr); for (i = 0; i < runs; i ++) { memcpy(lr, inputBytes, sizeof(lr)); inputBytes += sizeof(lr); if (isEncrypting) { blowfish_encrypt(context, &lr[0], &lr[1]); } else { blowfish_decrypt(context, &lr[0], &lr[1]); } UArray_appendBytes_size_(output, (unsigned char *)&lr, sizeof(lr)); } UArray_removeRange(input, 0, runs * sizeof(lr)); return self; }
int main(int argc, char *argv[]) { int i; struct blowfish_context *ctx; uint32_t tmp[2]; ctx = blowfish_context_new(); blowfish_set_p(ctx, newP); blowfish_set_key(ctx, (unsigned char*) "TESTKEY", 7); printf("\nbefore encr = "); for (i = 0; i < 8; i++) printf("%x.",((unsigned char*) var)[i]); memcpy(tmp, var, sizeof(var)); blowfish_encrypt(ctx, (uint32_t*) var); printf("\nafter encr = "); for (i = 0; i < 8; i++) printf("%x.",((unsigned char*) var)[i]); blowfish_decrypt(ctx,(uint32_t*) var); printf("\nafter decr = "); for (i = 0; i < 8; i++) printf("%x.",((unsigned char*) var)[i]); printf("\n"); if (strncmp((char*)tmp, (char*)var, sizeof(var))) printf("%s%s", "\n===================================", "\ntest failed!!!!!!!!!!\n\n===================================\n"); else printf("%s%s", "\n===================================", "\nTEST PASSED\n\n===================================\n"); return 0; }
IoObject *IoBlowfish_endProcessing(IoBlowfish *self, IoObject *locals, IoMessage *m) { /*doc Blowfish endProcessing Finish processing remaining bytes of inputBuffer. */ blowfish_ctx *context = &(DATA(self)->context); unsigned long lr[2]; IoBlowfish_process(self, locals, m); // process the full blocks first { int isEncrypting = DATA(self)->isEncrypting; UArray *input = IoObject_rawGetMutableUArraySlot(self, locals, m, IOSYMBOL("inputBuffer")); UArray *output = IoObject_rawGetMutableUArraySlot(self, locals, m, IOSYMBOL("outputBuffer")); IOASSERT(UArray_sizeInBytes(input) < sizeof(lr), "internal error - too many bytes left in inputBuffer"); memset(lr, 0, sizeof(lr)); memcpy(lr, (uint8_t *)UArray_bytes(input), UArray_sizeInBytes(input)); if (isEncrypting) { blowfish_encrypt(context, &lr[0], &lr[1]); } else { blowfish_decrypt(context, &lr[0], &lr[1]); } UArray_appendBytes_size_(output, (unsigned char *)&lr, sizeof(lr)); UArray_setSize_(input, 0); } return self; }