void DES_bs_clear_keys()

{

memset(DES_bs_all.K, 0, sizeof(DES_bs_all.K));

}

void DES_bs_set_key(char *key, int index)

{

register char *ptr;

register int ofs, bit;

register ARCH_WORD value;

ofs = 56;

for (ptr = key; *ptr && ofs; ptr++) {

bit = (ofs -= 7);

value = *ptr & 0x7F;

do {

DES_bs_all.K[bit++] |= (value & 1) << index;

} while (value >>= 1);

}

}

void DES_bs_crypt(int count)

{

register int bit;

register ARCH_WORD R, L;

memset(DES_bs_all.B, 0, sizeof(DES_bs_all.B));

do {

DES_bs_body();

if (!--count) break;

for (bit = 0; bit < 32; bit++) {

R = DES_bs_all.B[bit];

L = DES_bs_all.B[bit + 32];

DES_bs_all.B[bit + 32] = R;

DES_bs_all.B[bit] = L;

}

} while (1);

}

ARCH_WORD *DES_bs_get_binary(char *ciphertext)

{

static ARCH_WORD out[64];

ARCH_WORD *raw;

int bit;

int index, shift;

int value;

raw = DES_raw_get_binary(ciphertext);

out[1] = out[0] = 0;

for (bit = 0; bit < 64; bit++) {

index = bit >> 4;

/* Swap L and R here instead of doing it one more time in DES_bs_crypt() */

index ^= 2;

/* Calculate the number of one of the 16 data bits in raw[index] */

shift = ((bit & 0xC) << 1) + (bit & 3) + 1;

/* Get the bit */

value = (raw[index] >> shift) & 1;

if (DES_bs_mem_saving)

/* Memory saving: pack the bits into two words */

out[bit >> 5] |= value << (bit & 0x1F);

else

/* We either set or clear all the bits in every word */

out[bit] = value ? ~(ARCH_WORD)0 : 0;

}

return out;

}

int DES_bs_binary_hash(ARCH_WORD *binary, int count)

{

int bit, result;

if (DES_bs_mem_saving)

return (int)*binary & ((1 << count) - 1);

result = 0;

for (bit = 0; bit < count; bit++)

if (binary[bit]) result |= 1 << bit;

return result;

}

int DES_bs_get_hash(int index, int count)

{

register int bit, result;

register ARCH_WORD mask;

mask = (ARCH_WORD)1 << index;

result = 0;

for (bit = 0; bit < count; bit++)

if (DES_bs_all.B[bit] & mask) result |= 1 << bit;

return result;

}

/*

* The trick I used here allows to compare one ciphertext against all the

* DES_bs_crypt() outputs in just O(log2(ARCH_BITS)) operations.

*/

int DES_bs_cmp_all(ARCH_WORD *binary, int count)

{

register int bit;

register ARCH_WORD mask;

mask = 0;

if (DES_bs_mem_saving)

for (bit = 0; bit < ((count < 32) ? count : 32); bit++) {

mask |= DES_bs_all.B[bit] ^

((binary[0] & (1 << bit)) ? ~(ARCH_WORD)0 : 0);

if (mask == ~(ARCH_WORD)0) return 0;

}

else

for (bit = 0; bit < count; bit++) {

mask |= DES_bs_all.B[bit] ^ binary[bit];

if (mask == ~(ARCH_WORD)0) return 0;

}

return 1;

}

int DES_bs_cmp_one(ARCH_WORD *binary, int count, int index)

{

register int bit;

register ARCH_WORD mask;

if (DES_bs_mem_saving) {

for (bit = 0; bit < count; bit++)

if (((DES_bs_all.B[bit] >> index) ^

(binary[bit >> 5] >> (bit & 0x1F))) & 1) return 0;

return 1;

}

mask = (ARCH_WORD)1 << index;

for (bit = 0; bit < count; bit++)

if ((DES_bs_all.B[bit] ^ binary[bit]) & mask) return 0;

return 1;

} )