/***************************************************************************
                                                                           *
Copyright 2013 CertiVox UK Ltd.                                           *
                                                                           *
This file is part of CertiVox MIRACL Crypto SDK.                           *
                                                                           *
The CertiVox MIRACL Crypto SDK provides developers with an                 *
extensive and efficient set of cryptographic functions.                    *
For further information about its features and functionalities please      *
refer to http://www.certivox.com                                           *
                                                                           *
* The CertiVox MIRACL Crypto SDK is free software: you can                 *
  redistribute it and/or modify it under the terms of the                  *
  GNU Affero General Public License as published by the                    *
  Free Software Foundation, either version 3 of the License,               *
  or (at your option) any later version.                                   *
                                                                           *
* The CertiVox MIRACL Crypto SDK is distributed in the hope                *
  that it will be useful, but WITHOUT ANY WARRANTY; without even the       *
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
  See the GNU Affero General Public License for more details.              *
                                                                           *
* You should have received a copy of the GNU Affero General Public         *
  License along with CertiVox MIRACL Crypto SDK.                           *
  If not, see <http://www.gnu.org/licenses/>.                              *
                                                                           *
You can be released from the requirements of the license by purchasing     *
a commercial license. Buying such a license is mandatory as soon as you    *
develop commercial activities involving the CertiVox MIRACL Crypto SDK     *
without disclosing the source code of your own applications, or shipping   *
the CertiVox MIRACL Crypto SDK with a closed source product.               *
                                                                           *
***************************************************************************/
/*
 * Implementation of BPS Format Preserving Encryption
 *
 * See "BPS: a Format Preserving Encryption Proposal" by E. Brier, T. Peyrin and J. Stern
 *
 * http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/bps/bps-spec.pdf
 *
 * Uses AES internally
 *
 * Author: M. Scott 2012/2015
 */

#include <stdlib.h> 
#include "miracl.h"

/* Define FPE_TEST to activate test main program and run test vectors */
/* Link with mraes.c */
/* gcc -O2 mrfpe.c mraes.c -o mrfpe.exe */
/* #define FPE_TEST */

#define UINT32 mr_unsign32 /* 32-bit unsigned type */
#define W 8 /* recommended number of rounds */
#define BLOCK_SIZE 16 /* 16 Byte Blocks - AES */
#define ENCRYPT 0
#define DECRYPT 1

static void unpack(UINT32 a,MR_BYTE *b)
{ /* unpack bytes from a word */
    b[0]=MR_TOBYTE(a);
    b[1]=MR_TOBYTE(a>>8);
    b[2]=MR_TOBYTE(a>>16);
    b[3]=MR_TOBYTE(a>>24);
}

/* Little Endian */

static int to_base_256(char *x,int len,int s,MR_BYTE *y)
{ /* x[] of length len to base s is converted to byte array y[] of length BLOCK_SIZE */
	int i,j,m;
	UINT32 c;

	for (i=0;i<BLOCK_SIZE;i++) y[i]=0;
	if (len==0) return 0;	

	m=1; y[0]=x[len-1];
	for (j=len-2;j>=0;j--)
	{ /* multiply by s */
		c=x[j];
		for (i=0;i<m;i++)
		{
			c+=(UINT32)y[i]*s;
			y[i]=c&0xff;
			c>>=8;
		}
		if (c>0) {m++; y[m-1]=c;}
	}
	
	return m;
}

/* Find max_b for chosen cipher and number base */

static int maxb(int s)
{
	MR_BYTE y[BLOCK_SIZE];
	int i,m,n,c;
	if (s==2) return 192;
	m=1; y[0]=1;
	for (n=0;;n++)
	{
		c=0;
		for (i=0;i<m;i++)
		{ /* multiply y by s */
			c+=(UINT32)y[i]*s;
			y[i]=c&0xff;
			c>>=8;
		}
		if (c>0) {m++; y[m-1]=c;}
		if (m==13) break;	/* greater than 2^96 for AES */
	}
	return 2*n;
}

static void from_base_256(int addsub,MR_BYTE *y,int len,int s,char *x)
{ /* y[] of length BLOCK_SIZE is added to or subtracted from base s array x[] of length len. */
	int i,m,n;
	UINT32 c,d;

	m=BLOCK_SIZE;
	n=0; c=0;
	forever
	{
		while (m>0 && y[m-1]==0) m--;
		d=0;
		for (i=m-1;i>=0;i--)
		{ /* divide y by s */
			d=(d<<8)+y[i];
			y[i]=d/s;
			d%=s;
		}
		if (addsub==ENCRYPT)
		{ /* ADD */
			d+=c+x[n]; c=0;
			if ((int)d>=s) 
				{c=1; x[n]=d-s;}
			else x[n]=d;
		}
		else
		{ /* SUB */
			d+=c; c=0;
			if ((UINT32)x[n]>=d) x[n]-=d;
			else
				{x[n]+=(s-d); c=1;}
		}
		n++;
		if (n>=len) break;
	}
}

