Crypt-Rainbow

 view release on metacpan or  search on metacpan

_rainbow.c  view on Meta::CPAN

/***************************************************** 
 * Rainbow Cipher header file for ANSI C             *
 *   Chang-Hyi Lee  and  Jeong-Soo Kim                *
 *   Digital Communication Lab.,                     *
 *   SAIT, Samsung Advanced Institute of Technology  *
 *****************************************************/

#undef BIG_ENDIAN
#ifndef LITTLE_ENDIAN   /* jcd */
#define LITTLE_ENDIAN
#endif

#include <stdio.h>
/* #include <stdlib.h> */
#include <time.h>
#include <memory.h>
/* #include <assert.h> */
#include <string.h>

/*  Defines:  */
#define     BITSPERBLOCK    128  /*  Number of bits in a cipher block  */
#define     BLOCKSIZE       (BITSPERBLOCK/8)  /* # bytes in a cipher block  */
#define     BLOCK_WSIZE     (BITSPERBLOCK/32) /* # WORD32's in a cipher block  */
#define     DIR_ENCRYPT     0    /*  Are we encrpyting?  */
#define     DIR_DECRYPT     1    /*  Are we decrpyting?  */
#define     MODE_ECB        1    /*  Are we ciphering in ECB mode?   */
#define     MODE_CBC        2    /*  Are we ciphering in CBC mode?   */
#define     MODE_CFB1       3    /*  Are we ciphering in 1-bit CFB mode? */
#define     R_TRUE            1
#define     R_FALSE           0


/*  Error Codes :  */
#define     BAD_KEY_DIR        -1  /*  Key direction is invalid, e.g.,
					unknown value */
#define     BAD_KEY_MAT        -2  /*  Key material not of correct 
					length */
#define     BAD_KEY_INSTANCE   -3  /*  Key passed is not valid  */
#define     BAD_KEY_LENGTH     -4  /*  Key size in bits is wrong */
#define     BAD_CIPHER_MODE    -5  /*  Params struct passed to 
					cipherInit invalid */
#define     BAD_CIPHER_STATE   -6  /*  Cipher in wrong state (e.g., not 
					initialized) */
#define     BAD_CIPHER_INPUT   -7  /*  Wrong cipher input length */

#define     MAX_KEY_SIZE	   32  /* # of ASCII char's needed to
					represent a key */
#define     MAX_IV_SIZE		   16  /* # bytes needed to
					represent an IV  */
#define     SCHEDULE_KEY_SIZE  16*2*(R+1) /* total size of scheduled key */

#define     R           7   /* proposed encryption round */


/*  Typedefs:  */
    typedef unsigned char	BYTE;	 /*  8 bit */
    typedef unsigned short	WORD16;	 /* 16 bit */
#ifdef __alpha
	typedef unsigned int	WORD32;	 /* 32 bit */
#else  /* !__alpha */
	typedef unsigned long	WORD32;	 /* 32 bit */
#endif /* :__alpha */


/*  The structure for key information */
typedef struct keyInstance {
      BYTE  direction;	/*  In our case this is negligible, since this
	      structure involve both enc/dec Keys */
      int   keyLen;	    /*  Length of the key  */
      char  keyMaterial[MAX_KEY_SIZE+1];  /*  Raw key data in ASCII */
      BYTE	KS_Enc[SCHEDULE_KEY_SIZE];     /*  encryption key */
	  BYTE	KS_Dec[SCHEDULE_KEY_SIZE];     /*  decryption key */
      } keyInstance;

/*  The structure for cipher information */
typedef struct cipherInstance {
      BYTE  mode;            /* MODE_ECB, MODE_CBC, or MODE_CFB1 */
      BYTE  IV[MAX_IV_SIZE]; /* A possible Initialization Vector for 
      					ciphering */
	  BYTE  RED[512];        /* The S-box table RED=[f]|[f^(-1)] */
      int   blockSize;    	 /* Here It is fixed : 128  */
      } cipherInstance;

/*  Function protoypes  */
int makeKey(keyInstance *key, BYTE direction, int keyLen,
			char *keyMaterial);

int cipherInit(cipherInstance *cipher, BYTE mode, char *IV);

int blockEncrypt(cipherInstance *cipher, keyInstance *key, BYTE *input, 
			int inputLen, BYTE *outBuffer);

