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