svn: ecrypt/trunk/submissions/mickey-128/bit-by-bit/mickey-128.c
/* 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; i<ctx->ivsize; 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<msglen; i++)
{
output[i] = input[i];
for (j=0; j<8; j++)
output [i] ^= CLOCK_KG (ctx, 0, 0) << (7-j);
}
}
/* Generate keystream data */
void ECRYPT_keystream_bytes(
ECRYPT_ctx* ctx,
u8* keystream,
u32 length) /* Length of keystream in bytes. */
{
u32 i, j;
/* Counting variables */
for (i=0; i<length; i++)
{
keystream[i] = 0;
for (j=0; j<8; j++)
keystream[i] ^= CLOCK_KG (ctx, 0, 0) << (7-j);
}
}