Example #1
0
void blowfish_key_setup(const BYTE user_key[], BLOWFISH_KEY *keystruct, size_t len)
{
   BYTE block[8];
   int idx,idx2;

   // Copy over the constant init array vals (so the originals aren't destroyed).
   memcpy(keystruct->p,p_perm,sizeof(WORD) * 18);
   memcpy(keystruct->s,s_perm,sizeof(WORD) * 1024);

   // Combine the key with the P box. Assume key is standard 448 bits (56 bytes) or less.
   for (idx = 0, idx2 = 0; idx < 18; ++idx, idx2 += 4)
      keystruct->p[idx] ^= (user_key[idx2 % len] << 24) | (user_key[(idx2+1) % len] << 16)
                           | (user_key[(idx2+2) % len] << 8) | (user_key[(idx2+3) % len]);
   // Re-calculate the P box.
   memset(block, 0, 8);
   for (idx = 0; idx < 18; idx += 2) {
      blowfish_encrypt(block,block,keystruct);
      keystruct->p[idx] = (block[0] << 24) | (block[1] << 16) | (block[2] << 8) | block[3];
      keystruct->p[idx+1]=(block[4] << 24) | (block[5] << 16) | (block[6] << 8) | block[7];
   }
   // Recalculate the S-boxes.
   for (idx = 0; idx < 4; ++idx) {
      for (idx2 = 0; idx2 < 256; idx2 += 2) {
         blowfish_encrypt(block,block,keystruct);
         keystruct->s[idx][idx2] = (block[0] << 24) | (block[1] << 16) |
                                   (block[2] << 8) | block[3];
         keystruct->s[idx][idx2+1] = (block[4] << 24) | (block[5] << 16) |
                                     (block[6] << 8) | block[7];
      }
   }
}
Example #2
0
static void blowfish_setkey(BlowfishContext * ctx,
			    const unsigned char *key, short keybytes)
{
    word32 *S0 = ctx->S0;
    word32 *S1 = ctx->S1;
    word32 *S2 = ctx->S2;
    word32 *S3 = ctx->S3;
    word32 *P = ctx->P;
    word32 str[2];
    int i;

    for (i = 0; i < 18; i++) {
	P[i] = parray[i];
	P[i] ^=
	    ((word32) (unsigned char) (key[(i * 4 + 0) % keybytes])) << 24;
	P[i] ^=
	    ((word32) (unsigned char) (key[(i * 4 + 1) % keybytes])) << 16;
	P[i] ^=
	    ((word32) (unsigned char) (key[(i * 4 + 2) % keybytes])) << 8;
	P[i] ^= ((word32) (unsigned char) (key[(i * 4 + 3) % keybytes]));
    }

    for (i = 0; i < 256; i++) {
	S0[i] = sbox0[i];
	S1[i] = sbox1[i];
	S2[i] = sbox2[i];
	S3[i] = sbox3[i];
    }

    str[0] = str[1] = 0;

    for (i = 0; i < 18; i += 2) {
	blowfish_encrypt(str[0], str[1], str, ctx);
	P[i] = str[0];
	P[i + 1] = str[1];
    }

    for (i = 0; i < 256; i += 2) {
	blowfish_encrypt(str[0], str[1], str, ctx);
	S0[i] = str[0];
	S0[i + 1] = str[1];
    }
    for (i = 0; i < 256; i += 2) {
	blowfish_encrypt(str[0], str[1], str, ctx);
	S1[i] = str[0];
	S1[i + 1] = str[1];
    }
    for (i = 0; i < 256; i += 2) {
	blowfish_encrypt(str[0], str[1], str, ctx);
	S2[i] = str[0];
	S2[i + 1] = str[1];
    }
    for (i = 0; i < 256; i += 2) {
	blowfish_encrypt(str[0], str[1], str, ctx);
	S3[i] = str[0];
	S3[i + 1] = str[1];
    }
}
Example #3
0
static void blowfish_lsb_encrypt_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);
	iv0 ^= xL;
	iv1 ^= xR;
	blowfish_encrypt(iv0, iv1, out, ctx);
	iv0 = out[0];
	iv1 = out[1];
	PUT_32BIT_LSB_FIRST(blk, iv0);
	PUT_32BIT_LSB_FIRST(blk + 4, iv1);
	blk += 8;
	len -= 8;
    }

    ctx->iv0 = iv0;
    ctx->iv1 = iv1;
}
Example #4
0
File: blf.c Project: 50wu/gpdb
void
blowfish_encrypt_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);
		iv0 ^= xL;
		iv1 ^= xR;
		blowfish_encrypt(iv0, iv1, out, ctx);
		iv0 = out[0];
		iv1 = out[1];
		PUT_32BIT_MSB_FIRST(blk, iv0);
		PUT_32BIT_MSB_FIRST(blk + 4, iv1);
		blk += 8;
		len -= 8;
	}

	ctx->iv0 = iv0;
	ctx->iv1 = iv1;
}
Example #5
0
static void blowfish_msb_sdctr(unsigned char *blk, int len,
				     BlowfishContext * ctx)
{
    word32 b[2], iv0, iv1, tmp;

    assert((len & 7) == 0);

    iv0 = ctx->iv0;
    iv1 = ctx->iv1;

    while (len > 0) {
	blowfish_encrypt(iv0, iv1, b, ctx);
	tmp = GET_32BIT_MSB_FIRST(blk);
	PUT_32BIT_MSB_FIRST(blk, tmp ^ b[0]);
	tmp = GET_32BIT_MSB_FIRST(blk + 4);
	PUT_32BIT_MSB_FIRST(blk + 4, tmp ^ b[1]);
	if ((iv1 = (iv1 + 1) & 0xffffffff) == 0)
	    iv0 = (iv0 + 1) & 0xffffffff;
	blk += 8;
	len -= 8;
    }

    ctx->iv0 = iv0;
    ctx->iv1 = iv1;
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #8
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);
}
Example #9
0
void BLOWFISH_Base::generatePAndSBoxes(const unsigned char* key, size_t keySize, uint32_t* p, uint32_t* sboxes)
{
    for (size_t i = 0 ; i < 4 * 256; ++i)
        sboxes[i] = Init_SBoxes[i];

    for (size_t i = 0, j = 0; i < 18; ++i)
    {
        uint32_t data = 0x00000000;
        for (size_t k = 0; k < 4; ++k)
        {
            data = (data << 8) | (uint32_t)key[j];
            ++j;
            if (j >= keySize)
                j = 0;
        }

        p[i] = Init_P[i] ^ data;
    }

    uint32_t l = 0x00000000;
    uint32_t r = 0x00000000;

    for (size_t i = 0 ; i < 18 ; i += 2)
    {
        blowfish_encrypt(l, r, p, sboxes);

        p[i] = l;
        p[i + 1] = r;
    }

    for (size_t i = 0 ; i < 4 ; ++i)
    {
        for (size_t j = 0 ; j < 256; j += 2)
        {
            blowfish_encrypt(l, r, p, sboxes);

            sboxes[i * 256 + j] = l;
            sboxes[i * 256 + j + 1] = r;
        }
    }
}
Example #10
0
// Perform the key schedule for BlowFish32. This is esentially the encryption of
// a zero-block and using the result for successive values of the P and S
// subkeys until all subkeys have been filled out. The initial P keys are seeded
// with the key obtained from the user.
void blowfish_keygen() {
    size_t idx;

    // Initial block to encrypt
    int32_t block = 0x00000000;

    // XOR the key with the P subkey to get the first permutation
    for (idx = 0; idx < 18; idx++) {
        arr_p[idx] = arr_p[idx] ^ arr_key[idx];
    }

    // Complete the generation of the P subkey
    for (idx = 0; idx < 18; idx += 2) {
        block = blowfish_encrypt(block);
        arr_p[idx+0] = BIT16_HI(block);
        arr_p[idx+1] = BIT16_LO(block);
    }

    // Complete the generation of the S subkeys
    size_t sidx;
    for (sidx = 0; sidx < 4; sidx++) {
        uint16_t* arr_sx = NULL;
        switch (sidx) {
        case 0: arr_sx = arr_s1; break;
        case 1: arr_sx = arr_s2; break;
        case 2: arr_sx = arr_s3; break;
        case 3: arr_sx = arr_s4; break;
        }

        for (idx = 0; idx < 16; idx += 2) {
            block = blowfish_encrypt(block);
            arr_sx[idx+0] = BIT16_HI(block);
            arr_sx[idx+1] = BIT16_LO(block);
        }
    }
}
Example #11
0
void blowfish_lsb_encrypt_ecb(unsigned char *blk, int len,
                              BlowfishContext * ctx)
{
    word32 xL, xR, out[2];

    assert((len & 7) == 0);

    while (len > 0) {
	xL = GET_32BIT_LSB_FIRST(blk);
	xR = GET_32BIT_LSB_FIRST(blk + 4);
	blowfish_encrypt(xL, xR, out, ctx);
	PUT_32BIT_LSB_FIRST(blk, out[0]);
	PUT_32BIT_LSB_FIRST(blk + 4, out[1]);
	blk += 8;
	len -= 8;
    }
}
Example #12
0
File: blf.c Project: 50wu/gpdb
void
blowfish_encrypt_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_encrypt(xL, xR, out, ctx);
		PUT_32BIT_MSB_FIRST(blk, out[0]);
		PUT_32BIT_MSB_FIRST(blk + 4, out[1]);
		blk += 8;
		len -= 8;
	}
}
Example #13
0
File: main.c Project: dzruyk/spam
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;
}
Example #14
0
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;
}
Example #15
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;
}
Example #16
0
File: blf.c Project: 50wu/gpdb
void
blowfish_setkey(BlowfishContext *ctx,
				const uint8 *key, short keybytes)
{
	uint32	   *S0 = ctx->S0;
	uint32	   *S1 = ctx->S1;
	uint32	   *S2 = ctx->S2;
	uint32	   *S3 = ctx->S3;
	uint32	   *P = ctx->P;
	uint32		str[2];
	int			i;

	Assert(keybytes > 0 && keybytes <= (448 / 8));

	for (i = 0; i < 18; i++)
	{
		P[i] = parray[i];
		P[i] ^= ((uint32) key[(i * 4 + 0) % keybytes]) << 24;
		P[i] ^= ((uint32) key[(i * 4 + 1) % keybytes]) << 16;
		P[i] ^= ((uint32) key[(i * 4 + 2) % keybytes]) << 8;
		P[i] ^= ((uint32) key[(i * 4 + 3) % keybytes]);
	}

	for (i = 0; i < 256; i++)
	{
		S0[i] = sbox0[i];
		S1[i] = sbox1[i];
		S2[i] = sbox2[i];
		S3[i] = sbox3[i];
	}

	str[0] = str[1] = 0;

	for (i = 0; i < 18; i += 2)
	{
		blowfish_encrypt(str[0], str[1], str, ctx);
		P[i] = str[0];
		P[i + 1] = str[1];
	}

	for (i = 0; i < 256; i += 2)
	{
		blowfish_encrypt(str[0], str[1], str, ctx);
		S0[i] = str[0];
		S0[i + 1] = str[1];
	}
	for (i = 0; i < 256; i += 2)
	{
		blowfish_encrypt(str[0], str[1], str, ctx);
		S1[i] = str[0];
		S1[i + 1] = str[1];
	}
	for (i = 0; i < 256; i += 2)
	{
		blowfish_encrypt(str[0], str[1], str, ctx);
		S2[i] = str[0];
		S2[i + 1] = str[1];
	}
	for (i = 0; i < 256; i += 2)
	{
		blowfish_encrypt(str[0], str[1], str, ctx);
		S3[i] = str[0];
		S3[i + 1] = str[1];
	}
}
Example #17
0
void blowfish_expandkey(BlowfishContext * ctx,
                        const unsigned char *key, short keybytes,
                        const unsigned char *salt, short saltbytes)
{
    word32 *S0 = ctx->S0;
    word32 *S1 = ctx->S1;
    word32 *S2 = ctx->S2;
    word32 *S3 = ctx->S3;
    word32 *P = ctx->P;
    word32 str[2];
    int i, j;
    int saltpos;
    unsigned char dummysalt[1];

    saltpos = 0;
    if (!salt) {
        saltbytes = 1;
        salt = dummysalt;
        dummysalt[0] = 0;
    }

    for (i = 0; i < 18; i++) {
	P[i] ^=
	    ((word32) (unsigned char) (key[(i * 4 + 0) % keybytes])) << 24;
	P[i] ^=
	    ((word32) (unsigned char) (key[(i * 4 + 1) % keybytes])) << 16;
	P[i] ^=
	    ((word32) (unsigned char) (key[(i * 4 + 2) % keybytes])) << 8;
	P[i] ^= ((word32) (unsigned char) (key[(i * 4 + 3) % keybytes]));
    }

    str[0] = str[1] = 0;

    for (i = 0; i < 18; i += 2) {
        for (j = 0; j < 8; j++)
            str[j/4] ^= ((word32)salt[saltpos++ % saltbytes]) << (24-8*(j%4));

	blowfish_encrypt(str[0], str[1], str, ctx);
	P[i] = str[0];
	P[i + 1] = str[1];
    }

    for (i = 0; i < 256; i += 2) {
        for (j = 0; j < 8; j++)
            str[j/4] ^= ((word32)salt[saltpos++ % saltbytes]) << (24-8*(j%4));
	blowfish_encrypt(str[0], str[1], str, ctx);
	S0[i] = str[0];
	S0[i + 1] = str[1];
    }
    for (i = 0; i < 256; i += 2) {
        for (j = 0; j < 8; j++)
            str[j/4] ^= ((word32)salt[saltpos++ % saltbytes]) << (24-8*(j%4));
	blowfish_encrypt(str[0], str[1], str, ctx);
	S1[i] = str[0];
	S1[i + 1] = str[1];
    }
    for (i = 0; i < 256; i += 2) {
        for (j = 0; j < 8; j++)
            str[j/4] ^= ((word32)salt[saltpos++ % saltbytes]) << (24-8*(j%4));
	blowfish_encrypt(str[0], str[1], str, ctx);
	S2[i] = str[0];
	S2[i + 1] = str[1];
    }
    for (i = 0; i < 256; i += 2) {
        for (j = 0; j < 8; j++)
            str[j/4] ^= ((word32)salt[saltpos++ % saltbytes]) << (24-8*(j%4));
	blowfish_encrypt(str[0], str[1], str, ctx);
	S3[i] = str[0];
	S3[i + 1] = str[1];
    }
}