/* * F-FCSR-8 reference implementation. * * (c) 2005 FCSR project. This software is provided 'as-is', without * any express or implied warranty. In no event will the authors be held * liable for any damages arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to no restriction. * * Technical remarks and questions can be addressed to * */ #define FFCSR8_EVALUATE #include "ffcsr8-sync.h" #ifdef FFCSR8_EVALUATE #include #endif void ECRYPT_keysetup( ECRYPT_ctx* ctx, const u8* key, u32 keyse, /* Key se in bits. */ u32 ivse) /* IV se in bits. */ { u32 i; ctx->carry[0] = 0; ctx->carry[1] = 0; ctx->carry[2] = 0; ctx->carry[3] = 0; ctx->state[3] = key[3] | key[2]<<8 | key[1]<<16 | key[0]<<24; ctx->state[2] = key[7] | key[6]<<8 | key[5]<<16 | key[4]<<24; ctx->state[1] = key[11] | key[10]<<8 | key[9]<<16 | key[8]<<24; ctx->state[0] = key[15] | key[14]<<8 | key[13]<<16 | key[12]<<24; while( goodfilter(ctx) != 1 ) { ctx->carry[0] = 0; ctx->carry[1] = 0; ctx->carry[2] = 0; ctx->carry[3] = 0; ECRYPT_clock(ctx); ECRYPT_clock(ctx); ECRYPT_clock(ctx); ECRYPT_clock(ctx); ECRYPT_clock(ctx); ECRYPT_clock(ctx); } ctx->filter[0]=ctx->state[0]; ctx->filter[1]=ctx->state[1]; ctx->filter[2]=ctx->state[2]; ctx->filter[3]=ctx->state[3]; ctx->carry[0] = 0; ctx->carry[1] = 0; ctx->carry[2] = 0; ctx->carry[3] = 0; for(i=0;i<128;i++) { ECRYPT_clock(ctx); } init[0]=ctx->state[0]; init[1]=ctx->state[1]; init[2]=ctx->state[2]; init[3]=ctx->state[3]; } void ECRYPT_ivsetup( ECRYPT_ctx* ctx, const u8* iv) { u32 i=0,tmp; ctx->carry[0] = 0; ctx->carry[1] = 0; ctx->carry[2] = 0; ctx->carry[3] = 0; insertIV(ctx,&iv[0]); ctx->state[0]=init[0]; ctx->state[1]=init[1]; ctx->state[2]=init[2]; ctx->state[3]=init[3]; for( i=0; i<64 ; i++) { ECRYPT_clock(ctx); } ctx->carry[0] = 0; ctx->carry[1] = 0; ctx->carry[2] = 0; ctx->carry[3] = 0; insertIV(ctx,&iv[8]); for( i=0; i<64 ; i++) { ECRYPT_clock(ctx); } ctx->state[0]=init[0]; ctx->state[1]=init[1]; ctx->state[2]=init[2]; ctx->state[3]=init[3]; } void ECRYPT_process_bytes( int action, /* 0 = encrypt; 1 = decrypt; */ ECRYPT_ctx* ctx, const u8* input, u8* output, u32 msglen) /* Message length in bytes. */ { u32 i; for( i=0 ; i< msglen ; i++) { ECRYPT_clock(ctx); output[i] = input[i] ^ ECRYPT_filter(ctx); } } /* Update the shift register and the carry register of the FCSR */ void ECRYPT_clock( ECRYPT_ctx* ctx ) { u32 feedback; u32 buffer[4]; /* expand the feedback bit */ feedback = ((int) (ctx->state[0] << (MAXSHIFT))) >> (MAXSHIFT); /* shift the state */ ctx->state[0] = ctx->state[0] >> 1; ctx->state[0] |= (ctx->state[1] & 0x00000001 ) << (MAXSHIFT); ctx->state[1] = ctx->state[1] >> 1; ctx->state[1] |= (ctx->state[2] & 0x01 ) << (MAXSHIFT); ctx->state[2] = ctx->state[2] >> 1; ctx->state[2] |= (ctx->state[3] & 0x01 ) << (MAXSHIFT); ctx->state[3] >>=1; /* update the register */ buffer[0] = ctx->state[0] ^ ctx->carry[0]; buffer[1] = ctx->state[1] ^ ctx->carry[1]; buffer[2] = ctx->state[2] ^ ctx->carry[2]; buffer[3] = ctx->state[3] ^ ctx->carry[3]; ctx->carry[0] &= ctx->state[0]; ctx->carry[1] &= ctx->state[1]; ctx->carry[2] &= ctx->state[2]; ctx->carry[3] &= ctx->state[3]; ctx->carry[0] ^= buffer[0] & (feedback &d0); ctx->carry[1] ^= buffer[1] & (feedback &d1); ctx->carry[2] ^= buffer[2] & (feedback &d2); ctx->carry[3] ^= buffer[3] & (feedback &d3); buffer[0] ^= feedback & d0; buffer[1] ^= feedback & d1; buffer[2] ^= feedback & d2; buffer[3] ^= feedback & d3; ctx->state[0] = buffer[0]; ctx->state[1] = buffer[1]; ctx->state[2] = buffer[2]; ctx->state[3] = buffer[3]; } /* Produce one byte of keystream from the internal state of the register */ u8 ECRYPT_filter( ECRYPT_ctx* ctx ) { u32 buffer[4]; buffer[0] = ctx->filter[0] & ctx->state[0]; buffer[1] = ctx->filter[1] & ctx->state[1]; buffer[2] = ctx->filter[2] & ctx->state[2]; buffer[3] = ctx->filter[3] & ctx->state[3]; buffer[0] ^= buffer[1]; buffer[2] ^= buffer[3]; buffer[0] ^= buffer[2]; buffer[0] ^= ( buffer[0] >> 16 ); buffer[0] ^= ( buffer[0] >> 8); return (u8)buffer[0]; } /* compute the hamming of 32 bits word */ /* this method is efficient for low hamming weight word */ u32 hammingWeight ( u32 n ) { u32 count=0 ; while (n) { count++ ; n &= (n - 1) ; } return count ; } /* each subFilter of the filter must have a hamming weight > LIMIT_WEIGHT */ u8 goodfilter ( ECRYPT_ctx *ctx ) { u32 i,j; u32 weight; u32 tmp, mask; for ( i=0; i < 8 ; i++ ) { mask = 0x01010101 << i; tmp = (ctx->state[0] & mask)>>i ; tmp ^= ((ctx->state[1] & mask) >>i)<<1; tmp ^= ((ctx->state[2] & mask) >>i)<<2; tmp ^= ((ctx->state[3] & mask) >>i)<<3; weight=hammingWeight(tmp); if(weightcarry[0] |= (tmp & 0x00000001) << (ivD0Load[i]); tmp = tmp>>1; } tmp=iv[6]; for( i=8; i<14 ;i++) { ctx->carry[0] |= (tmp & 0x00000001) << ivD0Load[i]; tmp = tmp>>1; } /* inject the next 16 bit of IV in the carry */ for( i=0; i<2;i++) { ctx->carry[1] |= (tmp & 0x00000001) << ivD1Load[i]; tmp = tmp>>1; } tmp=iv[5]; for( i=2; i<10;i++) { ctx->carry[1] |= (tmp & 0x00000001) << ivD1Load[i]; tmp = tmp>>1; } tmp=iv[4]; for( i=10; i<16;i++) { ctx->carry[1] |= (tmp & 0x00000001) << ivD1Load[i]; tmp = tmp>>1; } /* inject the next 21 bit of IV in the carry */ ctx->carry[2] |= (tmp & 0x00000001) << ivD2Load[0]; tmp = tmp>>1; ctx->carry[2] |= (tmp & 0x00000001) << ivD2Load[1]; tmp=iv[3]; for( i=2; i<10;i++) { ctx->carry[2] |= (tmp & 0x00000001) << ivD2Load[i]; tmp = tmp>>1; } tmp=iv[2]; for( i=10; i<18;i++) { ctx->carry[2] |= (tmp & 0x00000001) << ivD2Load[i]; tmp = tmp>>1; } tmp=iv[1]; for( i=18; i<21;i++) { ctx->carry[2] |= (tmp & 0x00000001) << ivD2Load[i]; tmp = tmp>>1; } /* inject the last 17 bit of IV in the carry */ for(i=0;i<5;i++) { ctx->carry[3] |= (tmp & 0x00000001) << ivD3Load[i]; tmp = tmp>>1; } tmp=iv[0]; for( i=5; i<13;i++) { ctx->carry[3] |= (tmp & 0x00000001) << ivD3Load[i]; tmp = tmp>>1; } } #ifdef FFCSR8_EVALUATE #define MB 1048576 #define NUM_MB 100 int main() { u32 nbByte,i,j; clock_t orig, end; double time; ECRYPT_ctx ctx; /* key for test vector */ u8 testKEY[16] = { 0x00, 0x88 , 0x63 , 0x9d, 0x6b , 0xf8 , 0x47 , 0xed , 0x59 , 0xc6 , 0x21 , 0x79 , 0x5d , 0x33 , 0x63 , 0xf1 }; u8 testIV[16] = { 0x00 , 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 , 0x99 , 0xAA , 0xBB , 0xCC , 0xDD , 0xEE , 0xFF}; u8 encipheredText[9]={ 0x50 , 0xf8 , 0xec , 0xde , 0xfa , 0x3c , 0x15 , 0xe1 , 0xc0 }; u8 output[9]; u8 text[9]={'S','O','S','E','M','A','N','U','K'}; u8 data=0; /* iv for vector test */ printf("\t TEST VECTOR\n"); printf("KEY 0x"); for(i=0;i<16;i++) { printf("%x",testKEY[i]); } printf("\n"); printf("IV 0x"); for(i=0;i<16;i++) { printf("%x",testIV[i]); } printf("\n"); printf("Plain Text: "); for(i=0;i<9;i++) { printf("%c",text[i]); } printf("\n"); ECRYPT_keysetup( &ctx , testKEY , ECRYPT_MAXKEYSIZE , ECRYPT_MAXIVSIZE); printf("Key loaded\n"); printf("Filter is: \n%x %x %x %x\n",ctx.filter[0],ctx.filter[1],ctx.filter[2],ctx.filter[3]); ECRYPT_ivsetup( &ctx , testIV ); printf("IV loaded\n"); ECRYPT_process_bytes( 0, &ctx , text , output , 9); printf("Enciphered Text: 0x"); for(i=0;i<9;i++) { if(encipheredText[i] != output[i]) { printf("ERROR\n"); exit(EXIT_FAILURE); } else { printf("%x",output[i]); } } printf("\n"); ECRYPT_keysetup( &ctx , testKEY , ECRYPT_MAXKEYSIZE , ECRYPT_MAXIVSIZE); ECRYPT_ivsetup( &ctx , testIV ); ECRYPT_process_bytes( 1, &ctx , output , output, 9); printf("Deciphered Text: "); for(i=0;i<9;i++) { printf("%c",output[i]); } printf("\n"); printf("SPEED TEST\n"); ECRYPT_keysetup( &ctx , testKEY , ECRYPT_MAXKEYSIZE , ECRYPT_MAXIVSIZE); ECRYPT_ivsetup( &ctx , testIV ); orig = clock(); for(i=0;i<(NUM_MB);i++) { for( j=0 ; j