int blockDecrypt(cipherInstance *cipher, keyInstance *key, BYTE *input,
			int inputLen, BYTE *outBuffer);


#define     WD(a)    ((WORD32 *)(a)) /* for utility */

/* platform endianness: */
#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
#	if defined(_M_IX86) || defined(_M_I86) || defined(__alpha)
#		define LITTLE_ENDIAN
#	else
#		error "Either LITTLE_ENDIAN or BIG_ENDIAN must be defined"
#	endif
#elif defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
#	error "LITTLE_ENDIAN and BIG_ENDIAN must not be simultaneously defined"
#endif /* !LITTLE_ENDIAN && !BIG_ENDIAN */


/* Microsoft C / Intel x86 optimizations: */
#if defined(_MSC_VER) && defined(_M_IX86) 
#	define HARDWARE_ROTATIONS
#	define ASSEMBLER_CORE
#endif  /* :(_MSC_VER && _M_IX86) */


#ifdef HARDWARE_ROTATIONS
#	define ROTL(x, s) (_lrotl ((x), (s)))
#	define ROTR(x, s) (_lrotr ((x), (s)))
#else  /* !HARDWARE_ROTATIONS */
#	define ROTL(x, s) (((x) << (s)) | ((x) >> (32 - (s))))
#	define ROTR(x, s) (((x) >> (s)) | ((x) << (32 - (s))))
#endif /* :HARDWARE_ROTATIONS */

#ifdef LITTLE_ENDIAN
#	ifdef MASKED_BYTE_EXTRACTION
#		define GETB0(x) (((x)      ) & 0xffU)
#		define GETB1(x) (((x) >>  8) & 0xffU)
#		define GETB2(x) (((x) >> 16) & 0xffU)
#		define GETB3(x) (((x) >> 24) & 0xffU)
#	else  /* !MASKED_BYTE_EXTRACTION */
#		define GETB0(x) ((BYTE)  ((x)      ))
#		define GETB1(x) ((BYTE)  ((x) >>  8))
#		define GETB2(x) ((BYTE)  ((x) >> 16))
#		define GETB3(x) ((BYTE)  ((x) >> 24))
#	endif /* :MASKED_BYTE_EXTRACTION */

_rainbow.c  view on Meta::CPAN

		  (data[2] & key[(RN)][0])^   \
		  (data[3] & key[(RN)][1]);   \
	tmp[3] = (data[0] & key[(RN)][3])^\
		  (data[1] & key[(RN)][0])^   \
		  (data[2] & key[(RN)][1])^   \
		  (data[3] & key[(RN)][2]);   \
}

#define R_function(TABLE) \
{ /* R-layer */ \
	data[0] = PUTB1((TABLE)[GETB0(tmp[0])])|  \
		PUTB0((TABLE)[256+GETB1(tmp[0])])|    \
		PUTB3((TABLE)[GETB2(tmp[0])])|        \
		PUTB2((TABLE)[256+GETB3(tmp[0])]);    \
	data[1] = PUTB2((TABLE)[GETB0(tmp[1])])|  \
		PUTB0((TABLE)[256+GETB2(tmp[1])])|    \
		PUTB3((TABLE)[GETB1(tmp[1])])|        \
		PUTB1((TABLE)[256+GETB3(tmp[1])]);    \
	data[2] = PUTB3((TABLE)[GETB0(tmp[2])])|  \
		PUTB0((TABLE)[256+GETB3(tmp[2])])|    \
		PUTB2((TABLE)[GETB1(tmp[2])])|        \
		PUTB1((TABLE)[256+GETB2(tmp[2])]);    \
	data[3] = PUTB2((TABLE)[GETB0(tmp[3])])|  \
		PUTB0((TABLE)[256+GETB2(tmp[3])])|    \
		PUTB3((TABLE)[GETB1(tmp[3])])|        \
		PUTB1((TABLE)[256+GETB3(tmp[3])]);    \
}

#define ROUND_function(key_num) \
{ /* one round process 'F_function' in the document */ \
	G_function(key_num);   \
	B_function(key_num+1); \
	R_function(SBox);      \
}

#define ONEBLOCK_CIPH /* here : only for the blockLen=16bytes */ \
{ /* one block encryption */ \
	ROUND_function(0);  \
	ROUND_function(2);  \
	ROUND_function(4);  \
	ROUND_function(6);  \
	ROUND_function(8);  \
	ROUND_function(10); \
	ROUND_function(12); \
	G_function(14);     \
	B_function(15);     \
	COPY_BLOCK(data,tmp);\
}