/* AES instance must be initialised and passed */
/* Format Preserving Encryption/Decryption routine */
/* Array x of length len to base s is encrypted/decrypted in place */

static void BC(int crypt,char *x,int len,int s,aes *a,UINT32 TL,UINT32 TR)
{
	int i,j;
	char *left,*right;
	MR_BYTE buff[BLOCK_SIZE];
	int l,r;
	l=r=len/2;
	if (len%2==1) l++;

	left=&x[0]; right=&x[l];

	for (i=0;i<W;i++)
	{
		if (crypt==ENCRYPT) j=i;
		else j=W-i-1;
		if (j%2==0)
		{
			to_base_256(right,r,s,buff);
			unpack(TR^j,&buff[12]);
			aes_ecb_encrypt(a,buff);
			from_base_256(crypt,buff,l,s,left);
		}
		else
		{
			to_base_256(left,l,s,buff);
			unpack(TL^j,&buff[12]);
			aes_ecb_encrypt(a,buff);
			from_base_256(crypt,buff,r,s,right);
		}
	}
}

/* Algorithm 3 */

/* x is an array of length len of numbers to the base s */
/* a is an initialised AES instance  */
/* TL and TR are 32-bit tweak values */
/* x is replaced in place by encrypted values. The format of x[] is preserved */

void FPE_encrypt(int s,aes *a,UINT32 TL,UINT32 TR,char *x,int len)
{
	int i,j,c,rest,mb=maxb(s);
	if (len<=mb)
	{
		BC(ENCRYPT,x,len,s,a,TL,TR);
		return;
	}
	rest=len%mb;
	c=0; i=0;
	while (len-c>=mb)
	{
		if (i!=0) for (j=c;j<c+mb;j++) x[j]=(x[j]+x[j-mb])%s;
		BC(ENCRYPT,&x[c],mb,s,a,TL^(i<<16),TR^(i<<16));
		c+=mb; i++;
	}
	if (len!=c)
	{
		for (j=len-rest;j<len;j++)
			x[j]=(x[j]+x[j-mb])%s;
		BC(ENCRYPT,&x[len-mb],mb,s,a,TL^(i<<16),TR^(i<<16));
	}
}

/* Algorithm 4 */

void FPE_decrypt(int s,aes *a,UINT32 TL,UINT32 TR,char *x,int len)
{
	int i,j,c,rest,mb=maxb(s);
	int b;
	if (len<=mb)
	{
		BC(DECRYPT,x,len,s,a,TL,TR);
		return;
	}
	rest=len%mb;
	c=len-rest; i=c/mb;
	if (len!=c)
	{
		BC(DECRYPT,&x[len-mb],mb,s,a,TL^(i<<16),TR^(i<<16));
		for (j=len-rest;j<len;j++)
			{b=(x[j]-x[j-mb])%s; if (b<0) x[j]=b+s; else x[j]=b;}
	}
	while (c!=0)
	{
		c-=mb; i--;
		BC(DECRYPT,&x[c],mb,s,a,TL^(i<<16),TR^(i<<16));
		if (i!=0) for (j=c;j<c+mb;j++) {b=(x[j]-x[j-mb])%s; if (b<0) x[j]=b+s; else x[j]=b;}
	}
}

/* Test Program - runs NIST test vectors from http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/FF3samples.pdf */

#ifdef FPE_TEST

