Files
holycard-cracker/crypto1_bs.c
2016-04-12 20:55:22 +02:00

95 lines
4.2 KiB
C

// Bit-sliced Crypto-1 implementation (C) 2015 by Aram Verstegen
// The cipher states are stored with the least significant bit first, hence all bit indexes are reversed here
#include "crypto1_bs.h"
// The following functions use this global or thread-local state
// It is sized to fit exactly KEYSTREAM_SIZE more states next to the initial state
__thread bitslice_t states[KEYSTREAM_SIZE+STATE_SIZE];
__thread bitslice_t * restrict state_p;
void crypto1_bs_init(){
// initialize constant one and zero bit vectors
memset(bs_ones.bytes, 0xff, VECTOR_SIZE);
memset(bs_zeroes.bytes, 0x00, VECTOR_SIZE);
}
// The following functions have side effects on 48 bitslices at the state_p pointer
// use the crypto1_bs_rewind_* macros to (re-)initialize them as needed
inline const bitslice_value_t crypto1_bs_bit(const bitslice_value_t input, const bool is_encrypted){
bitslice_value_t feedback = (state_p[47- 0].value ^ state_p[47- 5].value ^ state_p[47- 9].value ^
state_p[47-10].value ^ state_p[47-12].value ^ state_p[47-14].value ^
state_p[47-15].value ^ state_p[47-17].value ^ state_p[47-19].value ^
state_p[47-24].value ^ state_p[47-25].value ^ state_p[47-27].value ^
state_p[47-29].value ^ state_p[47-35].value ^ state_p[47-39].value ^
state_p[47-41].value ^ state_p[47-42].value ^ state_p[47-43].value);
const bitslice_value_t ks_bits = crypto1_bs_f20(state_p);
if(is_encrypted){
feedback ^= ks_bits;
}
state_p--;
state_p[0].value = feedback ^ input;
return ks_bits;
}
inline const bitslice_value_t crypto1_bs_lfsr_rollback(const bitslice_value_t input, const bool is_encrypted){
bitslice_value_t feedout = state_p[0].value;
state_p++;
const bitslice_value_t ks_bits = crypto1_bs_f20(state_p);
if(is_encrypted){
feedout ^= ks_bits;
}
const bitslice_value_t feedback = (feedout ^ state_p[47- 5].value ^ state_p[47- 9].value ^
state_p[47-10].value ^ state_p[47-12].value ^ state_p[47-14].value ^
state_p[47-15].value ^ state_p[47-17].value ^ state_p[47-19].value ^
state_p[47-24].value ^ state_p[47-25].value ^ state_p[47-27].value ^
state_p[47-29].value ^ state_p[47-35].value ^ state_p[47-39].value ^
state_p[47-41].value ^ state_p[47-42].value ^ state_p[47-43].value);
state_p[47].value = feedback ^ input;
return ks_bits;
}
// side-effect free from here on
// note that bytes are sliced and unsliced with reversed endianness
inline void crypto1_bs_convert_states(bitslice_t bitsliced_states[], state_t regular_states[]){
size_t bit_idx = 0, slice_idx = 0;
state_t values[MAX_BITSLICES];
for(slice_idx = 0; slice_idx < MAX_BITSLICES; slice_idx++){
for(bit_idx = 0; bit_idx < STATE_SIZE; bit_idx++){
bool bit = get_vector_bit(slice_idx, bitsliced_states[bit_idx]);
values[slice_idx].value <<= 1;
values[slice_idx].value |= bit;
}
// swap endianness
values[slice_idx].value = rev_state_t(values[slice_idx].value);
// roll off unused bits
values[slice_idx].value >>= ((sizeof(state_t)*8)-STATE_SIZE);
}
memcpy(regular_states, values, sizeof(values));
}
// bitslice a value
void crypto1_bs_bitslice_value32(uint32_t value, bitslice_t bitsliced_value[], size_t bit_len){
// load nonce bytes with unswapped endianness
size_t bit_idx;
for(bit_idx = 0; bit_idx < bit_len; bit_idx++){
bool bit = get_bit(bit_len-1-bit_idx, rev32(value));
if(bit){
bitsliced_value[bit_idx].value = bs_ones.value;
} else {
bitsliced_value[bit_idx].value = bs_zeroes.value;
}
}
}
void crypto1_bs_print_states(bitslice_t bitsliced_states[]){
size_t slice_idx = 0;
state_t values[MAX_BITSLICES];
crypto1_bs_convert_states(bitsliced_states, values);
for(slice_idx = 0; slice_idx < MAX_BITSLICES; slice_idx++){
printf("State %03lu: %012lx\n", slice_idx, values[slice_idx].value);
}
}