int blockEncrypt (cipherInstance *cipher, keyInstance *keys, BYTE *input,
				 int inputLen, BYTE *outBuffer)
{
	if (cipher == NULL) return BAD_CIPHER_STATE;
	if (keys == NULL) return BAD_KEY_INSTANCE;
	if (inputLen%128) return BAD_CIPHER_INPUT;

	if (cipher->mode == MODE_ECB) {
		RB_Enc_ecb (cipher->RED, keys->KS_Enc, input, inputLen, outBuffer);
		return R_TRUE;
	}
	if (cipher->mode == MODE_CBC) {
		RB_Enc_cbc (cipher->RED, keys->KS_Enc,cipher->IV, input, inputLen, outBuffer);
		return R_TRUE;
	}
	if (cipher->mode == MODE_CFB1) {
		RB_Enc_cfb1 (cipher->RED, keys->KS_Enc,cipher->IV, input, inputLen, outBuffer);
		return R_TRUE;
	}
	return BAD_CIPHER_MODE;
}

/* ECB-mode encryption */
static void RB_Enc_ecb (BYTE *table, BYTE *cipherKey, BYTE *input, int inputLen, 
						BYTE *outBuffer)
{
	WORD32 tmp[4], data[4], key[2*(R+1)][4];
	WORD32 *scan, *tar;
	BYTE *SBox;
	int i, ib;

	SBox = table;
	scan = WD(cipherKey);
	for (i=0; i<2*(R+1); i++) {
		COPY_BLOCK(key[i], scan);
		scan += 4;
	}

	ib = inputLen/BITSPERBLOCK;  /* check # of cyphering blocks */
	scan = WD(input);
	tar = WD(outBuffer);

	for (i=0; i<ib; i++) {
		COPY_BLOCK(data, scan);
		ONEBLOCK_CIPH; /* encrypt */
		COPY_BLOCK(tar, data);
		scan += BLOCK_WSIZE;
		tar += BLOCK_WSIZE;
	}
}

#define BLOCK_XOR(B, A) \
{ \
	B[0] ^= A[0];\
	B[1] ^= A[1];\
	B[2] ^= A[2];\
	B[3] ^= A[3];\
}
/* CBC-mode encryption */
static void RB_Enc_cbc (BYTE *table, BYTE *cipherKey, BYTE *iv, BYTE *input, int inputLen, 
					BYTE *outBuffer)
{
	WORD32 tmp[4], data[4], key[2*(R+1)][4];
	WORD32 *scan, *tar;
	BYTE *SBox;
	int i, ib;

	SBox = table;
	scan = WD(cipherKey);
	for (i=0; i<2*(R+1); i++) {
		COPY_BLOCK(key[i], scan);
		scan += 4;
	}

	ib = inputLen/BITSPERBLOCK;  /* check # of cyphering blocks */
	scan = WD(input);
	tar = WD(outBuffer);

	COPY_BLOCK(data, scan);
	BLOCK_XOR(data, WD(iv));  /* added initial vector */
	ONEBLOCK_CIPH; /* encrypt */
	COPY_BLOCK(tar, data);

	for (i=1; i<ib; i++) {
		scan += BLOCK_WSIZE;
		tar += BLOCK_WSIZE;
		BLOCK_XOR(data, scan);  /* cipher block chaining */
		ONEBLOCK_CIPH; /* encrypt */
		COPY_BLOCK(tar, data);
	}
}

#define LSHIFT_PAST(D, b) \
{ /* shift by 1bit of and paste 1bit to cipher input data */ \
	dt = D[0]>>31;       \
	D[0] = (D[0]<<1)|b;  \
	df = (D[1]<<1)|dt;   \
	dt = D[1]>>31;       \
	D[1] = df;           \
	df = (D[2]<<1)|dt;   \
	dt = D[2]>>31;       \
	D[2] = df;           \
	D[3] = (D[3]<<1)|dt; \
}

