------------------------------------------------------------ -- 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; package sha3_pkg is -- different versions of SHA3 candidates constant SHA3_ROUND1 :integer:= 1; constant SHA3_ROUND2 :integer:= 2; constant SHA3_ROUND3 :integer:= 3; -- hash output size constant HASH_SIZE_224 :integer:=224; constant HASH_SIZE_256 :integer:=256; constant HASH_SIZE_384 :integer:=384; constant HASH_SIZE_512 :integer:=512; -- adder constants constant SCCA_BASED : integer := 0; constant SCCA_TREE_BASED : integer := 1; constant CSA_BASED : integer := 2; constant PC_BASED : integer := 3; constant CSA_CPA_BASED : integer := 4; constant CLA_BASED : integer := 5; constant FCCA_BASED : integer := 6; constant FCCA_TREE_BASED : integer := 7; constant DSP_BASED : integer := 8; constant YES : integer := 1; constant NO : integer := 0; -- family constants constant SPARTAN3 : integer := 0; constant VIRTEX4 : integer := 1; constant VIRTEX5 : integer := 2; -- fifo mode constants constant ZERO_WAIT_STATE : integer:=0; constant ONE_WAIT_STATE : integer:=1; constant ZERO_WAIT_STATE_PREFETCH : integer:=2; -- implementation constants constant DISTRIBUTED : integer:=0; constant BRAM : integer:=1; constant COMBINATIONAL : integer:=2; -- counter constants constant COUNTER_STYLE_1 : integer:=1; constant COUNTER_STYLE_2 : integer:=2; constant COUNTER_STYLE_3 : integer:=3; -- logic constants constant GND : std_logic := '0'; constant VCC : std_logic := '1'; -- aes constants constant AES_SBOX_SIZE :integer:=8; constant AES_WORD_SIZE :integer:=32; constant AES_BLOCK_SIZE :integer:=128; constant AES_KEY_SIZE :integer:=128; constant AES_ROUND_BASIC :integer:=1; constant AES_ROUND_TBOX :integer:=2; type rom_pad64bit_type is array (0 to 7) of std_logic_vector(7 downto 0); constant lookup_sel_lvl2_64bit_pad : rom_pad64bit_type := ( "10000000", "01000000", "00100000", "00010000", "00001000", "00000100", "00000010", "00000001"); constant lookup_sel_lvl1_64bit_pad : rom_pad64bit_type := ( "00000000", "10000000", "11000000", "11100000", "11110000", "11111000", "11111100", "11111110"); type rom_pad32bit_type is array (0 to 3) of std_logic_vector(3 downto 0); constant lookup_sel_lvl2_32bit_pad : rom_pad32bit_type := ("1000", "0100", "0010", "0001"); constant lookup_sel_lvl1_32bit_pad : rom_pad32bit_type := ("0000", "1000", "1100", "1110"); -- basic shifting and rotating functions function shrx ( x : std_logic_vector; y : integer) return std_logic_vector; function shlx ( x : std_logic_vector; y : integer) return std_logic_vector; function rorx ( x : std_logic_vector; y : integer) return std_logic_vector; function rolx ( x : std_logic_vector; y : integer) return std_logic_vector; -- log based 2 function log2 (N: natural) return natural; -- switching endianess functions -- Note : Names changed for clarity -- switch_endian --> switch_endian_word -- switch_endian_word --> switch_endian_byte function switch_endian_byte ( x : std_logic_vector; width : integer; w : integer ) return std_logic_vector; function switch_endian_word ( x : std_logic_vector; width : integer; w : integer ) return std_logic_vector; -- galois field multiplication functions for AES sbox combinational function function GF_SQ_SCL_2 ( x : in STD_LOGIC_VECTOR (1 downto 0)) return STD_LOGIC_VECTOR; function GF_SCL_2 ( x : in STD_LOGIC_VECTOR (1 downto 0)) return STD_LOGIC_VECTOR; function GF_MUL_2 ( x,y : in STD_LOGIC_VECTOR (1 downto 0)) return STD_LOGIC_VECTOR; function GF_MUL_SCL_2 ( x,y : in STD_LOGIC_VECTOR (1 downto 0))return STD_LOGIC_VECTOR; function GF_INV_2 ( x : in STD_LOGIC_VECTOR (1 downto 0)) return STD_LOGIC_VECTOR; function GF_SQ_2 ( x : in STD_LOGIC_VECTOR (1 downto 0)) return STD_LOGIC_VECTOR; function MUL_X ( x : in STD_LOGIC_VECTOR (7 downto 0)) return STD_LOGIC_VECTOR; function MUL_MX ( x : in STD_LOGIC_VECTOR (7 downto 0)) return STD_LOGIC_VECTOR; function GF_INV_4 ( x : in STD_LOGIC_VECTOR (3 downto 0))return STD_LOGIC_VECTOR; function GF_MUL_4 ( x, y : in STD_LOGIC_VECTOR (3 downto 0))return STD_LOGIC_VECTOR; function GF_SQ_SCL_4 ( x : in STD_LOGIC_VECTOR (3 downto 0))return STD_LOGIC_VECTOR; function GF_INV_8 ( x : in STD_LOGIC_VECTOR (7 downto 0))return STD_LOGIC_VECTOR; -- components declaration component csa is generic (n :integer := 32); port ( a : in std_logic_vector(n-1 downto 0); b : in std_logic_vector(n-1 downto 0); cin : in std_logic_vector(n-1 downto 0); s : out std_logic_vector(n-1 downto 0); cout : out std_logic_vector(n-1 downto 0)); end component; component fcca is generic (n :integer := 32); port ( a : in std_logic_vector(n-1 downto 0); b : in std_logic_vector(n-1 downto 0); s : out std_logic_vector(n-1 downto 0)); end component; component pc is generic (n :integer :=32); port ( a : in std_logic_vector(n-1 downto 0); b : in std_logic_vector(n-1 downto 0); c : in std_logic_vector(n-1 downto 0); d : in std_logic_vector(n-1 downto 0); e : in std_logic_vector(n-1 downto 0); s0 : out std_logic_vector(n-1 downto 0); s1 : out std_logic_vector(n-1 downto 0); s2 : out std_logic_vector(n-1 downto 0) ); end component; component regn is generic ( N : integer := 32; init : std_logic_vector ); port ( clk : in std_logic; rst : in std_logic; en : in std_logic; input : in std_logic_vector(N-1 downto 0); output : out std_logic_vector(N-1 downto 0) ); end component; component d_ff is port( clk : in std_logic; ena : in std_logic; rst : in std_logic; d : in std_logic; q : out std_logic); end component; component piso is generic ( N : integer := 512; --inputs M : integer := 32 --outputs -- N must be divisible by M ); port ( clk : in std_logic; en : in std_logic; sel : in std_logic; input : in std_logic_vector(N-1 downto 0); output : out std_logic_vector(M-1 downto 0) ); end component; component sipo is generic ( N : integer := 512; M : integer := 32 -- N must be divisible by M ); port ( clk : in std_logic; en : in std_logic; input : in std_logic_vector(M-1 downto 0); output : out std_logic_vector(N-1 downto 0) ); end component; component countern is generic ( N : integer := 2; step:integer:=1; style :integer :=COUNTER_STYLE_1 ); port ( clk : in std_logic; rst : in std_logic; load : in std_logic; en : in std_logic; input : in std_logic_vector(N-1 downto 0); output : out std_logic_vector(N-1 downto 0) ); end component; component decountern is generic ( n : integer := 64; sub : integer := 1 ); port ( clk : in std_logic; rst : in std_logic; load : in std_logic; en : in std_logic; input : in std_logic_vector(n-1 downto 0); --sub : in std_logic_vector(n-1 downto 0); output : out std_logic_vector(n-1 downto 0) ); end component; component sr_reg is generic ( init : std_logic := '0' ); port ( rst : in std_logic; clk : in std_logic; set : in std_logic; clr : in std_logic; output : out std_logic ); end component; component sync_clock is generic ( fr : integer := 1 ); port ( rst : in std_logic; fast_clock : in std_logic; slow_clock : in std_logic; sync : out std_logic ); end component; component fifo_ram is generic ( fifo_mode : integer := ZERO_WAIT_STATE; depth : integer := 512; log2depth : integer := 9; n : integer := 64 ); port ( clk : in std_logic; write : in std_logic; rd_addr : in std_logic_vector (log2depth-1 downto 0); wr_addr : in std_logic_vector (log2depth-1 downto 0); din : in std_logic_vector (n-1 downto 0); dout : out std_logic_vector (n-1 downto 0)); end component; component fifo generic ( fifo_mode : integer := ONE_WAIT_STATE; depth : integer := 64; log2depth : integer := 6; N : integer := 32); port ( clk : in std_logic; rst : in std_logic; write : in std_logic; read : in std_logic; din : in std_logic_vector(n-1 downto 0); dout : out std_logic_vector(n-1 downto 0); full : in std_logic; empty : out std_logic); end component; component aes_sbox_sync is port( clk : in std_logic; input : in std_logic_vector(AES_SBOX_SIZE-1 downto 0); output : out std_logic_vector(AES_SBOX_SIZE-1 downto 0)); end component; component aes_sbox is generic (rom_style :integer:=DISTRIBUTED); port( input : in std_logic_vector(AES_SBOX_SIZE-1 downto 0); output : out std_logic_vector(AES_SBOX_SIZE-1 downto 0)); end component; component aes_mul is generic (cons :integer := 3); port( input : in std_logic_vector(AES_SBOX_SIZE-1 downto 0); output : out std_logic_vector(AES_SBOX_SIZE-1 downto 0)); end component; component aes_mixcolumn is port( input : in std_logic_vector(AES_WORD_SIZE-1 downto 0); output : out std_logic_vector(AES_WORD_SIZE-1 downto 0)); end component; component aes_shiftrow is generic (n :integer := AES_BLOCK_SIZE; s :integer := AES_SBOX_SIZE); port( input : in std_logic_vector(n-1 downto 0); output : out std_logic_vector(n-1 downto 0)); end component; component aes_tbox0 is port ( address : in std_logic_vector(AES_SBOX_SIZE-1 downto 0); dout : out std_logic_vector(AES_WORD_SIZE-1 downto 0)); end component; component aes_tbox1 is port ( address : in std_logic_vector(AES_SBOX_SIZE-1 downto 0); dout : out std_logic_vector(AES_WORD_SIZE-1 downto 0)); end component; component aes_tbox2 is port ( address : in std_logic_vector(AES_SBOX_SIZE-1 downto 0); dout : out std_logic_vector(AES_WORD_SIZE-1 downto 0)); end component; component aes_tbox3 is port ( address : in std_logic_vector(AES_SBOX_SIZE-1 downto 0); dout : out std_logic_vector(AES_WORD_SIZE-1 downto 0)); end component; component aes_tbox0_sync is port ( clk : in std_logic; address : in std_logic_vector(AES_SBOX_SIZE-1 downto 0); dout : out std_logic_vector(AES_WORD_SIZE-1 downto 0)); end component; component aes_tbox1_sync is port ( clk : in std_logic; address : in std_logic_vector(AES_SBOX_SIZE-1 downto 0); dout : out std_logic_vector(AES_WORD_SIZE-1 downto 0)); end component; component aes_tbox2_sync is port ( clk : in std_logic; address : in std_logic_vector(AES_SBOX_SIZE-1 downto 0); dout : out std_logic_vector(AES_WORD_SIZE-1 downto 0)); end component; component aes_tbox3_sync is port ( clk : in std_logic; address : in std_logic_vector(AES_SBOX_SIZE-1 downto 0); dout : out std_logic_vector(AES_WORD_SIZE-1 downto 0)); end component; component aes_round is generic (rom_style :integer:=DISTRIBUTED); port( input : in std_logic_vector(AES_BLOCK_SIZE-1 downto 0); key : in std_logic_vector(AES_BLOCK_SIZE-1 downto 0); output : out std_logic_vector(AES_BLOCK_SIZE-1 downto 0)); end component; component aes_round_sync is generic (rom_style :integer:=DISTRIBUTED); port( clk : in std_logic; input : in std_logic_vector(AES_BLOCK_SIZE-1 downto 0); key : in std_logic_vector(AES_BLOCK_SIZE-1 downto 0); output : out std_logic_vector(AES_BLOCK_SIZE-1 downto 0)); end component; component sha3_fsm3 is generic ( w : integer := 64; h : integer := 256 ); port ( --global clk : in std_logic; rst : in std_logic; -- datapath eo : out std_logic; -- fsm 2 handshake signal output_write : in std_logic; output_write_clr : out std_logic; output_busy_clr : out std_logic; -- fifo dst_ready : in std_logic; dst_write : out std_logic ); end component; component aes_sbox_logic is Port ( S_IN : in STD_LOGIC_VECTOR (7 downto 0); S_OUT : out STD_LOGIC_VECTOR (7 downto 0)); end component; component shfreg is generic ( width : integer := 32; depth : integer := 16 ); port ( clk : in std_logic; en : in std_logic; i : in std_logic_vector(width-1 downto 0); o : out std_logic_vector(width-1 downto 0) ); end component; component adder is generic ( adder_type : integer:= SCCA_BASED; n : integer := 64); port( a : in std_logic_vector(n-1 downto 0); b : in std_logic_vector(n-1 downto 0); s : out std_logic_vector(n-1 downto 0) ); end component; component regna is generic ( RST_ACTIVE_VALUE : std_logic := '0'; N : integer := 32; INIT : std_logic_vector ); port ( clk : in std_logic; rst : in std_logic; en : in std_logic; input : in std_logic_vector(N-1 downto 0); output : out std_logic_vector(N-1 downto 0) ); end component; component sr_rega is generic ( RST_ACTIVE_VALUE : std_logic := '0'; INIT : std_logic := '0' ); port ( rst : in std_logic; clk : in std_logic; set : in std_logic; clr : in std_logic; output : out std_logic ); end component; component counterna is generic ( RST_ACTIVE_VALUE : std_logic := '0'; N : integer := 2 ); port ( clk : in std_logic; rst : in std_logic; load : in std_logic; en : in std_logic; output : out std_logic_vector(N-1 downto 0) ); end component; end sha3_pkg; -- functions description package body sha3_pkg is function shrx ( x : std_logic_vector; y : integer) return std_logic_vector is variable zeros : std_logic_vector(y-1 downto 0) := (others => '0'); begin return (zeros & x(x'high downto y)); end shrx; function shlx ( x : std_logic_vector; y : integer) return std_logic_vector is variable zeros : std_logic_vector(y-1 downto 0) := (others => '0'); begin return (x(x'high-y downto x'low) & zeros); end shlx; function rorx ( x : std_logic_vector; y : integer) return std_logic_vector is begin return (x(y-1 downto x'low) & x(x'high downto y)); end rorx; function rolx ( x : std_logic_vector; y : integer) return std_logic_vector is begin return (x(x'high-y downto x'low) & x(x'high downto x'high-y+1)); end rolx; function log2 (N: natural) return natural is begin -- if N then -- return 1; -- else -- return 1 + log2(N/2); -- end if; if ( N = 0 ) then return 0; elsif N <= 2 then return 1; else if (N mod 2 = 0) then return 1 + log2(N/2); else return 1 + log2((N+1)/2); end if; end if; end; function switch_endian_byte ( x : std_logic_vector; width : integer; w : integer ) return std_logic_vector is variable xseg : integer := width/w; variable wseg : integer := w/8; variable retval : std_logic_vector(width-1 downto 0); begin for i in xseg downto 1 loop for j in 0 to wseg-1 loop retval(i*w - 1 - j*8 downto i*w - 8 - j*8 ) := x(i*w - 1 - (wseg-1-j)*8 downto i*w - 8 - (wseg-1-j)*8); end loop; end loop; return(retval); end switch_endian_byte; function switch_endian_word ( x : std_logic_vector; width : integer; w : integer ) return std_logic_vector is variable xseg : integer := width/w; variable retval : std_logic_vector(width-1 downto 0); begin for i in xseg downto 1 loop retval(i*w - 1 downto w*(i-1) ) := x(w*(xseg-i+1) - 1 downto w*(xseg-i)); end loop; return(retval); end switch_endian_word; function GF_SQ_SCL_2 ( x : in STD_LOGIC_VECTOR (1 downto 0)) return STD_LOGIC_VECTOR is variable y : STD_LOGIC_VECTOR (1 downto 0); begin y := x(1) & (x(1) xor x(0)); return y; end GF_SQ_SCL_2; function GF_SCL_2 ( x : in STD_LOGIC_VECTOR (1 downto 0)) return STD_LOGIC_VECTOR is variable y : STD_LOGIC_VECTOR (1 downto 0); begin y := x(0) & (x(1) xor x(0)); return y; end GF_SCL_2; function GF_MUL_2 ( x,y : in STD_LOGIC_VECTOR (1 downto 0)) return STD_LOGIC_VECTOR is variable o : STD_LOGIC_VECTOR (1 downto 0); begin o := (((x(1) xor x(0)) and (y(1) xor y(0))) xor (x(1) and y(1))) & (((x(1) xor x(0)) and (y(1) xor y(0))) xor (x(0) and y(0))); return o; end GF_MUL_2; function GF_MUL_SCL_2 ( x,y : in STD_LOGIC_VECTOR (1 downto 0)) return STD_LOGIC_VECTOR is variable o : STD_LOGIC_VECTOR (1 downto 0); begin o := (((x(1) xor x(0)) and (y(1) xor y(0))) xor (x(0) and y(0))) & ((x(1) and y(1)) xor (x(0) and y(0))); return o; end GF_MUL_SCL_2; function GF_INV_2 ( x : in STD_LOGIC_VECTOR (1 downto 0)) return STD_LOGIC_VECTOR is variable y : STD_LOGIC_VECTOR (1 downto 0); begin y(1) := x(0); y(0) := x(1); return y; end GF_INV_2; function GF_SQ_2 ( x : in STD_LOGIC_VECTOR (1 downto 0)) return STD_LOGIC_VECTOR is variable y : STD_LOGIC_VECTOR (1 downto 0); begin y(1) := x(0); y(0) := x(1); return y; end GF_SQ_2; function MUL_X ( x : in STD_LOGIC_VECTOR (7 downto 0)) return STD_LOGIC_VECTOR is variable y : STD_LOGIC_VECTOR (7 downto 0); begin y(7) := x(7) xor x(6) xor x(5) xor x(2) xor x(1) xor x(0); y(6) := x(6) xor x(5) xor x(4) xor x(0); y(5) := x(6) xor x(5) xor x(1) xor x(0); y(4) := x(7) xor x(6) xor x(5) xor x(0); y(3) := x(7) xor x(4) xor x(3) xor x(1) xor x(0); y(2) := x(0); y(1) := x(6) xor x(5) xor x(0); y(0) := x(6) xor x(3) xor x(2) xor x(1) xor x(0); return y; end MUL_X; function MUL_MX ( x : in STD_LOGIC_VECTOR (7 downto 0)) return STD_LOGIC_VECTOR is variable y : STD_LOGIC_VECTOR (7 downto 0); begin y(7) := x(5) xor x(3); y(6) := x(7) xor x(3); y(5) := x(6) xor x(0); y(4) := x(7) xor x(5) xor x(3); y(3) := x(7) xor x(6) xor x(5) xor x(4) xor x(3); y(2) := x(6) xor x(5) xor x(3) xor x(2) xor x(0); y(1) := x(5) xor x(4) xor x(1); y(0) := x(6) xor x(4) xor x(1); return y; end MUL_MX; function GF_INV_4 ( x : in STD_LOGIC_VECTOR (3 downto 0)) return STD_LOGIC_VECTOR is variable y : STD_LOGIC_VECTOR (3 downto 0); variable r0, r1, SQ_IN, SQ_OUT, MUL_1_OUT, GF_INV_IN, GF_INV_OUT, MUL_2_OUT , MUL_3_OUT :STD_LOGIC_VECTOR (1 downto 0); begin r1 := x(3 downto 2); r0 := x(1 downto 0); SQ_IN := r1 xor r0; SQ_OUT := GF_SQ_SCL_2 ( x => SQ_IN); MUL_1_OUT := GF_MUL_2( x => r1, y => r0); GF_INV_IN := MUL_1_OUT xor SQ_OUT; GF_INV_OUT := GF_INV_2(x => GF_INV_IN); MUL_2_OUT := GF_MUL_2 ( x => r1, y => GF_INV_OUT); MUL_3_OUT := GF_MUL_2 ( x => GF_INV_OUT, y => r0); y := MUL_3_OUT & MUL_2_OUT; return y; end GF_INV_4; function GF_MUL_4 ( x,y : in STD_LOGIC_VECTOR (3 downto 0)) return STD_LOGIC_VECTOR is variable o : STD_LOGIC_VECTOR (3 downto 0); variable tao1, tao0, delta1, delta0, fi1, fi0, tmp1, tmp0, RES_MUL1, RES_MUL0,RES_MUL_SCL: std_logic_vector (1 downto 0); begin tao1 := x(3 downto 2); tao0 := x(1 downto 0); delta1 := y(3 downto 2); delta0 := y(1 downto 0); tmp1 := tao1 xor tao0; tmp0 := delta1 xor delta0; RES_MUL1 := GF_MUL_2 ( x=> tao1, y=> delta1); RES_MUL0 := GF_MUL_2 ( x=> tao0, y=> delta0); RES_MUL_SCL := GF_MUL_SCL_2( x=> tmp1, y=> tmp0); fi1 := RES_MUL1 xor RES_MUL_SCL; fi0 := RES_MUL0 xor RES_MUL_SCL; o := fi1 & fi0; return o; end GF_MUL_4; function GF_SQ_SCL_4 ( x : in STD_LOGIC_VECTOR (3 downto 0)) return STD_LOGIC_VECTOR is variable y : STD_LOGIC_VECTOR (3 downto 0); variable tao1, tao0, delta1, delta0, tmp1, tmp0: std_logic_vector (1 downto 0); begin tao1 := x(3 downto 2); tao0 := x(1 downto 0); tmp1 := tao1 xor tao0; tmp0 := GF_SCL_2 ( x => tao0); delta1 := GF_SQ_2( x=> tmp1); delta0 := GF_SQ_2 ( x=> tmp0); y := delta1 & delta0; return y; end GF_SQ_SCL_4; function GF_INV_8 ( x : in STD_LOGIC_VECTOR (7 downto 0)) return STD_LOGIC_VECTOR is variable y : STD_LOGIC_VECTOR (7 downto 0); variable r0, r1, SQ_IN, SQ_OUT, MUL_1_OUT, GF_INV_IN, GF_INV_OUT, MUL_2_OUT , MUL_3_OUT :STD_LOGIC_VECTOR (3 downto 0); begin r1 := x(7 downto 4); r0 := x(3 downto 0); SQ_IN := r1 xor r0; SQ_OUT := GF_SQ_SCL_4 ( x => SQ_IN); MUL_1_OUT := GF_MUL_4 ( x => r1, y => r0); GF_INV_IN := MUL_1_OUT xor SQ_OUT; GF_INV_OUT := GF_INV_4 (x => GF_INV_IN); MUL_2_OUT := GF_MUL_4 ( x => r1, y => GF_INV_OUT); MUL_3_OUT := GF_MUL_4 ( x => GF_INV_OUT, y => r0); y := MUL_3_OUT & MUL_2_OUT; return y; end GF_INV_8; end package body sha3_pkg;