------------------------------------------------------------ -- Copyright: 2010 Integrated Sytems Laboratory, ETH Zurich -- http://www.iis.ee.ethz.ch/~sha3 ------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.shabalPkg.all; entity perm is port ( ClkxCI : in std_logic; RstxRBI : in std_logic; NewBlockxSI : in std_logic; StartxSI : in std_logic; MxDI : in std_logic_vector(WWIDTH*16-1 downto 0); 1 downto 0); -- hash output -- (Shabal-256:8, Shabal-512:16) ValidOutxSO : out std_logic ); end perm; architecture rtl of perm is component controller port ( ClkxCI : in std_logic; RstxRBI : in std_logic; NewBlockxSI : in std_logic; StatexDO : out std_logic_vector(1 downto 0); CntxDO : out unsigned(1 downto 0); LastxSO : out std_logic; ValidOutxSO : out std_logic); end component; signal AxDN, AxDP : blockA; signal MxDN, MxDP, BxDN, BxDP, CxDN, CxDP : blockB; signal WxDN, WxDP : blockW; signal StatexD : std_logic_vector(1 downto 0); signal CntxD : unsigned(1 downto 0); signal LastxS : std_logic; begin -- rtl u_controller : controller port map ( ClkxCI => ClkxCI, RstxRBI => RstxRBI, NewBlockxSI => NewBlockxSI, StatexDO => StatexD, CntxDO => CntxD, LastxSO => LastxS, ValidOutxSO => ValidOutxSO); p_update : process (AxDP, BxDP, CntxD, CxDP, LastxS, MxDI, MxDP, NewBlockxSI, StartxSI, StatexD, WxDP) variable Aperm, Wnew0, Wnew1, Anew0, Anew1 : std_logic_vector(31 downto 0); variable Marray, Bnew : blockB; begin -- process p_update AxDN <= AxDP; BxDN <= BxDP; CxDN <= CxDP; MxDN <= MxDP; WxDN <= WxDP; case StatexD is when "11" => -- initialize M for i in 0 to 15 loop Marray(i) := MxDI((16-i)*WWIDTH-1 downto (15-i)*WWIDTH); end loop; -- i if NewBlockxSI = '1' then MxDN <= Marray; end if; if StartxSI = '1' then -- initialize last 10 words of A AxDN(2 to 11) <= Ainit(2 to 11); Anew0 := Ainit(0); Anew1 := Ainit(1); Bnew := Binit; -- initialize C CxDN <= Cinit; Wnew0 := x"00000001"; Wnew1 := (others => '0'); else Anew0 := AxDP(0); Anew1 := AxDP(1); Bnew := BxDP; -- increment W unless the final block is processed if NewBlockxSI = '0' then Wnew0 := WxDP(0); Wnew1 := WxDP(1); else Wnew0 := std_logic_vector(unsigned(WxDP(0)) + 1); Wnew1 := WxDP(1); if Wnew0 = x"00000000" then Wnew1 := std_logic_vector(unsigned(WxDP(1)) + 1); end if; end if; end if; -- update/initialize W and first 2 words of A WxDN(0) <= Wnew0; WxDN(1) <= Wnew1; AxDN(0) <= Anew0 xor Wnew0; AxDN(1) <= Anew1 xor Wnew1; -- initialize B, add input block and rotate for i in 0 to 15 loop if LastxS = '0' then BxDN(i) <= Rotl(std_logic_vector(unsigned(Bnew(i)) + unsigned(Marray(i))),17); else BxDN(i) <= Rotl(std_logic_vector(unsigned(Bnew(i)) + unsigned(MxDP(i))),17); end if; end loop; ------------------------------------------------------------------------- when "01" => for i in 0 to 10 loop AxDN(i) <= AxDP(i+1); end loop; -- i Aperm := Ufun(AxDP(0) xor Vfun(Rotl(AxDP(11),15)) xor CxDP(8)) xor BxDP(o1) xor (BxDP(o2) and not(BxDP(o3))) xor MxDP(0); AxDN(11) <= Aperm; -- A(i+16*j mod r) computation -- for i in 0 to 15 loop -- CxDN(i) CxDP(i-1 mod 16); -- MxDN(i) MxDP(i+1 mod 16); -- end loop; -- i for i in 1 to 15 loop CxDN(i) <= CxDP(i-1); end loop; -- i CxDN(0) <= CxDP(15); for i in 0 to 14 loop MxDN(i) <= MxDP(i+1); end loop; -- i MxDN(15) <= MxDP(0); for i in 0 to 14 loop BxDN(i) <= BxDP(i+1); end loop; -- i BxDN(15) <= Rotl(BxDP(0),1) xor not(Aperm); ------------------------------------------------------------------------- when "10" => for i in 0 to 11 loop AxDN(i) <= std_logic_vector(unsigned(AxDP(i)) + unsigned(CxDP(APCMATRIX(to_integer(CntxD),i)))); end loop; -- i -- after finishing the permutation, subtract the message block from C -- and swap B and C if CntxD = 2 then for i in 0 to 15 loop BxDN(i) <= std_logic_vector(unsigned(CxDP(i)) - unsigned(MxDP(i))); CxDN(i) <= BxDP(i); end loop; -- i end if; ------------------------------------------------------------------------- when others => null; end case; end process p_update; ----------------------------------------------------------------------------- -- OUTPUT ----------------------------------------------------------------------------- -- HashxDO(16*WWIDTH-1 downto 15*WWIDTH) CxDP(0); -- HashxDO(15*WWIDTH-1 downto 14*WWIDTH) CxDP(1); -- HashxDO(14*WWIDTH-1 downto 13*WWIDTH) CxDP(2); -- HashxDO(13*WWIDTH-1 downto 12*WWIDTH) CxDP(3); -- HashxDO(12*WWIDTH-1 downto 11*WWIDTH) CxDP(4); -- HashxDO(11*WWIDTH-1 downto 10*WWIDTH) CxDP(5); -- HashxDO(10*WWIDTH-1 downto 9*WWIDTH) CxDP(6); -- HashxDO(9*WWIDTH-1 downto 8*WWIDTH) CxDP(7); -- Shabal-256 output: HashxDO(8*WWIDTH-1 downto 7*WWIDTH) <= CxDP(8); HashxDO(7*WWIDTH-1 downto 6*WWIDTH) <= CxDP(9); HashxDO(6*WWIDTH-1 downto 5*WWIDTH) <= CxDP(10); HashxDO(5*WWIDTH-1 downto 4*WWIDTH) <= CxDP(11); HashxDO(4*WWIDTH-1 downto 3*WWIDTH) <= CxDP(12); HashxDO(3*WWIDTH-1 downto 2*WWIDTH) <= CxDP(13); HashxDO(2*WWIDTH-1 downto WWIDTH) <= CxDP(14); HashxDO(WWIDTH-1 downto 0) <= CxDP(15); ----------------------------------------------------------------------------- -- MEMORY ----------------------------------------------------------------------------- p_mem: process (ClkxCI, RstxRBI) begin -- process p_mem if RstxRBI = '0' then -- asynchronous reset (active low) AxDP <= (others => (others => '0')); BxDP <= (others => (others => '0')); CxDP <= (others => (others => '0')); WxDP <= (others => (others => '0')); MxDP <= (others => (others => '0')); elsif ClkxCI'event and ClkxCI = '1' then -- rising clock edge AxDP <= AxDN; BxDP <= BxDN; CxDP <= CxDN; WxDP <= WxDN; MxDP <= MxDN; end if; end process p_mem; end rtl;