/* CFB1-mode encryption */
static void RB_Enc_cfb1 (BYTE *table, BYTE *cipherKey, BYTE *iv, BYTE *input, int inputLen, 
					BYTE *outBuffer)
{
	WORD32 tmp[4], data[4], feed[4], key[2*(R+1)][4], df,dt, *cnv;
	BYTE *scan, *tar, *SBox;
	register BYTE grab, bit, fback;
	int i, j;

	SBox = table;
	cnv = WD(cipherKey);
	for (i=0; i<2*(R+1); i++) {
		COPY_BLOCK (key[i], cnv);
		cnv += 4;

_rainbow.c  view on Meta::CPAN

	tmp[3] = (data[0] & key[(RN)][3])^\
		  (data[1] & key[(RN)][0])^   \
		  (data[2] & key[(RN)][1])^   \
		  (data[3] & key[(RN)][2]);   \
}

//#define R_function(TABLE) 
#define R_function(TABLE) \
{ /* R-layer */ \
	data[0] = PUTB1((TABLE)[GETB0(tmp[0])])|  \
		PUTB0((TABLE)[256+GETB1(tmp[0])])|    \
		PUTB3((TABLE)[GETB2(tmp[0])])|        \
		PUTB2((TABLE)[256+GETB3(tmp[0])]);    \
	data[1] = PUTB2((TABLE)[GETB0(tmp[1])])|  \
		PUTB0((TABLE)[256+GETB2(tmp[1])])|    \
		PUTB3((TABLE)[GETB1(tmp[1])])|        \
		PUTB1((TABLE)[256+GETB3(tmp[1])]);    \
	data[2] = PUTB3((TABLE)[GETB0(tmp[2])])|  \
		PUTB0((TABLE)[256+GETB3(tmp[2])])|    \
		PUTB2((TABLE)[GETB1(tmp[2])])|        \
		PUTB1((TABLE)[256+GETB2(tmp[2])]);    \
	data[3] = PUTB2((TABLE)[GETB0(tmp[3])])|  \
		PUTB0((TABLE)[256+GETB2(tmp[3])])|    \
		PUTB3((TABLE)[GETB1(tmp[3])])|        \
		PUTB1((TABLE)[256+GETB3(tmp[3])]);    \
}

/*
#define ROUND_function(key_num) \
{ \
	G_function((key_num));   \
	B_function((key_num+1)); \
	R_function(SBox);        \
}
*/
#define ONEBLOCK_CIPH /* here : only for the blockLen=16bytes */\
{ /* one block encryption */ \
	ROUND_function(0);  \
	ROUND_function(2);  \
	ROUND_function(4);  \
	ROUND_function(6);  \
	ROUND_function(8);  \
	ROUND_function(10); \
	ROUND_function(12); \
	G_function(14);     \
	B_function(15);     \
	COPY_BLOCK(data,tmp);\
}

int blockDecrypt (cipherInstance *cipher, keyInstance *keys, BYTE *input,
				 int inputLen, BYTE *outBuffer)
{
	if (cipher == NULL) return BAD_CIPHER_STATE;
	if (keys == NULL) return BAD_KEY_INSTANCE;
	if (inputLen%128) return BAD_CIPHER_INPUT;

	if (cipher->mode == MODE_ECB) {
		RB_Dec_ecb (cipher->RED, keys->KS_Dec, input, inputLen, outBuffer);
		return R_TRUE;
	}
	if (cipher->mode == MODE_CBC) {
		RB_Dec_cbc (cipher->RED, keys->KS_Dec, cipher->IV, input, inputLen, outBuffer);
		return R_TRUE;
	}
	if (cipher->mode == MODE_CFB1) {
		RB_Dec_cfb1 (cipher->RED, keys->KS_Enc,cipher->IV, input, inputLen, outBuffer);
		return R_TRUE;
	}
	return BAD_CIPHER_MODE;
}

/* ECB-mode encryption */
static void RB_Dec_ecb (BYTE *table, BYTE *cipherKey, BYTE *input, int inputLen, BYTE *outBuffer)
{
	WORD32 tmp[4], data[4],key[2*(R+1)][4];
	WORD32 *scan, *tar;
	BYTE *SBox;
	int i, ib;

	SBox = table;
	scan = WD(cipherKey);
	for (i=0; i<2*(R+1); i++) {
		COPY_BLOCK (key[i], scan);
		scan += 4;
	}

	ib = inputLen/BITSPERBLOCK;  /* check # of cyphering blocks */
	scan = WD(input);
	tar = WD(outBuffer);

	for (i=0; i<ib; i++) {
		COPY_BLOCK (data, scan);
		ONEBLOCK_CIPH ;
		COPY_BLOCK (tar, data);
		scan += BLOCK_WSIZE;
		tar += BLOCK_WSIZE;
	}
}

/*
#define BLOCK_XOR(B, A) \
{ \
	B[0] ^= A[0]; \
	B[1] ^= A[1]; \
	B[2] ^= A[2]; \
	B[3] ^= A[3]; \
}
*/
/* CBC-mode encryption */
static void RB_Dec_cbc (BYTE *table, BYTE *cipherKey, BYTE *iv, BYTE *input, int inputLen, 
					BYTE *outBuffer)
{
	WORD32 tmp[4], data[4], key[2*(R+1)][4], pred[4];
	WORD32 *scan, *tar;
	BYTE *SBox;
	int i, ib;

	SBox = table;
	scan = WD(cipherKey);
	for (i=0; i<2*(R+1); i++) {
		COPY_BLOCK (key[i], scan);
		scan += 4;
	}

	ib = inputLen/BITSPERBLOCK;  /* check # of cyphering blocks */
	scan = WD(input);
	tar = WD(outBuffer);

	COPY_BLOCK(data, scan);
	COPY_BLOCK(pred, data); /* grab into 'pred' to recover 
	             the next ciphertext */
	ONEBLOCK_CIPH;  /* decrypt */
	BLOCK_XOR(data, WD(iv));  /* added initial vector to recover
	             original plaintext */
	COPY_BLOCK(tar, data);

	for (i=1; i<ib; i++) {
		scan += BLOCK_WSIZE;
		tar += BLOCK_WSIZE;
		COPY_BLOCK(data, scan);
		ONEBLOCK_CIPH;  /* decrypt */
		BLOCK_XOR(data, pred);  /* recover plaintext using predecessor */
		COPY_BLOCK(tar, data);
		COPY_BLOCK(pred, scan);
	}
}

#define LSHIFT_PAST(D, b) \
{ /* shift by 1bit of and paste 1bit to cipher input data */ \
	dt = D[0]>>31;       \
	D[0] = (D[0]<<1)|b;  \
	df = (D[1]<<1)|dt;   \
	dt = D[1]>>31;       \
	D[1] = df;           \
	df = (D[2]<<1)|dt;   \
	dt = D[2]>>31;       \
	D[2] = df;           \
	D[3] = (D[3]<<1)|dt; \
}
/* CFB1-mode encryption */
static void RB_Dec_cfb1 (BYTE *table, BYTE *cipherKey, BYTE *iv, BYTE *input, int inputLen, 
					BYTE *outBuffer)
{
	WORD32 tmp[4], data[4],feed[4], key[2*(R+1)][4], df,dt, *cnv;
	BYTE *scan, *tar, *SBox;
	register BYTE grab, bit, pred;
	int i, j;

	SBox = table;

_rainbow.c  view on Meta::CPAN

			LSHIFT_PAST(feed, pred);  /* preparing cipher input block */
			COPY_BLOCK(data, feed);
			ONEBLOCK_CIPH ;  /* decrypt */
			bit =(BYTE)(data[3]>>31);
		}
		*tar = grab;		
		scan++;
		tar++;
	}
}