int main()
{
	int i,j,n,radix;
	aes a;
	char key[32];
	char x[256];    /* any length... */
	UINT32 TL,TR;

//# sample #1

	radix=10;
	TL=0xD8E7920A;
	TR=0xFA330A73; /* random tweaks */

/* Set AES key */
//EF 43 59 D8 D5 80 AA 4F 7F 03 6D 6F 04 FC 6A 94 

	key[15]=0xEF; key[14]=0x43; key[13]=0x59; key[12]=0xD8; key[11]=0xD5; key[10]=0x80; key[9]=0xAA; key[8]=0x4F;
	key[7]=0x7F; key[6]=0x03; key[5]=0x6D; key[4]=0x6F; key[3]=0x04; key[2]=0xFC; key[1]=0x6A; key[0]=0x94;

	printf("\n128 bit aes key= ");
	for (i=0;i<16;i++)
		printf("%02x",(unsigned char) key[i]);
	printf("\n");

    aes_init(&a,MR_ECB,16,key,NULL);

	n=18;
	x[0]=8; x[1]=9; x[2]=0; x[3]=1; x[4]=2; x[5]=1; x[6]=2; x[7]=3;
	x[8]=4; x[9]=5; x[10]=6; x[11]=7; x[12]=8; x[13]=9; x[14]=0; x[15]=0; x[16]=0; x[17]=0;

/* Encrypt/decrypt short string */

	printf("\nSample #1\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");

//sample #2

	TL=0x9A768A92;
	TR=0xF60E12D8;

/* Encrypt/decrypt short string */

	printf("\nSample #2\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");

//sample #3

	n=29;
	x[0]=8; x[1]=9; x[2]=0; x[3]=1; x[4]=2; x[5]=1; x[6]=2; x[7]=3;
	x[8]=4; x[9]=5; x[10]=6; x[11]=7; x[12]=8; x[13]=9; x[14]=0; x[15]=0; x[16]=0; x[17]=0;
	x[18]=0; x[19]=0; x[20]=7; x[21]=8; x[22]=9; x[23]=0; x[24]=0; x[25]=0; x[26]=0; x[27]=0; x[28]=0;

	TL=0xD8E7920A;
	TR=0xFA330A73; /* random tweaks */

/* Encrypt/decrypt short string */

	printf("\nSample #3\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");

// sample #4
	TL=0x0;
	TR=0x0;

	printf("\nSample #4\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n"); 

// sample #5

	radix=26;
	TL=0x9A768A92;
	TR=0xF60E12D8;

	n=19;
	x[0]=0; x[1]=1; x[2]=2; x[3]=3; x[4]=4; x[5]=5; x[6]=6; x[7]=7;
	x[8]=8; x[9]=9; x[10]=10; x[11]=11; x[12]=12; x[13]=13; x[14]=14; x[15]=15; x[16]=16; x[17]=17;
	x[18]=18; 

	printf("\nSample #5\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n"); 

// sample #6

	key[23]=0xEF; key[22]=0x43; key[21]=0x59; key[20]=0xD8; key[19]=0xD5; key[18]=0x80; key[17]=0xAA; key[16]=0x4F;
	key[15]=0x7F; key[14]=0x03; key[13]=0x6D; key[12]=0x6F; key[11]=0x04; key[10]=0xFC; key[9]=0x6A;  key[8]=0x94;
	key[7]=0x2b;  key[6]=0x7E;  key[5]=0x15;  key[4]=0x16;  key[3]=0x28;  key[2]=0xAE;  key[1]=0xD2;  key[0]=0xA6;

	printf("\n192-bit aes key= ");
	for (i=0;i<24;i++)
		printf("%02x",(unsigned char) key[i]);
	printf("\n");

    aes_init(&a,MR_ECB,24,key,NULL);

	n=18;
	x[0]=8; x[1]=9; x[2]=0; x[3]=1; x[4]=2; x[5]=1; x[6]=2; x[7]=3;
	x[8]=4; x[9]=5; x[10]=6; x[11]=7; x[12]=8; x[13]=9; x[14]=0; x[15]=0; x[16]=0; x[17]=0;

	radix=10;
	TL=0xD8E7920A;
	TR=0xFA330A73; /* random tweaks */

	printf("\nSample #6\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n"); 

// sample #7

	TL=0x9A768A92;
	TR=0xF60E12D8;

	printf("\nSample #7\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n"); 

// sample #8

	n=29;
	x[0]=8; x[1]=9; x[2]=0; x[3]=1; x[4]=2; x[5]=1; x[6]=2; x[7]=3;
	x[8]=4; x[9]=5; x[10]=6; x[11]=7; x[12]=8; x[13]=9; x[14]=0; x[15]=0; x[16]=0; x[17]=0;
	x[18]=0; x[19]=0; x[20]=7; x[21]=8; x[22]=9; x[23]=0; x[24]=0; x[25]=0; x[26]=0; x[27]=0; x[28]=0;

	TL=0xD8E7920A;
	TR=0xFA330A73; /* random tweaks */

	printf("\nSample #8\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n"); 

// sample #9

	TL=0x0;
	TR=0x0;

	printf("\nSample #9\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n"); 

// sample #10

	radix=26;
	TL=0x9A768A92;
	TR=0xF60E12D8;

	n=19;
	x[0]=0; x[1]=1; x[2]=2; x[3]=3; x[4]=4; x[5]=5; x[6]=6; x[7]=7;
	x[8]=8; x[9]=9; x[10]=10; x[11]=11; x[12]=12; x[13]=13; x[14]=14; x[15]=15; x[16]=16; x[17]=17;
	x[18]=18; 

	printf("\nSample #10\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n"); 

// sample #11

	key[31]=0xEF; key[30]=0x43; key[29]=0x59; key[28]=0xD8; key[27]=0xD5; key[26]=0x80; key[25]=0xAA; key[24]=0x4F;
	key[23]=0x7F; key[22]=0x03; key[21]=0x6D; key[20]=0x6F; key[19]=0x04; key[18]=0xFC; key[17]=0x6A; key[16]=0x94;
	key[15]=0x2b; key[14]=0x7E; key[13]=0x15; key[12]=0x16; key[11]=0x28; key[10]=0xAE; key[9]=0xD2;  key[8]=0xA6;
	key[7]=0xAB;  key[6]=0xF7;  key[5]=0x15;  key[4]=0x88;  key[3]=0x09;  key[2]=0xCF;  key[1]=0x4F;  key[0]=0x3C;

	printf("\n256-bit aes key= ");
	for (i=0;i<32;i++)
		printf("%02x",(unsigned char) key[i]);
	printf("\n");

    aes_init(&a,MR_ECB,32,key,NULL);

	n=18;
	x[0]=8; x[1]=9; x[2]=0; x[3]=1; x[4]=2; x[5]=1; x[6]=2; x[7]=3;
	x[8]=4; x[9]=5; x[10]=6; x[11]=7; x[12]=8; x[13]=9; x[14]=0; x[15]=0; x[16]=0; x[17]=0;

	radix=10;
	TL=0xD8E7920A;
	TR=0xFA330A73; /* random tweaks */

	printf("\nSample #11\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n"); 

// sample #12

	TL=0x9A768A92;
	TR=0xF60E12D8;

	printf("\nSample #12\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n"); 

// sample #13

	n=29;
	x[0]=8; x[1]=9; x[2]=0; x[3]=1; x[4]=2; x[5]=1; x[6]=2; x[7]=3;
	x[8]=4; x[9]=5; x[10]=6; x[11]=7; x[12]=8; x[13]=9; x[14]=0; x[15]=0; x[16]=0; x[17]=0;
	x[18]=0; x[19]=0; x[20]=7; x[21]=8; x[22]=9; x[23]=0; x[24]=0; x[25]=0; x[26]=0; x[27]=0; x[28]=0;

	TL=0xD8E7920A;
	TR=0xFA330A73; /* random tweaks */

	printf("\nSample #13\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n"); 

// sample #14

	TL=0x0;
	TR=0x0; /* random tweaks */

	printf("\nSample #14\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n"); 

// sample #15

	radix=26;
	TL=0x9A768A92;
	TR=0xF60E12D8;

	n=19;
	x[0]=0; x[1]=1; x[2]=2; x[3]=3; x[4]=4; x[5]=5; x[6]=6; x[7]=7;
	x[8]=8; x[9]=9; x[10]=10; x[11]=11; x[12]=12; x[13]=13; x[14]=14; x[15]=15; x[16]=16; x[17]=17;
	x[18]=18; 

	printf("\nSample #15\n");
	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_encrypt(radix,&a,TL,TR,x,n);

	printf("Ciphertext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");
	FPE_decrypt(radix,&a,TL,TR,x,n);

	printf("Plaintext=\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n"); 

// Timing Test

	radix=10;
	TL=0xD8E7920A;
	TR=0xFA330A73; /* random tweaks */

/* Set 128-bit AES key */

	key[15]=0xEF; key[14]=0x43; key[13]=0x59; key[12]=0xD8; key[11]=0xD5; key[10]=0x80; key[9]=0xAA; key[8]=0x4F;
	key[7]=0x7F; key[6]=0x03; key[5]=0x6D; key[4]=0x6F; key[3]=0x04; key[2]=0xFC; key[1]=0x6A; key[0]=0x94;

	printf("\n128-bit aes key= ");
	for (i=0;i<16;i++)
		printf("%02x",(unsigned char) key[i]);
	printf("\n");

    aes_init(&a,MR_ECB,16,key,NULL);

	n=18;
	x[0]=8; x[1]=9; x[2]=0; x[3]=1; x[4]=2; x[5]=1; x[6]=2; x[7]=3;
	x[8]=4; x[9]=5; x[10]=6; x[11]=7; x[12]=8; x[13]=9; x[14]=0; x[15]=0; x[16]=0; x[17]=0;

/* Encrypt/decrypt short string */

	printf("\nTiming test for 1 million encryption/decryptions\n");
	printf("Start..\n");

	for (j=0;j<1000000;j++)
	{
		FPE_encrypt(radix,&a,TL,TR,x,n);
		FPE_decrypt(radix,&a,TL,TR,x,n);
	}
	printf("Finished\n");
	for (i=0;i<n;i++) printf("%d ",x[i]);
	printf("\n");


	return 0;
}

#endif
