/* This file contains a simple, "one bit at a time" implementation of functions declared in ecrypt-sync.h so as to realise the keystream generator MICKEY-128 version 0.4 */ /* Date started :- 28/4/05 */ /* Date last altered :- 28/4/05 */ /* Include the header file ecrypt-sync.h, edited for this bit-by-bit implementation of MICKEY-128 v1 */ #include "ecrypt-sync.h" u8 R_Mask[128] = {1,1,1,1,0,0,1,1,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,1, 1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,1,1,0,0,0,0,0,1,1,1, 1,0,0,0,0,1,1,1,0,1,1,0,1,1,1,0,0,1,1,1,1,1,0,1,0,1,1,0,0,0,1,1, 1,0,0,0,1,0,1,0,1,0,1,1,1,0,1,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,1,0}; /* Feedback mask associated with the register R (independent of key or IV) */ u8 COMP0[127] = {1,1,1,1,1,0,1,0,0,1,0,0,1,1,1,1,0,1,1,0,1,0,1,1,1,0,1,1,1,0,1,0, 1,0,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,1,0,0,1,1,1,1,0, 0,1,0,0,0,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,0, 1,0,0,0,1,1,0,0,1,0,0,1,1,0,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,0}; u8 COMP1[127] = {1,0,0,0,1,1,0,0,1,1,1,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,1,1,1,1,1,0, 0,0,0,1,1,0,0,1,0,0,1,1,1,1,0,0,0,1,1,0,1,1,0,1,0,1,1,1,1,1,1,1, 0,0,0,0,0,1,1,1,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0, 1,0,1,0,0,0,1,0,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1}; /* Determines whether certain bits are complemented when used in the S feedback function */ u8 FB0[128] = {1,1,1,1,0,1,0,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,0,0,0,1,1, 0,1,0,0,0,1,0,0,1,1,0,0,0,1,0,1,1,1,1,1,0,1,0,0,0,1,1,1,0,0,0,0, 1,0,0,0,0,0,0,1,1,0,1,1,0,0,1,0,1,0,1,0,0,1,1,1,0,1,1,0,0,1,1,0, 1,0,0,0,1,0,0,1,1,1,0,1,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1,1}; u8 FB1[128] = {1,1,0,1,0,1,0,1,1,1,1,0,1,1,1,0,0,0,1,0,1,1,1,1,1,1,0,1,1,0,0,1, 0,0,0,0,1,0,0,1,0,0,1,1,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,1,1,1,0, 0,1,1,0,1,1,0,1,0,0,0,1,1,0,0,0,0,1,0,1,1,0,0,1,1,1,1,1,0,1,1,0, 1,1,1,0,0,1,1,1,0,1,1,1,1,1,1,0,1,1,0,1,0,0,1,0,0,0,1,1,0,1,1,0}; /* Two alternative sets of stages into which s127 is fed back, Galois-style */ /* * Key and message independent initialization. This function will be * called once when the program starts. */ void ECRYPT_init(void) { return; } /* The following routine clocks register R in ctx with given input and control bits */ void CLOCK_R( ECRYPT_ctx* ctx, u8 input_bit_r, u8 control_bit_r) { u8 Feedback_bit; /* r_127 ^ input bit */ u8 i; /* Index variable */ Feedback_bit = ctx->R[127] ^ input_bit_r; if (control_bit_r) { /* Shift and XOR */ if (Feedback_bit) { for (i=127; i>0; i--) ctx->R[i] = ctx->R[i-1] ^ ctx->R[i] ^ R_Mask[i]; ctx->R[0] = R_Mask[0] ^ ctx->R[0]; } else { for (i=127; i>0; i--) ctx->R[i] = ctx->R[i-1] ^ ctx->R[i]; } } else { /* Shift only */ if (Feedback_bit) { for (i=127; i>0; i--) ctx->R[i] = ctx->R[i-1] ^ R_Mask[i]; ctx->R[0] = R_Mask[0]; } else { for (i=127; i>0; i--) ctx->R[i] = ctx->R[i-1]; ctx->R[0] = 0; } } } /* The following routine clocks register S in ctx with given input and control bits */ void CLOCK_S( ECRYPT_ctx* ctx, u8 input_bit_s, u8 control_bit_s) { u8 s_hat[128]; /* Intermediate values of the s stages */ u8 Feedback_bit; /* s_127 ^ input bit */ int i; /* Index variable */ Feedback_bit = ctx->S[127] ^ input_bit_s; for (i=126; i>0; i--) s_hat[i] = ctx->S[i-1] ^ ((ctx->S[i] ^ COMP0[i]) & (ctx->S[i+1] ^ COMP1[i])); s_hat[0] = 0; s_hat[127] = ctx->S[126]; for (i=0; i<128; i++) ctx->S[i] = s_hat[i]; if (Feedback_bit) { if (control_bit_s) { for (i=0; i<128; i++) ctx->S[i] = s_hat[i] ^ FB1[i]; } else { for (i=0; i<128; i++) ctx->S[i] = s_hat[i] ^ FB0[i]; } } } /* The following routine obtains a keysteam bit from the generator, which it then clocks */ int CLOCK_KG( ECRYPT_ctx* ctx, u8 mixing, u8 input_bit) { int Keystream_bit; /* Keystream bit to be returned */ u8 Control_bit_R, Control_bit_S; /* Control the variable clocking of the R and S registers */ Keystream_bit = (ctx->R[0] ^ ctx->S[0]) & 1; Control_bit_R = ctx->S[43] ^ ctx->R[85]; Control_bit_S = ctx->S[85] ^ ctx->R[42]; if (mixing) CLOCK_R (ctx, input_bit ^ ctx->S[64], Control_bit_R); else CLOCK_R (ctx, input_bit, Control_bit_R); CLOCK_S (ctx, input_bit, Control_bit_S); return Keystream_bit; } /* Key setup: simply save the key in ctx for use during IV setup */ void ECRYPT_keysetup( ECRYPT_ctx* ctx, const u8* key, u32 keysize, /* Key size in bits. */ u32 ivsize) /* IV size in bits. */ { int i; /* Indexing variable */ /* Store the key in the algorithm context */ for (i = 0; i<16; i++) ctx->key[i] = key[i]; /* Remember the IV size */ ctx->ivsize = ivsize; } /* * IV setup. After having called ECRYPT_keysetup(), the user is * allowed to call ECRYPT_ivsetup() different times in order to * encrypt/decrypt different messages with the same key but different * IV's. */ /* This routine implements key loading according to the MICKEY-128 specification */ void ECRYPT_ivsetup( ECRYPT_ctx* ctx, const u8* iv) { u8 i; /* Counting/indexing variable */ u8 iv_or_key_bit; /* Bit being loaded */ /* Initialise R and S to all zeros */ for (i=0; i<128; i++) { ctx->R[i] = 0; ctx->S[i] = 0; } /* Load in IV */ for (i=0; iivsize; i++) { iv_or_key_bit = (iv[i/8] >> (7-(i%8))) & 1; /* Adopt usual, perverse, labelling order */ CLOCK_KG (ctx, 1, iv_or_key_bit); } /* Load in K */ for (i=0; i<128; i++) { iv_or_key_bit = (ctx->key[i/8] >> (7-(i%8))) & 1; /* Adopt usual, perverse, labelling order */ CLOCK_KG (ctx, 1, iv_or_key_bit); } /* Preclock */ for (i=0; i<128; i++) { CLOCK_KG (ctx, 1, 0); } } /* Stream cipher a block of data */ void ECRYPT_process_bytes( int action, /* 0 = encrypt; 1 = decrypt; */ ECRYPT_ctx* ctx, const u8* input, u8* output, u32 msglen) /* length in bytes */ { u32 i, j; /* Counting variables */ for (i=0; i