#define ITERATIONS 1024

void blockPrint(char *buf, int length);
static void cipher_correct_test(void);
static void cipher_speed_test(void);


static const BYTE plainSrc[1024] = {0, };



int main (void)
{
	cipher_correct_test();
	cipher_speed_test();
	return 0;
}

void cipher_correct_test(void)
{
	keyInstance keys;
	cipherInstance ciph;
	BYTE ptext[1024], ctext[1024], keySrc[MAX_KEY_SIZE], inV[MAX_IV_SIZE];
	int i, textLen=1024*8, keySrcLen=16*8, status;


	for (i=0; i<1024; i++) {
		ptext[i] = 0;
		ctext[i] = 0;
	}
	for (i=0; i<MAX_KEY_SIZE; i++) keySrc[i] = 0;
	for (i=0; i<MAX_IV_SIZE; i++) inV[i] = 1; 

	status = makeKey(&keys, DIR_ENCRYPT, keySrcLen, (char *)keySrc);
	if (status != R_TRUE) {
		printf("Error Occured!__er_code=%d\n",status);
		exit(1);
	}
	/* ECB TEST start-- */
	status = cipherInit(&ciph, MODE_ECB, (char *)inV); 
	if (status != R_TRUE) {
		printf("Error Occured!__er_code=%d\n",status);
		exit(1);
	}
	status =blockEncrypt(&ciph, &keys, (BYTE *)ptext, textLen,(BYTE *)ctext);
	status =blockDecrypt(&ciph, &keys, (BYTE *)ctext, textLen,(BYTE *)ptext);
	if (strncmp(plainSrc,ptext,1024)==0) printf("----ECB : OK!----\n");
	else printf("----ECB : FAIL!-----\n");

	/* CBC TEST start--- */
	status = cipherInit(&ciph, MODE_CBC, (char *)inV); 
	if (status != R_TRUE) {
		printf("Error Occured!__er_code=%d\n",status);
		exit(1);
	}
	status =blockEncrypt(&ciph, &keys, (BYTE *)ptext, textLen,(BYTE *)ctext);
	status =blockDecrypt(&ciph, &keys, (BYTE *)ctext, textLen,(BYTE *)ptext);
	if (strncmp(plainSrc,ptext,1024)==0) printf("----CBC : OK!----\n");
	else printf("----CBC : FAIL!-----\n");

	/* CFB1 TEST start--- */
	status = cipherInit(&ciph, MODE_CFB1, (char *)inV); 
	if (status != R_TRUE) {
		printf("Error Occured!__er_code=%d\n",status);
		exit(1);
	}
	status =blockEncrypt(&ciph, &keys, (BYTE *)ptext, textLen,(BYTE *)ctext); 
	status =blockDecrypt(&ciph, &keys, (BYTE *)ctext, textLen,(BYTE *)ptext); 
	if (strncmp(plainSrc,ptext,1024)==0) printf("----CFB1 : OK!----\n");
	else printf("----CFB1 : FAIL!-----\n");
}

