------------------------------------------------------------ -- 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;