Mickey V2Mickey V2 is a Light Weight Stream Cipher and was written by Steve Babbage and Matthew Dodd. It creates a key stream from an 80-bit key and a variable length initialization vector (of up to 80 bits). The keystream with a maximum length of \(2^{40}\) bits [paper]. Code/* This file contains an implementation of functions declared in ecrypt-sync.h so as to realise the keystream generator MICKEY version 2 */ /* Date started :- 28/4/05 */ /* Date last altered :- 28/6/06 */ /* Include the header file ecrypt-sync.h, edited for MICKEY v 2 */ #include "ecrypt-sync.h" #include stdio.h #include string.h /* Declare static variables, independent of key or IV */ u32 R_Mask[4]; /* Feedback mask associated with the register R */ u32 Comp0[4]; /* Input mask associated with register S */ u32 Comp1[4]; /* Second input mask associated with register S */ u32 S_Mask0[4]; /* Feedback mask associated with the register S for clock control bit = 0 */ u32 S_Mask1[4]; /* Feedback mask associated with the register S for clock control bit = 1 */ /* * Key and message independent initialization. This function will be * called once when the program starts. */ int hex2data(unsigned char *data, const unsigned char *hexstring, unsigned int len) { unsigned const char *pos = hexstring; char *endptr; size_t count = 0; if ((hexstring[0] == '\0') || (strlen(hexstring) % 2)) { //hexstring contains no data //or hexstring has an odd length return -1; } for(count = 0; count < len; count++) { char buf[5] = {'0', 'x', pos[0], pos[1], 0}; data[count] = strtol(buf, &endptr, 0); pos += 2 * sizeof(char); if (endptr[0] != '\0') { //non-hexadecimal character encountered return -1; } } return 0; } void ECRYPT_init(void) { /* Initialise the feedback mask associated with register R */ R_Mask[0] = 0x1279327b; R_Mask[1] = 0xb5546660; R_Mask[2] = 0xdf87818f; R_Mask[3] = 0x00000003; /* Initialise Comp0 */ Comp0[0] = 0x6aa97a30; Comp0[1] = 0x7942a809; Comp0[2] = 0x057ebfea; Comp0[3] = 0x00000006; /* Initialise Comp1 */ Comp1[0] = 0xdd629e9a; Comp1[1] = 0xe3a21d63; Comp1[2] = 0x91c23dd7; Comp1[3] = 0x00000001; /* Initialise the feedback masks associated with register S */ S_Mask0[0] = 0x9ffa7faf; S_Mask0[1] = 0xaf4a9381; S_Mask0[2] = 0x9cec5802; S_Mask0[3] = 0x00000001; S_Mask1[0] = 0x4c8cb877; S_Mask1[1] = 0x4911b063; S_Mask1[2] = 0x40fbc52b; S_Mask1[3] = 0x00000008; } /* The following routine clocks register R in ctx with given input and control bits */ void CLOCK_R( ECRYPT_ctx* ctx, int input_bit, int control_bit) { int Feedback_bit; /* r_99 ^ input bit */ int Carry0, Carry1, Carry2; /* Respectively, carry from R[0] into R[1], carry from R[1] into R[2] and carry from R[2] into R[3] */ /* Initialise the variables */ Feedback_bit = ((ctx->R[3] >> 3) & 1) ^ input_bit; Carry0 = (ctx->R[0] >> 31) & 1; Carry1 = (ctx->R[1] >> 31) & 1; Carry2 = (ctx->R[2] >> 31) & 1; if (control_bit) { /* Shift and xor */ ctx->R[0] ^= (ctx->R[0] << 1); ctx->R[1] ^= (ctx->R[1] << 1) ^ Carry0; ctx->R[2] ^= (ctx->R[2] << 1) ^ Carry1; ctx->R[3] ^= (ctx->R[3] << 1) ^ Carry2; } else { /* Shift only */ ctx->R[0] = (ctx->R[0] << 1); ctx->R[1] = (ctx->R[1] << 1) ^ Carry0; ctx->R[2] = (ctx->R[2] << 1) ^ Carry1; ctx->R[3] = (ctx->R[3] << 1) ^ Carry2; } /* Implement feedback into the various register stages */ if (Feedback_bit) { ctx->R[0] ^= R_Mask[0]; ctx->R[1] ^= R_Mask[1]; ctx->R[2] ^= R_Mask[2]; ctx->R[3] ^= R_Mask[3]; } } /* The following routine clocks register S in ctx with given input and control bits */ void CLOCK_S( ECRYPT_ctx* ctx, int input_bit, int control_bit) { int Feedback_bit; /* s_99 ^ input bit */ int Carry0, Carry1, Carry2; /* Respectively, carry from S[0] into S[1], carry from S[1] into S[2] and carry from S[2] into S[3] */ /* Compute the feedback and carry bits */ Feedback_bit = ((ctx->S[3] >> 3) & 1) ^ input_bit; Carry0 = (ctx->S[0] >> 31) & 1; Carry1 = (ctx->S[1] >> 31) & 1; Carry2 = (ctx->S[2] >> 31) & 1; /* Derive "s hat" according to the MICKEY v 2 specification */ ctx->S[0] = (ctx->S[0] << 1) ^ ((ctx->S[0] ^ Comp0[0]) & ((ctx->S[0] >> 1) ^ (ctx->S[1] << 31) ^ Comp1[0]) & 0xfffffffe); ctx->S[1] = (ctx->S[1] << 1) ^ ((ctx->S[1] ^ Comp0[1]) & ((ctx->S[1] >> 1) ^ (ctx->S[2] << 31) ^ Comp1[1])) ^ Carry0; ctx->S[2] = (ctx->S[2] << 1) ^ ((ctx->S[2] ^ Comp0[2]) & ((ctx->S[2] >> 1) ^ (ctx->S[3] << 31) ^ Comp1[2])) ^ Carry1; ctx->S[3] = (ctx->S[3] << 1) ^ ((ctx->S[3] ^ Comp0[3]) & ((ctx->S[3] >> 1) ^ Comp1[3]) & 0x7) ^ Carry2; /* Apply suitable feedback from s_99 */ if (Feedback_bit) { if (control_bit) { ctx->S[0] ^= S_Mask1[0]; ctx->S[1] ^= S_Mask1[1]; ctx->S[2] ^= S_Mask1[2]; ctx->S[3] ^= S_Mask1[3]; } else { ctx->S[0] ^= S_Mask0[0]; ctx->S[1] ^= S_Mask0[1]; ctx->S[2] ^= S_Mask0[2]; ctx->S[3] ^= S_Mask0[3]; } } } /* The following routine implements a clock of the keystream generator. The parameter mixing is set to 0 or a non-zero value to determine whether mixing (from s_50) is not/is applied; the parameter input_bit is used to specify any input bit to the generator */ int CLOCK_KG ( ECRYPT_ctx* ctx, int mixing, int input_bit) { int Keystream_bit; /* Keystream bit to be returned (only valid if mixing = 0 and input_bit = 0 */ int control_bit_r; /* The control bit for register R */ int control_bit_s; /* The control bit for register S */ Keystream_bit = (ctx->R[0] ^ ctx->S[0]) & 1; control_bit_r = ((ctx->S[1] >> 2) ^ (ctx->R[2] >> 3)) & 1; control_bit_s = ((ctx->R[1] >> 1) ^ (ctx->S[2] >> 3)) & 1; if (mixing) CLOCK_R (ctx, ((ctx->S[1] >> 18) & 1) ^ input_bit, 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<10; i++) ctx->key[i] = key[i]; /* Store the iv size in the context too */ 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 v1 specification */ void ECRYPT_ivsetup( ECRYPT_ctx* ctx, const u8* iv) { int i; /* Counting/indexing variable */ int iv_or_key_bit; /* Bit being loaded */ /* Initialise R and S to all zeros */ for (i=0; i<4; 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<80; 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<100; 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); } } void perform_iterated_test (u8 *key) { ECRYPT_ctx ctx; /* Keystream generator context */ u8 iv[4]; /* Array to contain iv derived from keystream */ u8 keystream[16]; /* Array to contain generated keystream bytes */ int i; /* Counting variable */ /* Display the key */ printf ("Iterated test key ="); for (i=0; i<10; i++) printf (" %02x", key[i]); printf ("\n"); /* Load key */ ECRYPT_keysetup (&ctx, key, 80, 0); ECRYPT_ivsetup (&ctx, iv); for (i=0; i<1000; i++) { /* Generate new key and iv from keystream */ ECRYPT_keystream_bytes (&ctx, key, 10); ECRYPT_keystream_bytes (&ctx, iv, 4); /* Load new key */ ECRYPT_keysetup (&ctx, key, 80, 32); /* Load new IV */ ECRYPT_ivsetup (&ctx, iv); } /* Generate keystream */ ECRYPT_keystream_bytes (&ctx, keystream, 16); /* Display the derived keytream */ printf ("Final keystream ="); for (i=0; i<16; i++) printf (" %02x", keystream[i]); printf ("\n"); printf ("\n"); } void perform_test (u8 *key, u8* iv, int iv_length_in_bits) { ECRYPT_ctx ctx; /* Keystream generator context */ u8 keystream[16]; /* Array to contain generated keystream bytes */ int i; /* Counting variable */ /* Load key */ ECRYPT_keysetup (&ctx, key, 80, iv_length_in_bits); /* Load IV */ ECRYPT_ivsetup (&ctx, iv); /* Generate keystream */ ECRYPT_keystream_bytes (&ctx, keystream, 16); /* Display the key */ printf ("Key ="); for (i=0; i<10; i++) printf (" %02x", key[i]); printf ("\n"); /* Display the IV */ printf ("IV ="); for (i=0; i<(iv_length_in_bits+7)/8; i++) printf (" %02x", iv[i]); printf ("\n"); /* Display the derived keytream */ printf ("Keystream ="); for (i=0; i<16; i++) printf (" %02x", keystream[i]); printf ("\n"); printf ("\n"); } int main(int argc, char **argv) { char str1[20]; char str2[16]; u8 key_1[10] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34}; u8 iv_1[4] = {0x21, 0x43, 0x65, 0x87}; /* Initialise the algorithm */ ECRYPT_init (); if (argc>1) { strcpy(str1, argv[1]); strcpy(str2, argv[2]); hex2data(key_1, str1,strlen(argv[1])); hex2data(iv_1, str2,strlen(argv[2])); } /* Generate the test data */ perform_test (key_1, iv_1, 32); } |