void blockPrint(char *buf, int length)
{
	int i;

	for (i=0; i<length; i++) {
		printf("%02x",buf[i]&0xff);
	}
	printf("\n");
}

static void cipher_speed_test(void)
{
	keyInstance keys;
	cipherInstance ciph;
	BYTE ptext[1024], ctext[1024], keySrc[MAX_KEY_SIZE], inV[MAX_IV_SIZE];
	int i, textLen=1024*8, keySrcLen=16*8, status;
	clock_t elapsed;
	double sec;

	for (i=0; i<1024; i++) {
		ptext[i] = 0;
		ctext[i] = 0;
	}
	for (i=0; i<MAX_KEY_SIZE; i++) keySrc[i] = 0;
	for (i=0; i<MAX_IV_SIZE; i++) inV[i] = 1; 

	status = makeKey(&keys, DIR_ENCRYPT, keySrcLen, (char *)keySrc);
	if (status != R_TRUE) {
		printf("Error Occured!__er_code=%d\n",status);
		exit(1);
	}

	status = cipherInit(&ciph, MODE_ECB, (char *)inV); 
	if (status != R_TRUE) {
		printf("Error Occured!__er_code=%d\n",status);
		exit(1);
	}
	elapsed = -clock();
	for (i=0; i<ITERATIONS; i++) {
		status =blockEncrypt(&ciph, &keys, (BYTE *)ptext, textLen,(BYTE *)ctext);
		strncpy (ctext, ptext, 1024);
	}
	elapsed += clock ();
	sec = elapsed ? (double) elapsed / CLOCKS_PER_SEC : 1.0;
	printf("****ECB_speed.... ");
	printf (" %.4f sec(1Mbytes), %.4f Mbytes/sec.\n",
		sec, 1./sec);

	status = cipherInit(&ciph, MODE_CBC, (char *)inV); 
	if (status != R_TRUE) {
		printf("Error Occured!__er_code=%d\n",status);
		exit(1);
	}
	elapsed = -clock();
	for (i=0; i<ITERATIONS; i++) {
		status =blockEncrypt(&ciph, &keys, (BYTE *)ptext, textLen,(BYTE *)ctext);
		strncpy (ctext, ptext, 1024);
	}
	elapsed += clock ();
	sec = elapsed ? (double) elapsed / CLOCKS_PER_SEC : 1.0;
	printf("****CBC_speed.... ");
	printf (" %.4f sec(1Mbytes), %.4f Mbytes/sec.\n",
		sec, 1./sec);
}



( run in 0.581 second using v1.01-cache-2.11-cpan-e1769b4cff6 )