------------------------------------------------------------ -- Copyright: 2011 Integrated Sytems Laboratory, ETH Zurich -- http://www.iis.ee.ethz.ch/~sha3 ------------------------------------------------------------ ------------------------------------------------------------------------------- -- Title : Skein for ETHZ -- Project : Shabziger ------------------------------------------------------------------------------- -- File : ethz_skein.vhd -- Author : Chrikell -- Company : Integrated Systems Laboratory, ETH Zurich -- Created : 2011-08-25 -- Last update: 2011-09-01 -- Platform : ModelSim (simulation), Synopsys (synthesis) -- Standard : VHDL'87 ------------------------------------------------------------------------------- -- Description: ------------------------------------------------------------------------------- -- Copyright (c) 2011 Integrated Systems Laboratory, ETH Zurich ------------------------------------------------------------------------------- -- Revisions : -- Date Version Author Description -- 2011-08-25 1.0 Chrikell ------------------------------------------------------------------------------- library ieee; use ieee.numeric_std.all; use ieee.std_logic_1164.all; use work.skeinpkg.all; entity ethz_skein is port ( ClkxCI : in std_logic; RstxRBI : in std_logic; FinBlockxSI : in std_logic; InWrEnxSI : in std_logic; OutWrEnxSO : out std_logic; PenUltCyclexSO : out std_logic; BlockxDI : in std_logic_vector(511 downto 0); MsgLenxDI : in std_logic_vector(63 downto 0); -- size of current Block, in Bytes. Only used if FinBlockxSI = '1' HashxDO : out std_logic_vector(255 downto 0); ScanInxTI : in std_logic; ScanEnxTI : in std_logic; ScanOutxTO : out std_logic ); end ethz_skein; architecture rtl of ethz_skein is type Tweak is array (0 to 2) of std_logic_vector(63 downto 0); type FSMState is (idle, first, run, final); signal StatexDP, StatexDN, StateTmpxD : HashState; signal TmpStatexDP, TmpStatexDN : HashUnsigned; signal MsgBlkxDN, MsgBlkxDP : HashState; signal KeyxDP, KeyxDN : Key; signal TweakxDN, TweakxDP : Tweak; signal ByteCntxDN, ByteCntxDP : unsigned(63 downto 0); signal RoundxSP, RoundxSN, RoundxSPP : unsigned(6 downto 0); signal FSMStatexDP, FSMStatexDN : FSMState; signal WaitxSN, WaitxSP : std_logic; signal KeyUpdxSN, KeyUpdxSP : std_logic; signal FinBlockxSN, FinBlockxSP : std_logic; signal KeyAddxSN, KeyAddxSP : std_logic; signal OutWrEnxSN, OutWrEnxSP : std_logic; signal FrstBlkxS : std_logic; signal FrstBlkxSP, FrstBlkxSN : std_logic; signal FinalizexS : std_logic; signal Debug : integer; begin -- rtl ----------------------------------------------------------------------------- -- FSM ----------------------------------------------------------------------------- FSM : process (BlockxDI, ByteCntxDP, FSMStatexDP, FinBlockxSI, FinBlockxSP, FrstBlkxSP, InWrEnxSI, KeyAddxSP, KeyUpdxSP, MsgBlkxDP, MsgLenxDI, OutWrEnxSP, RoundxSP, WaitxSP) begin -- process FSM FSMStatexDN <= FSMStatexDP; MsgBlkxDN <= MsgBlkxDP; RoundxSN <= RoundxSP; FrstBlkxS <= '0'; FinBlockxSN <= FinBlockxSP; KeyUpdxSN <= '0'; WaitxSN <= '0'; KeyAddxSN <= '0'; PenUltCyclexSO <= '0'; OutWrEnxSN <= '0'; OutWrEnxSO <= OutWrEnxSP; FinalizexS <= '0'; ByteCntxDN <= ByteCntxDP; FrstBlkxSN <= '0'; case FSMStatexDP is ------------------------------------------------------------------------- -- idle ------------------------------------------------------------------------- when idle => WaitxSN <= '1'; if InWrEnxSI = '1' then for i in 0 to 7 loop for j in 0 to 7 loop MsgBlkxDN(7-j)((8*(i+1)-1) downto (8*i)) <= BlockxDI((j*64)+(8*(8-i)-1) downto (j*64)+(8*(7-i))); end loop; --i end loop; -- i KeyUpdxSN <= '1'; FSMStatexDN <= first; FinBlockxSN <= FinBlockxSI; KeyAddxSN <= '1'; WaitxSN <= '0'; ByteCntxDN <= unsigned(MsgLenxDI); end if; RoundxSN <= (others => '0'); ------------------------------------------------------------------------- -- first ------------------------------------------------------------------------- when first => FrstBlkxS <= '1'; if RoundxSP(1 downto 0) = "10" then KeyUpdxSN <= '1'; end if; if KeyAddxSP = '0' then RoundxSN <= RoundxSP +1; if RoundxSP(1 downto 0) = "11" then KeyAddxSN <= '1'; end if; end if; if RoundxSP = 71 and FinBlockxSP = '0' then PenUltCyclexSO <= '1'; end if; if RoundxSP = 72 then if FinBlockxSP = '1' then FSMStatexDN <= final; RoundxSN <= (others => '0'); KeyUpdxSN <= '1'; WaitxSN <= '1'; MsgBlkxDN <= (others => (others => '0')); FrstBlkxSN <= '1'; elsif InWrEnxSI = '1' then FSMStatexDN <= run; RoundxSN <= (others => '0'); KeyUpdxSN <= '1'; WaitxSN <= '1'; FinBlockxSN <= FinBlockxSI; for i in 0 to 7 loop for j in 0 to 7 loop MsgBlkxDN(7-j)((8*(i+1)-1) downto (8*i)) <= BlockxDI((j*64)+(8*(8-i)-1) downto (j*64)+(8*(7-i))); end loop; --i end loop; -- i ByteCntxDN <= unsigned(MsgLenxDI); else RoundxSN <= RoundxSP; WaitxSN <= '1'; end if; end if; ------------------------------------------------------------------------- -- run ------------------------------------------------------------------------- when run => if RoundxSP = 0 and KeyUpdxSP = '1' then KeyAddxSN <= '1'; end if; if RoundxSP(1 downto 0) = "10" then KeyUpdxSN <= '1'; end if; if KeyAddxSP = '0' and WaitxSP = '0' then RoundxSN <= RoundxSP +1; if RoundxSP(1 downto 0) = "11" then KeyAddxSN <= '1'; end if; end if; if RoundxSP = 71 and FinBlockxSP = '0' then PenUltCyclexSO <= '1'; end if; if RoundxSP = 72 then if FinBlockxSP = '1' then FSMStatexDN <= final; RoundxSN <= (others => '0'); KeyUpdxSN <= '1'; WaitxSN <= '1'; MsgBlkxDN <= (others => (others => '0')); FrstBlkxSN <= '1'; elsif InWrEnxSI = '1' then FSMStatexDN <= run; RoundxSN <= (others => '0'); KeyUpdxSN <= '1'; WaitxSN <= '1'; FinBlockxSN <= FinBlockxSI; for i in 0 to 7 loop for j in 0 to 7 loop MsgBlkxDN(7-j)((8*(i+1)-1) downto (8*i)) <= BlockxDI((j*64)+(8*(8-i)-1) downto (j*64)+(8*(7-i))); end loop; --i end loop; -- i ByteCntxDN <= unsigned(MsgLenxDI); else RoundxSN <= RoundxSP; WaitxSN <= '1'; end if; end if; ------------------------------------------------------------------------- -- Final ------------------------------------------------------------------------- when final => FrstBlkxSN <= FrstBlkxSP; FinalizexS <= '1'; if RoundxSP = 0 and KeyUpdxSP = '1' then KeyAddxSN <= '1'; end if; if RoundxSP(1 downto 0) = "10" then KeyUpdxSN <= '1'; end if; if KeyAddxSP = '0' and WaitxSP = '0'then RoundxSN <= RoundxSP +1; if RoundxSP(1 downto 0) = "11" then KeyAddxSN <= '1'; end if; end if; if RoundxSP = 71 then PenUltCyclexSO <= '1'; end if; if RoundxSP = 72 then OutWrEnxSN <= '1'; if InWrEnxSI = '1' then for i in 0 to 7 loop for j in 0 to 7 loop MsgBlkxDN(7-j)((8*(i+1)-1) downto (8*i)) <= BlockxDI((j*64)+(8*(8-i)-1) downto (j*64)+(8*(7-i))); end loop; --i end loop; -- i KeyUpdxSN <= '1'; FSMStatexDN <= first; FinBlockxSN <= FinBlockxSI; KeyAddxSN <= '1'; WaitxSN <= '0'; RoundxSN <= (others => '0'); ByteCntxDN <= unsigned(MsgLenxDI); else FSMStatexDN <= idle; WaitxSN <= '1'; end if; end if; when others => null; end case; end process FSM; ----------------------------------------------------------------------------- -- Key Management ----------------------------------------------------------------------------- KeyMan : process (ByteCntxDP, FinBlockxSP, FinalizexS, FrstBlkxS, FrstBlkxSP, KeyUpdxSP, KeyxDN, KeyxDP, MsgBlkxDP, RoundxSP, StatexDP, TweakxDN, TweakxDP) begin -- process KeyMan TweakxDN <= TweakxDP; KeyxDN <= KeyxDP; if KeyUpdxSP = '1' then if RoundxSP = 0 or RoundxSP = 72 then if FrstBlkxS = '1' then for i in 0 to 7 loop KeyxDN(i) <= IV(i); end loop; -- i else for i in 0 to 7 loop KeyxDN(i) <= StatexDP(i); end loop; -- i end if; -- FrstBlkxS KeyxDN(8) <= C240 xor KeyxDN(0) xor KeyxDN(1) xor KeyxDN(2) xor KeyxDN(3) xor KeyxDN(4) xor KeyxDN(5) xor KeyxDN(6) xor KeyxDN(7); if FinalizexS = '0' then TweakxDN(1) <= FinBlockxSP & FrstBlkxS & "110000" &X"00000000000000"; TweakxDN(0) <= std_logic_vector(ByteCntxDP); else TweakxDN(1) <= FinBlockxSP & FrstBlkxSP & "111111" &X"00000000000000"; TweakxDN(0) <= X"000000000000000" & "1000"; end if; TweakxDN(2) <= TweakxDN(0) xor TweakxDN(1); else TweakxDN(0) <= TweakxDP(1); TweakxDN(1) <= TweakxDP(2); TweakxDN(2) <= TweakxDP(0); KeyxDN(0) <= KeyxDP(1); KeyxDN(1) <= KeyxDP(2); KeyxDN(2) <= KeyxDP(3); KeyxDN(3) <= KeyxDP(4); KeyxDN(4) <= KeyxDP(5); KeyxDN(5) <= KeyxDP(6); KeyxDN(6) <= KeyxDP(7); KeyxDN(7) <= KeyxDP(8); KeyxDN(8) <= KeyxDP(0); end if; --FrstRndxS end if; for i in 0 to 7 loop if RoundxSP = 0 then if i = 5 then StateTmpxD(i) <= std_logic_vector(unsigned(MsgBlkxDP(i)) + unsigned(KeyxDN(i))+unsigned(TweakxDN(0))); elsif i = 6 then StateTmpxD(i) <= std_logic_vector(unsigned(MsgBlkxDP(i)) + unsigned(KeyxDN(i))+unsigned(TweakxDN(1))); elsif i = 7 then StateTmpxD(i) <= std_logic_vector(unsigned(MsgBlkxDP(i)) + unsigned(KeyxDN(i))+RoundxSP(6 downto 2)); else StateTmpxD(i) <= std_logic_vector(unsigned(MsgBlkxDP(i)) + unsigned(KeyxDN(i))); end if; elsif RoundxSP < 72 then if i = 5 then StateTmpxD(i) <= std_logic_vector(unsigned(StatexDP(i)) + unsigned(KeyxDN(i))+unsigned(TweakxDN(0))); elsif i = 6 then StateTmpxD(i) <= std_logic_vector(unsigned(StatexDP(i)) + unsigned(KeyxDN(i))+unsigned(TweakxDN(1))); elsif i = 7 then StateTmpxD(i) <= std_logic_vector(unsigned(StatexDP(i)) + unsigned(KeyxDN(i))+RoundxSP(6 downto 2)); else StateTmpxD(i) <= std_logic_vector(unsigned(StatexDP(i)) + unsigned(KeyxDN(i))); end if; else if i = 5 then StateTmpxD(i) <= std_logic_vector((unsigned(StatexDP(i)) + unsigned(KeyxDN(i))+unsigned(TweakxDN(0))) xor unsigned(MsgBlkxDP(i))); elsif i = 6 then StateTmpxD(i) <= std_logic_vector((unsigned(StatexDP(i)) + unsigned(KeyxDN(i))+unsigned(TweakxDN(1))) xor unsigned(MsgBlkxDP(i))); elsif i = 7 then StateTmpxD(i) <= std_logic_vector((unsigned(StatexDP(i)) + unsigned(KeyxDN(i))+RoundxSP(6 downto 2)) xor unsigned(MsgBlkxDP(i))); else StateTmpxD(i) <= std_logic_vector((unsigned(StatexDP(i)) + unsigned(KeyxDN(i))) xor unsigned(MsgBlkxDP(i))); end if; end if; end loop; -- i end process KeyMan; ----------------------------------------------------------------------------- -- MixRound ----------------------------------------------------------------------------- Mixround : process (KeyAddxSP, MsgBlkxDP, RoundxSP, StateTmpxD, StatexDP, TmpStatexDN, TmpStatexDP, WaitxSP) begin -- process MixRound Debug <= 0; if WaitxSP = '0' then if KeyAddxSP = '0' then if RoundxSP < 72 then TmpStatexDN(6) <= TmpStatexDP(0)+ TmpStatexDP(1); TmpStatexDN(1) <= (TmpStatexDP(1) rol RotxS(to_integer(RoundxSP(2 downto 0)))(0)) xor TmpStatexDN(6); TmpStatexDN(0) <= TmpStatexDP(2)+ TmpStatexDP(3); TmpStatexDN(7) <= (TmpStatexDP(3) rol RotxS(to_integer(RoundxSP(2 downto 0)))(1)) xor TmpStatexDN(0); TmpStatexDN(2) <= TmpStatexDP(4)+ TmpStatexDP(5); TmpStatexDN(5) <= (TmpStatexDP(5) rol RotxS(to_integer(RoundxSP(2 downto 0)))(2)) xor TmpStatexDN(2); Debug <= RotxS(to_integer(RoundxSP(2 downto 0)))(2); TmpStatexDN(4) <= TmpStatexDP(6)+ TmpStatexDP(7); TmpStatexDN(3) <= (TmpStatexDP(7) rol RotxS(to_integer(RoundxSP(2 downto 0)))(3)) xor TmpStatexDN(4); else for i in 0 to 7 loop TmpStatexDN(i) <= unsigned(StateTmpxD(i)) xor unsigned(MsgBlkxDP(i)); end loop; -- i end if; -- round < 72 else for i in 0 to 7 loop TmpStatexDN(i) <= unsigned(StateTmpxD(i)); end loop; -- i end if; --keyadd else TmpStatexDN <= TmpStatexDP; end if; -- wait for i in 0 to 7 loop TmpStatexDP(i) <= unsigned(StatexDP(i)); StatexDN(i) <= std_logic_vector(TmpStatexDN(i)); end loop; -- i end process Mixround; ----------------------------------------------------------------------------- -- Output Process ----------------------------------------------------------------------------- Output : process (StatexDP) begin -- process Output for i in 0 to 7 loop for j in 0 to 3 loop HashxDO((j*64)+(8*(i+1)-1) downto (j*64)+(8*i)) <= StatexDP(3-j)((8*(8-i)-1) downto (8*(7-i))); end loop; --i end loop; -- i end process Output; ----------------------------------------------------------------------------- -- register ----------------------------------------------------------------------------- P_Reg : process (ClkxCI, RstxRBI) begin -- process Register if RstxRBI = '0' then -- asynchronous reset (active low) FSMStatexDP <= idle; StatexDP <= (others => (others => '0')); MsgBlkxDP <= (others => (others => '0')); KeyxDP <= (others => (others => '0')); TweakxDP <= (others => (others => '0')); ByteCntxDP <= (others => '0'); RoundxSP <= (others => '0'); RoundxSPP <= (others => '0'); WaitxSP <= '0'; KeyUpdxSP <= '0'; FinBlockxSP <= '0'; KeyAddxSP <= '0'; OutWrEnxSP <= '0'; FrstBlkxSP <= '0'; elsif ClkxCI'event and ClkxCI = '1' then -- rising clock edge FSMStatexDP <= FSMStatexDN; StatexDP <= StatexDN; MsgBlkxDP <= MsgBlkxDN; KeyxDP <= KeyxDN; TweakxDP <= TweakxDN; ByteCntxDP <= ByteCntxDN; RoundxSP <= RoundxSN; RoundxSPP <= RoundxSP; WaitxSP <= WaitxSN; KeyUpdxSP <= KeyUpdxSN; FinBlockxSP <= FinBlockxSN; KeyAddxSP <= KeyAddxSN; OutWrEnxSP <= OutWrEnxSN; FrstBlkxSP <= FrstBlkxSN; end if; end process P_Reg; end rtl;