------------------------------------------------------------ -- Copyright: 2011 George Mason University, Virginia USA -- http://www.iis.ee.ethz.ch/~sha3 ------------------------------------------------------------ -- ===================================================================== -- Copyright © 2010-2011 by Cryptographic Engineering Research Group (CERG), -- ECE Department, George Mason University -- Fairfax, VA, U.S.A. -- ===================================================================== library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use work.sha3_skein_package.ALL; use work.sha3_pkg.all; entity gmu_skein_datapath is generic ( version : integer := SHA3_ROUND3; adder_type : integer := SCCA_BASED; h : integer := HASH_SIZE_256 ); port ( -- external clk : in std_logic; rst : in std_logic; din : in std_logic_vector(511 downto 0); dout : out std_logic_vector(h-1 downto 0); tw_position64 : in std_logic_vector(63 downto 0); -- control signals er : in std_logic; sf : in std_logic; -- 1 for first block of a message sfinal : in std_logic; -- 0 for msg, 1 for output slast : in std_logic; -- 1 for last block and output , 0 else snb : in std_logic ); end gmu_skein_datapath; architecture struct of gmu_skein_datapath is ------ Constants constant nw : integer := 8; -- fixed constant b : integer := 512; -- fixed constant bzeros : std_logic_vector(b-1 downto 0) := (others => '0'); constant mw : integer := b; -- message width constant log2mw : integer := log2(mw); constant log2mwzeros : std_logic_vector(log2mw-1 downto 0) := (others => '0'); constant mwzeros : std_logic_vector(mw-1 downto 0) := (others => '0'); constant perm : permute_type (0 to nw-1) := get_perm( b ); constant rot : rot_type (0 to nw/2-1,0 to 7) := get_rot( b ); constant iv : std_logic_vector(b-1 downto 0) := get_iv( h, version ); constant sixteenzeros : std_logic_vector(15 downto 0) := (others => '0'); constant seventyone0 : std_logic_vector(70 downto 0) := (others =>'0'); constant remzeros : std_logic_vector(log2mw-4 downto 0) := (others => '0'); constant remones : std_logic_vector(log2mw-4 downto 0) := (others => '1'); ---------- -- TWEAK signal tweak : std_logic_vector(127 downto 0); constant tw_tree_level : std_logic_vector(6 downto 0) := (others =>'0'); constant tw_reserved : std_logic_vector(15 downto 0) := (others =>'0'); constant tw_bit_pad : std_logic := '0'; -- bit pad always '0' as message will be multiple of a byte constant zeros : std_logic_vector(31 downto 0) := (others => '0'); -- fill the rest of tweak's position signal tw_type : std_logic_vector(5 downto 0); signal tw_final, tw_first : std_logic; signal tw_position : std_logic_vector(63 downto 0); -- ROUND SIGNALS signal min,min_endian1,min_endian2, msg : std_logic_vector(mw-1 downto 0); signal r, rmux, rp : std_logic_vector(b-1 downto 0); signal threefish, cv, keyin : std_logic_vector(b-1 downto 0); signal switch_out, switch1, switch2 : std_logic_vector(h-1 downto 0); signal keyout : key_array(nw-1 downto 0); signal keyinj : key_array(nw-1 downto 0); signal round : round_array(0 to 4, nw-1 downto 0); signal roundout : round_array(0 to 3, nw-1 downto 0); -- 4x signal sshalf : std_logic; begin tw_type <= TW_OUT_CONS when sfinal = '1' else TW_MSG_CONS; tw_final <= (slast or sfinal); tw_first <= (sf or sfinal); tw_position <= conv_std_logic_vector(8,64) when sfinal = '1' else tw_position64; -- tweak tweak <= tw_final & tw_first & tw_type & tw_bit_pad & tw_tree_level & tw_reserved & zeros & tw_position; -- input min_endian1 <= switch_endian_byte(din,b,64); min_endian2 <= switch_endian_word(min_endian1,b,64); msgRegGen : process( rst, clk ) begin if ( rst = '0' ) then msg <= (others => '0'); elsif rising_edge( clk ) then if ( sfinal = '1' ) then msg <= (others => '0'); elsif ( snb = '1' ) then msg <= min_endian2; end if; end if; end process; rmux <= min_endian2 when snb = '1' else rp; r_reg : process( rst, clk ) begin if ( rst = '0' ) then r <= (others => '0'); elsif rising_edge( clk ) then if ( sfinal = '1' ) then r <= (others => '0'); elsif ( er = '1' ) then r <= rmux; end if; end if; end process; ----------------------- --------- ROUND ------- inout_gen : for i in nw-1 downto 0 generate round(0,i) <= r(iw*(i+1)-1 downto iw*i); rp(iw*(i+1)-1 downto iw*i) <= round(4,i); end generate; -- cntrl signal process ( clk ) begin if rising_edge( clk ) then if ( snb = '1' ) then sshalf <= '0'; elsif ( er = '1' ) then sshalf <= not sshalf; end if; end if; end process; -- core row_gen : for i in 0 to 3 generate key_inj : if ( i mod 4 = 0 ) generate keyinj_gen : for j in nw-1 downto 0 generate add_call : adder generic map ( adder_type => adder_type, n => 64 ) port map ( a => keyout(j), b => round(i,j) , s => keyinj(j)); end generate; mix_gen_gen : for j in 0 to nw/2-1 generate mix_gen : entity work.skein_mix_4r(struct) generic map ( adder_type => adder_type, rotate_0 => rot(j,i), rotate_1 => rot(j,i+4) ) port map ( sel => sshalf, a => keyinj(2*j), b => keyinj(2*j+1), c => roundout(i,2*j), d => roundout(i,2*j+1) ); end generate; end generate; nokey_inj : if (i mod 4 /= 0 ) generate mix_gen_gen : for j in 0 to nw/2-1 generate mix_gen_r : entity work.skein_mix_4r(struct) generic map (adder_type => adder_type, rotate_0 => rot(j,i), rotate_1 => rot(j,i+4) ) port map ( sel => sshalf, a => round(i,2*j), b => round(i,2*j+1), c => roundout(i,2*j), d => roundout(i,2*j+1) ); end generate; end generate; end generate; perm1: for i in 1 to 4 generate perm2 : for j in 0 to nw-1 generate round(i,j) <= roundout(i-1,perm(j)); end generate; end generate; --------- ROUND ------- ----------------------- threefish_out_gen : for i in nw-1 downto 0 generate threefish(64*(i+1)-1 downto 64*i) <= keyinj(i); end generate; cv <= threefish xor msg; keyin <= iv when sf = '1' else cv; keygen_gen : entity work.skein_keygen(struct) generic map (version => version, adder_type => adder_type, b => b, nw => nw) port map ( clk => clk, rst => rst, load => snb, en => er, keyin => keyin, tweak => tweak, keyout => keyout ); switch_out <= cv(h-1 downto 0); switch1 <= switch_endian_word(switch_out, h, iw); switch2 <= switch_endian_byte(switch1,h,iw); dout <= switch2; end struct;