------------------------------------------------------------
-- Copyright: 2010 Integrated Sytems Laboratory, ETH Zurich
-- http://www.iis.ee.ethz.ch/~sha3
------------------------------------------------------------
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
use work.fuguepkg.all;
entity fugue is
port (
ClkxCI : in std_logic;
RstxRBI : in std_logic;
InputEnxEI : in std_logic;
OutputEnxEO : out std_logic;
DxDI : in std_logic_vector(31 downto 0);
HashxDO : out std_logic_vector(255 downto 0));
end fugue;
architecture rtl of fugue is
component subbytes is
port (
ClkxCI : in std_logic;
RstxRBI : in std_logic;
DxDI : in std_logic_vector(7 downto 0);
DxDO : out std_logic_vector(7 downto 0));
end component;
-- FSM state (0...5)
signal StatexDP, StatexDN : unsigned(2 downto 0);
signal StateMatxDP, StateMatxDN : statematrix;
signal CXOR_1_27xD, CXOR_2_28xD, CXOR_3_29xD, CXOR_8_DxD : std_logic_vector(31 downto 0);
signal CXOR_0_10xD, CXOR_1_12xD, CXOR_2_13xD, CXOR_3_14xD : std_logic_vector(31 downto 0);
signal CXOR_0_4xD, CXOR_1_24xD, CXOR_0_15xD : std_logic_vector(31 downto 0);
signal CXOR_0_16xD, CXOR_1_24_27xD, CXOR_1_12_24xD : std_logic_vector(31 downto 0);
signal CcountxDP, CcountxDN : unsigned(3 downto 0);
signal DcountxDP, DcountxDN : unsigned(3 downto 0);
signal SMixInxD : smixstatemat; -- Signal after the mux, before SMIX is applied
signal SMixedxD : smixstate;
signal Shift2xD : smixstate;
signal Shift1xD : smixstate;
signal Mult7xD : smixstate;
signal SBoxedxD : smixstate;
begin -- rtl
-- Column XORs (including a XOR with the input data)
-- Used by the FSM
CXOR_1_27xD <= StateMatxDP(1) xor StateMatxDP(27);
CXOR_1_12_24xD <= StateMatxDP(1) xor StateMatxDP(12) xor StateMatxDP(24);
CXOR_1_24_27xD <= StateMatxDP(1) xor StateMatxDP(24) xor StateMatxDP(27);
CXOR_2_28xD <= StateMatxDP(2) xor StateMatxDP(28);
CXOR_3_29xD <= StateMatxDP(3) xor StateMatxDP(29);
CXOR_8_DxD <= StateMatxDP(8) xor DxDI;
CXOR_0_10xD <= StateMatxDP(0) xor StateMatxDP(10);
CXOR_1_12xD <= StateMatxDP(1) xor StateMatxDP(12);
CXOR_2_13xD <= StateMatxDP(2) xor StateMatxDP(13);
CXOR_3_14xD <= StateMatxDP(3) xor StateMatxDP(14);
CXOR_0_4xD <= StateMatxDP(0) xor StateMatxDP(4);
CXOR_1_24xD <= StateMatxDP(1) xor StateMatxDP(24);
CXOR_0_15xD <= StateMatxDP(0) xor StateMatxDP(15);
CXOR_0_16xD <= StateMatxDP(0) xor StateMatxDP(16);
-- purpose: Calculates bit-shifted signals needed for SMIX
-- type : combinational
-- inputs : SBoxedxD, Shift1xD, Shift2xD
-- outputs: Shift1xD, Shift2xD
p_bitshift : process (SBoxedxD, Shift1xD)
begin -- process p_bitshift
for i in 0 to 15 loop
if SBoxedxD(i)(7) = '1' then
Shift1xD(i) <= (SBoxedxD(i)(6 downto 0) & '0') xor X"1b";
else
Shift1xD(i) <= SBoxedxD(i)(6 downto 0) & '0';
end if;
if Shift1xD(i)(7) = '1' then
Shift2xD(i) <= (Shift1xD(i)(6 downto 0) & '0') xor X"1b";
else
Shift2xD(i) <= Shift1xD(i)(6 downto 0) & '0';
end if;
end loop;
end process p_bitshift;
-- Multiply SBoxedxD by seven, using the signals generated above
-- Result is used for SMIX calculation below
multseven : for i in 0 to 15 generate
Mult7xD(i) <= SBoxedxD(i) xor Shift1xD(i) xor Shift2xD(i);
end generate;
-- Apply the SMIX (multiplication by matrix N) to SBoxedxD
-- The result is used by the FSM
-- 1 4 7 1 1 0 0 0 1 0 0 0 1 0 0 0
SMixedxD(0) <= SBoxedxD(0) xor Shift2xD(1) xor Mult7xD(2) xor SBoxedxD(3) xor SBoxedxD(4) xor SBoxedxD(8) xor SBoxedxD(12);
-- 0 1 0 0 1 1 4 7 0 1 0 0 0 1 0 0
SMixedxD(1) <= SBoxedxD(1) xor SBoxedxD(4) xor SBoxedxD(5) xor Shift2xD(6) xor Mult7xD(7) xor SBoxedxD(9) xor SBoxedxD(13);
-- 0 0 1 0 0 0 1 0 7 1 1 4 0 0 1 0
SMixedxD(2) <= SBoxedxD(2) xor SBoxedxD(6) xor Mult7xD(8) xor SBoxedxD(9) xor SBoxedxD(10) xor Shift2xD(11) xor SBoxedxD(14);
-- 0 0 0 1 0 0 0 1 0 0 0 1 4 7 1 1
SMixedxD(3) <= SBoxedxD(3) xor SBoxedxD(7) xor SBoxedxD(11) xor Shift2xD(12) xor Mult7xD(13) xor SBoxedxD(14) xor SBoxedxD(15);
-- 0 0 0 0 0 4 7 1 1 0 0 0 1 0 0 0
SMixedxD(4) <= Shift2xD(5) xor Mult7xD(6) xor SBoxedxD(7) xor SBoxedxD(8) xor SBoxedxD(12);
-- 0 1 0 0 0 0 0 0 1 0 4 7 0 1 0 0
SMixedxD(5) <= SBoxedxD(1) xor SBoxedxD(8) xor Shift2xD(10) xor Mult7xD(11) xor SBoxedxD(13);
-- 0 0 1 0 0 0 1 0 0 0 0 0 7 1 0 4
SMixedxD(6) <= SBoxedxD(2) xor SBoxedxD(6) xor Mult7xD(12) xor SBoxedxD(13) xor Shift2xD(15);
-- 4 7 1 0 0 0 0 1 0 0 0 1 0 0 0 0
SMixedxD(7) <= Shift2xD(0) xor Mult7xD(1) xor SBoxedxD(2) xor SBoxedxD(7) xor SBoxedxD(11);
-- 0 0 0 0 7 0 0 0 6 4 7 1 7 0 0 0
SMixedxD(8) <= Mult7xD(4) xor Shift2xD(8) xor Shift1xD(8) xor Shift2xD(9) xor Mult7xD(10) xor SBoxedxD(11) xor Mult7xD(12);
-- 0 7 0 0 0 0 0 0 0 7 0 0 1 6 4 7
SMixedxD(9) <= Mult7xD(1) xor Mult7xD(9) xor SBoxedxD(12) xor Shift2xD(13) xor Shift1xD(13) xor Shift2xD(14) xor Mult7xD(15);
-- 7 1 6 4 0 0 7 0 0 0 0 0 0 0 7 0
SMixedxD(10) <= Mult7xD(0) xor SBoxedxD(1) xor Shift2xD(2) xor Shift1xD(2) xor Shift2xD(3) xor Mult7xD(6) xor Mult7xD(14);
-- 0 0 0 7 4 7 1 6 0 0 0 7 0 0 0 0
SMixedxD(11) <= Mult7xD(3) xor Shift2xD(4) xor Mult7xD(5) xor SBoxedxD(6) xor Shift2xD(7) xor Shift1xD(7) xor Mult7xD(11);
-- 0 0 0 0 4 0 0 0 4 0 0 0 5 4 7 1
SMixedxD(12) <= Shift2xD(4) xor Shift2xD(8) xor Shift2xD(12) xor SBoxedxD(12) xor Shift2xD(13) xor Mult7xD(14) xor SBoxedxD(15);
-- 1 5 4 7 0 0 0 0 0 4 0 0 0 4 0 0
SMixedxD(13) <= SBoxedxD(0) xor Shift2xD(1) xor SBoxedxD(1) xor Shift2xD(2) xor Mult7xD(3) xor Shift2xD(9) xor Shift2xD(13);
-- 0 0 4 0 7 1 5 4 0 0 0 0 0 0 4 0
SMixedxD(14) <= Shift2xD(2) xor Mult7xD(4) xor SBoxedxD(5) xor Shift2xD(6) xor SBoxedxD(6) xor Shift2xD(7) xor Shift2xD(14);
-- 0 0 0 4 0 0 0 4 4 7 1 5 0 0 0 0
SMixedxD(15) <= Shift2xD(3) xor Shift2xD(7) xor Shift2xD(8) xor Mult7xD(9) xor SBoxedxD(10) xor Shift2xD(11) xor SBoxedxD(11);
sboxi : for i in 3 downto 0 generate -- SBox components added by Patrice
sboxj : for j in 3 downto 0 generate
sbox : subbytes
port map (
ClkxCI => ClkxCI,
RstxRBI => RstxRBI,
DxDI => SMixInxD(i)(8*j+7 downto 8*j),
DxDO => SBoxedxD(i*4+3-j));
end generate sboxj;
end generate sboxi;
-- purpose: Controls the data flow
-- type : combinational
-- inputs : StatexDP, StateMatxDP, CcountxDP, DcountxDP, InputEnxEI, SMixedxD, DxDI and all the CXOR signals
-- outputs: StatexDN, StateMatxDN, CcountxDN, DcountxDN, OutputEnxEO, SMixInxD
p_fsm : process (StatexDP, StateMatxDP, CcountxDP, DcountxDP, InputEnxEI, SMixedxD, DxDI, CXOR_1_12_24xD, CXOR_1_24_27xD, CXOR_1_27xD, CXOR_2_28xD, CXOR_3_29xD, CXOR_8_DxD, CXOR_0_10xD, CXOR_1_12xD, CXOR_2_13xD, CXOR_3_14xD, CXOR_0_4xD, CXOR_1_24xD, CXOR_0_15xD, CXOR_0_16xD)
begin -- process p_fsm
StatexDN <= StatexDP;
StateMatxDN <= StateMatxDP;
CcountxDN <= CcountxDP;
DcountxDN <= DcountxDP;
SMixInxD <= (others => (others => '0'));
OutputEnxEO <= '0';
case to_integer(StatexDP) is
when 0 | 1 | 2 =>
-- (0) see below
SMixInxD(1) <= CXOR_2_28xD;
SMixInxD(2) <= CXOR_3_29xD;
-- (3) see below
-- (4) see below
StateMatxDN(5) <= StateMatxDP(2);
StateMatxDN(6) <= StateMatxDP(3);
StateMatxDN(7) <= StateMatxDP(4);
StateMatxDN(8) <= StateMatxDP(5);
StateMatxDN(9) <= StateMatxDP(6);
StateMatxDN(10) <= StateMatxDP(7);
-- (11) see below
StateMatxDN(12) <= StateMatxDP(9);
-- (13) see below
StateMatxDN(14) <= StateMatxDP(11);
-- (15) see below
StateMatxDN(16) <= CXOR_2_13xD;
StateMatxDN(17) <= CXOR_3_14xD;
StateMatxDN(18) <= StateMatxDP(15);
StateMatxDN(19) <= StateMatxDP(16);
StateMatxDN(20) <= StateMatxDP(17);
StateMatxDN(21) <= StateMatxDP(18);
StateMatxDN(22) <= StateMatxDP(19);
StateMatxDN(23) <= StateMatxDP(20);
StateMatxDN(24) <= StateMatxDP(21);
StateMatxDN(25) <= StateMatxDP(22);
StateMatxDN(26) <= StateMatxDP(23);
StateMatxDN(27) <= StateMatxDP(24);
StateMatxDN(28) <= StateMatxDP(25);
StateMatxDN(29) <= StateMatxDP(26);
DcountxDN <= (others => '0');
-- TODO: write the following code more nicely
-- state 0: only continue to state 1 if InputEn is 1
if to_integer(StatexDP) = 0 then
if InputEnxEI = '0' then
StateMatxDN <= INITSTATE;
else
SMixInxD(0) <= CXOR_1_24_27xD;
SMixInxD(3) <= DxDI;
StateMatxDN(4) <= CXOR_1_24xD;
StateMatxDN(11) <= CXOR_8_DxD;
StateMatxDN(13) <= StateMatxDP(10);
StateMatxDN(15) <= CXOR_1_12_24xD;
StatexDN <= StatexDP+1;
end if;
elsif to_integer(StatexDP) = 1 then
--state 1: apply ROR3/CMIX/SMIX, continue to state 2
CcountxDN <= (others => '0');
SMixInxD(0) <= CXOR_1_27xD;
StateMatxDN(4) <= StateMatxDP(1);
SMixInxD(3) <= StateMatxDP(0);
StateMatxDN(11) <= StateMatxDP(8);
StateMatxDN(13) <= StateMatxDP(10);
StateMatxDN(15) <= CXOR_1_12xD;
StatexDN <= StatexDP+1;
else
-- state 2: start counting final rounds when input ends
if InputEnxEI = '0' then
SMixInxD(0) <= CXOR_1_27xD;
SMixInxD(3) <= StateMatxDP(0);
StateMatxDN(4) <= StateMatxDP(1);
StateMatxDN(11) <= StateMatxDP(8);
StateMatxDN(13) <= StateMatxDP(10);
StateMatxDN(15) <= CXOR_1_12xD;
CcountxDN <= CcountxDP+1;
if CcountxDP = 9 then
StatexDN <= StatexDP+1;
end if;
else
SMixInxD(0) <= CXOR_1_24_27xD;
SMixInxD(3) <= DxDI;
StateMatxDN(4) <= CXOR_1_24xD;
StateMatxDN(11) <= CXOR_8_DxD;
StateMatxDN(13) <= CXOR_0_10xD;
StateMatxDN(15) <= CXOR_1_12_24xD;
StatexDN <= "001";
end if;
end if;
when 3 =>
SMixInxD(0) <= CXOR_0_15xD;
SMixInxD(1) <= StateMatxDP(16);
SMixInxD(2) <= StateMatxDP(17);
SMixInxD(3) <= StateMatxDP(18);
StateMatxDN(4) <= StateMatxDP(19);
StateMatxDN(5) <= StateMatxDP(20);
StateMatxDN(6) <= StateMatxDP(21);
StateMatxDN(7) <= StateMatxDP(22);
StateMatxDN(8) <= StateMatxDP(23);
StateMatxDN(9) <= StateMatxDP(24);
StateMatxDN(10) <= StateMatxDP(25);
StateMatxDN(11) <= StateMatxDP(26);
StateMatxDN(12) <= StateMatxDP(27);
StateMatxDN(13) <= StateMatxDP(28);
StateMatxDN(14) <= StateMatxDP(29);
StateMatxDN(15) <= StateMatxDP(0);
StateMatxDN(16) <= StateMatxDP(1);
StateMatxDN(17) <= StateMatxDP(2);
StateMatxDN(18) <= StateMatxDP(3);
StateMatxDN(19) <= CXOR_0_4xD;
StateMatxDN(20) <= StateMatxDP(5);
StateMatxDN(21) <= StateMatxDP(6);
StateMatxDN(22) <= StateMatxDP(7);
StateMatxDN(23) <= StateMatxDP(8);
StateMatxDN(24) <= StateMatxDP(9);
StateMatxDN(25) <= StateMatxDP(10);
StateMatxDN(26) <= StateMatxDP(11);
StateMatxDN(27) <= StateMatxDP(12);
StateMatxDN(28) <= StateMatxDP(13);
StateMatxDN(29) <= StateMatxDP(14);
StatexDN <= StatexDP+1;
when 4 =>
SMixInxD(0) <= CXOR_0_16xD;
SMixInxD(1) <= StateMatxDP(17);
SMixInxD(2) <= StateMatxDP(18);
SMixInxD(3) <= StateMatxDP(19);
StateMatxDN(4) <= StateMatxDP(20);
StateMatxDN(5) <= StateMatxDP(21);
StateMatxDN(6) <= StateMatxDP(22);
StateMatxDN(7) <= StateMatxDP(23);
StateMatxDN(8) <= StateMatxDP(24);
StateMatxDN(9) <= StateMatxDP(25);
StateMatxDN(10) <= StateMatxDP(26);
StateMatxDN(11) <= StateMatxDP(27);
StateMatxDN(12) <= StateMatxDP(28);
StateMatxDN(13) <= StateMatxDP(29);
StateMatxDN(14) <= StateMatxDP(0);
StateMatxDN(15) <= StateMatxDP(1);
StateMatxDN(16) <= StateMatxDP(2);
StateMatxDN(17) <= StateMatxDP(3);
StateMatxDN(18) <= CXOR_0_4xD;
StateMatxDN(19) <= StateMatxDP(5);
StateMatxDN(20) <= StateMatxDP(6);
StateMatxDN(21) <= StateMatxDP(7);
StateMatxDN(22) <= StateMatxDP(8);
StateMatxDN(23) <= StateMatxDP(9);
StateMatxDN(24) <= StateMatxDP(10);
StateMatxDN(25) <= StateMatxDP(11);
StateMatxDN(26) <= StateMatxDP(12);
StateMatxDN(27) <= StateMatxDP(13);
StateMatxDN(28) <= StateMatxDP(14);
StateMatxDN(29) <= StateMatxDP(15);
DcountxDN <= DcountxDP+1;
if DcountxDP = 12 then
StatexDN <= StatexDP+1;
else
StatexDN <= "011"; --3
end if;
when 5 =>
StateMatxDN <= INITSTATE;
StatexDN <= (others => '0');
OutputEnxEO <= '1';
when others => null;
end case;
--apply SMIX if the matrix is not going to be initialized
--(the following could be written as "if StatexDN /= "000" then" but we
--don't want this process to be sensitive on StatexDN)
if not((StatexDP = "000" and InputEnxEI = '0') or StatexDP = "101") then
for i in 0 to 3 loop
for j in 0 to 3 loop
StateMatxDN(i)(j*8+7 downto j*8) <= std_logic_vector(SMixedxD(4*i+3-j)(7 downto 0));
end loop; -- j
end loop; -- i
end if;
end process p_fsm;
-- Generate the hash from the current state
output : for i in 31 downto 0 generate
HashxDO(i+224) <= StateMatxDP(1)(i);
HashxDO(i+192) <= StateMatxDP(2)(i);
HashxDO(i+160) <= StateMatxDP(3)(i);
HashxDO(i+128) <= CXOR_0_4xD(i);
HashxDO(i+96) <= CXOR_0_15xD(i);
HashxDO(i+64) <= StateMatxDP(16)(i);
HashxDO(i+32) <= StateMatxDP(17)(i);
HashxDO(i) <= StateMatxDP(18)(i);
end generate output;
-- Memory
-----------------------------------------------------------------------------
p_mem : process (ClkxCI, RstxRBI)
begin -- process p_mem
if RstxRBI = '0' then -- asynchronous reset (active low)
StatexDP <= (others => '0');
StateMatxDP <= (others => (others => '0'));
CcountxDP <= (others => '0');
DcountxDP <= (others => '0');
elsif ClkxCI'event and ClkxCI = '1' then -- rising clock edge
StatexDP <= StatexDN;
StateMatxDP <= StateMatxDN;
CcountxDP <= CcountxDN;
DcountxDP <= DcountxDN;
end if;
end process p_mem;
end rtl;