URL
https://opencores.org/ocsvn/twofish/twofish/trunk
Subversion Repositories twofish
[/] [twofish/] [trunk/] [twofish_manual_en.txt] - Rev 13
Compare with Previous | Blame | View Log
TWOFISH MANUAL(c) 2006 Spyros NinosThis document is under the GPL. See file COPYING for licence details.1. Introduction2. Crypto primitives usage3. Testbenches4. Misc + Tips1. INTRODUCTION===============Twofish is a 128bit-block symmetric cipher, finalist candidate for the AES contest.It supports keys of 128, 192, 256 and all the sizes below 256 bits (with padding). Thisimplementation accepts keys of 128, 192 and 256 bits. If you want a different size thenyou'll have to create the padder yourself. The implementation was written in a VHDL 87and 93 mixed versions. Just to be sure, use the 93 version in compilation. The namingconvention for the components is kept as simple but self-explanatory as I could. I hadin mind that it would be possible to use two or three ciphers in the same design, sonames are such that there would be no name-conflict (I hope...). For every key-dependedcomponent the respective key size was used in the name to indicate the component'starget (i.e twofish_S128 is for 128 bit key). The cipher components are purecombinational circuits. This decision was based upon the assumption of portability.Since no memory is used, it can be implemented in any programmable device. Also, maximumflexibility was intended by dividing the cipher in key-parts. By doing this, youhave the choice to implement the cipher as a rolled out, iterative, pipelined or anyother architecture you may like to build.2. CRYPTO PRIMITIVES USAGE==========================The twofish.vhd file is divided in four parts. Firstly, there's the part where allthe key-independent components are found. The next three parts concern the componentsthat depend on the key - 128, 192 and 256 bits respectively.In the file you'll find the below main components:1) twofish_data_input2) twofish_data_output3) twofish_S1284) twofish_keysched1285) twofish_whit_keysched1286) twofish_encryption_round1287) twofish_decryption_round1288) twofish_S1929) twofish_keysched19210) twofish_whit_keysched19211) twofish_encryption_round19212) twofish_decryption_round19213) twofish_S25614) twofish_keysched25615) twofish_whit_keysched25616) twofish_encryption_round25617) twofish_decryption_round256You'll also find all the other components that the above depend on, but they are notimportant in building the cipher - except perhaps if you want to study the structureof this implementation and/or modify it. A short description of them follows:1) The first component is the TWOFISH_DATA_INPUT, which is a simple tranformation of theinput data from the way we provide it (which is big endian) to little endian convention,as required by the twofish specification. It must be used as an interface between theinput data provided to the circuit and the rest of the cipher. An alternative would beto extract the code from it and integrate it to another component. Note that since thedata block size of the cipher is always 128 bits, this component is supposed to be usedwith the components of all the key-sizes. The interface of the component is as follows:entity twofish_data_input isport (in_tdi : in std_logic_vector(127 downto 0);out_tdi : out std_logic_vector(127 downto 0));end twofish_data_input;It is quite simple; in_tdi is the data input as we provide it and out_tdi is thetransformed input data. (tdi comes from the Twofish Data Input)2) The component TWOFISH_DATA_OUTPUT makes the reverse procedure of the twofish_data_input.It takes the little endian convention cipher result and transforms it to the big endianone, as the specification requires. This component too is supposed to be used with thecomponents of all the key-sizes. The interface is as follows:entity twofish_data_output isport (in_tdo : in std_logic_vector(127 downto 0);out_tdo : out std_logic_vector(127 downto 0));end twofish_data_output;in_tdo accepts the ciphertext as we take it from the last round and out_tdo is thetranformed ciphertext. (tdo comes from the Twofish Data Output)3) The TWOFISH_S128 is a component that takes the key of 128 bits and produces the S0and S1 for the f function. The interface is as follows:entity twofish_S128 isport (in_key_ts128 : in std_logic_vector(127 downto 0);out_Sfirst_ts128,out_Ssecond_ts128 : out std_logic_vector(31 downto 0));end twofish_S128;Here, in_key_ts128 is the key that we provide. Note that there is no component thattransforms the key to the form that the twofish specification requires; rather thetranformation takes place within the twofish_S128 component. Here, there is theassumption/association that Sfirst refers to S0 and Ssecond refers to S1. There isno need to remember the association, since throughout the design, the same ruleis followed, so the only thing you have to do it to connect the pins with thesame name. This component can be used only when you implement a 128 bit key sizedesign. (ts128 comes from Twofish_S128)4) The TWOFISH_KEYSCHED128 component is the key scheduler of the twofish cipher,for 128 bit keys. It's interface is as follows:entity twofish_keysched128 isport (odd_in_tk128,even_in_tk128 : in std_logic_vector(7 downto 0);in_key_tk128 : in std_logic_vector(127 downto 0);out_key_up_tk128,out_key_down_tk128 : out std_logic_vector(31 downto 0));end twofish_keysched128;odd_in_tk128 and even_in_tk128 are the numbers of the round 2i and 2i+1, as describedin the specification. Clearly, 2i relates to the even_in_tk128 and 2i+1 relates tothe odd_in_tk128. in_key_tk128 is where the key goes. The key must be supplied to thecomponents without any endian-transformation; the tranformation takes place in thecomponent, as in twofish_S128. out_key_up_tk128 and out_key_down_tk128 are the twokeys produced from the scheduler. The association is that as we look the twofishdiagram provided in the specification page 11 (figure 3), the upper key is what weget from out_key_up_tk128 and the down key is what we get from out_key_down_tk128.As before, you don't have to remember the association, names are used the same throughoutthe whole design. This component too, can be used only when you implement a 128 bit keysize design. (tk128 comes from Twofish_Keysched128).IMPORTANT NOTICE: This component can be used in two ways: in combination withtwofish_whit_keysched128 (see below) or as a standalone component. In the firstcase, whitening keys are produced by twofish_whit_keysched128; so even_in_tk128 andodd_in_tk128 must start from 8,9 respectively and above. Or if you use it standalonethen you can start from 0 and above.5) The TWOFISH_WHIT_KEYSCHED128 produces the whitening keys K0..K7. The interfaceis as follows:entity twofish_whit_keysched128 isport (in_key_twk128 : in std_logic_vector(127 downto 0);out_K0_twk128,out_K1_twk128,out_K2_twk128,out_K3_twk128,out_K4_twk128,out_K5_twk128,out_K6_twk128,out_K7_twk128 : out std_logic_vector(31 downto 0));end twofish_whit_keysched128;in_key_twk128 is where the key is connected. As above, no big-little endian tranformationmust take place. It is performed within the component. The eight outputs produce thekeys. This component too can be used only when you implement a 128 bit key size design.(twk128 comes from Twofish_Whit_Keysched128).IMPORTANT NOTICE: If this component is to be used as a combination with twofish_keysched128care should be taken when supplying numbers to the latter. Read the notice of thetwofish_keysched128.6) The TWOFISH_ENCRYPTION_ROUND128 is the component that implements one round of encryption.The interface is as follows:entity twofish_encryption_round128 isport (in1_ter128,in2_ter128,in3_ter128,in4_ter128,in_Sfirst_ter128,in_Ssecond_ter128,in_key_up_ter128,in_key_down_ter128 : in std_logic_vector(31 downto 0);out1_ter128,out2_ter128,out3_ter128,out4_ter128 : out std_logic_vector(31 downto 0));end twofish_encryption_round128;in1_ter128, in1_ter128, in1_ter128, in1_ter128 are the four 32 bit inputs to the cipherround. in_Sfirst_ter128, in_Ssecond_ter128 are the two S needed for the g functions,in_key_up_ter128 and in_key_down_ter128 are the two round keys. Note that up and downnames are given to keys according to the diagram given in Twofish spec. You don't needto worry about it, keys follow the same naming convention throughout the whole design.Finally, out1_ter128, out1_ter228, out3_ter128 and out4_ter128 are the 32 bit outputsof the encryption round (ter128 comes from Twofish_Encryption_Round128).IMPORTANT NOTICE: the output swapping is taking place IN the component. YOU HAVE TO undothe last swap after the 16th round.7) The TWOFISH_DECRYPTION_ROUND128 is the component tha implements one round of decryption.The interface is as follows:entity twofish_decryption_round128 isport (in1_tdr128,in2_tdr128,in3_tdr128,in4_tdr128,in_Sfirst_tdr128,in_Ssecond_tdr128,in_key_up_tdr128,in_key_down_tdr128 : in std_logic_vector(31 downto 0);out1_tdr128,out2_tdr128,out3_tdr128,out4_tdr128 : out std_logic_vector(31 downto 0));end twofish_decryption_round128;As in twofish_encryption_round128 component, the ports are quite self-explanatory.(tdr128 comes from Twofish_Decryption_Round128).IMPORTANT NOTICE: as in twofish_encryption_round128, inside the component the outputswapping is taking place. YOU HAVE TO undo the last swap after the 16th round.Components8) twofish_S1929) twofish_keysched19210) twofish_whit_keysched19211) twofish_encryption_round19212) twofish_decryption_round19213) twofish_S25614) twofish_keysched25615) twofish_whit_keysched25616) twofish_encryption_round25617) twofish_decryption_round256work exactly as their 128 bit counterparts. The only difference is the third S thatis provided by twofish_S192 and needed by some of the rest of them, and the fourthS that is provided by twofish_S256. I.e:entity twofish_S192 isport (in_key_ts192 : in std_logic_vector(191 downto 0);out_Sfirst_ts192,out_Ssecond_ts192,out_Sthird_ts192 : out std_logic_vector(31 downto 0));end twofish_S192;which provide a third S that is used in twofish encryption and decryption rounds for192 bits and the fourth S that is provided from the twofish_S256 is used by thetwofish encryption and decryption rounds for 256 bits.Every IMPORTANT NOTICE that exist for the 128 bit components, are valid forthese components too.3. TESTBENCHES==============Testbenches for the cipher are provided for Tables, Variable key, Variable text,ECB/CBC Monte Carlo encryption and decryption tests. Every testbench comes withit's respective testvector file. The testvector file is transformed into a formthat it's easier to be manipulated, than in the original form supplied by thecipher designer(s).Every testbench produces a file with the results, that can be cross-checkedwith the testvector file of input - just to be certain that results are asexpected (usually with "diff").Along with the transformed testvector files, the orignal testvector files - whichare provided by the cipher designer(s) - are given. That way, you can check theoriginality of the transformed testvector files if you want to.Finally, some secondary circuits are provided for the testbenches to work. Theseare a 128 bit register, a mux and demux for 128 bit input(s)/output(s).4. MISC + TIPS==============You must pay attention in the whitening steps. None of the components actuallyimplements the input or output whitening steps. You only have the componentthat produces the whitening keys.Each cipher implementation was designed so as to demand as few components aspossible. That way, there would be no difficulty in using them and designingthe algo in its total. The problem is that the Reed Solomon used to producethe S keys is in a rolled-out form, because I chose not to use any form ofmemory. So, if you want to implement more that one key size cipher in thesame circuit/FPGA, the design size grows very much, and I doubt if it willfit in a signle FPGA. If you decide that you need more that one cipherinstantiation, then you'll have to tweak the design of the Reed Solomon.One example follows:Current implementaion is that the reed solomon components are specificallydesigned for the key size of the cipher, i.e for 128 bits key:entity reed_solomon128 isport (in_rs128 : in std_logic_vector(127 downto 0);out_Sfirst_rs128,out_Ssecond_rs128 : out std_logic_vector(31 downto 0));end reed_solomon128;and for 192 bits key:entity reed_solomon192 isport (in_rs192 : in std_logic_vector(191 downto 0);out_Sfirst_rs192,out_Ssecond_rs192,out_Sthird_rs192 : out std_logic_vector(31 downto 0));end reed_solomon192;What is happening, is that each component takes the input key, and performs themultiplications in rolled-out form of every 64 bit input. In other terms, in_rs128is split up in two 64 bit chunks, and each one is driven in it's respectivemultipliers. The result of the first multipliers is driven to out_Sfirst, the resultof the second to out_Ssecond. Respectively for reed_solomon192 the result of thethird multiplier is driven to out_Sthird and for reed_solomon256 the result of thefourth multiplier is driven to out_Sfourth. Every multiplication needs it'smultipliers (note that it is not a single mul, but a group of them because itsa matrix multiplication) so in the first component we need two groups of muls,in the second component three groups of them and in the third we need four.If you had to implement cipher with 128 and 192 sizes for example, you'd have toimplement both reed solomon components which total in 5 groups of multipliers.One solution would be to create a reed solomon that would take a single 64 bitinput and procude a single 32 bit output. For example:entity reed_solomon isport (in_rs : in std_logic_vector(63 downto 0);out_S_rs : out std_logic_vector(31 downto 0));end reed_solomon;Then you would divide the key into 64 bit chunks (128 bit in 2 chunks, 192 bitin 3 chunks and 256 bits in 4 chunks) and provide them to the componentsequentially. The results of the reed_solomon could be stored in a sort of RAM.That way you may slow down the process but you get to implement only one groupof multipliers and you gain a lot in space.The same goes for the whitening keys components. In the whitening componentsthe function h is impemented 8 times (2 h functions for each pair of keys,for the first 8 keys - K0..7). You could follow the above example and implementa component that accepts a 64 bit input (key chunk, every M is 32 bit, you need2 Ms for every h function) and produce a single 32 bit key. Thus, you canproduce every key sequentially and store it in a RAM for example.If you want some implementation examples, you'll have to read the testbenches.The cipher is implemented in iterated mode, but you'll get a clear picture of howto connect the components.
