library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
package sha256_pkg is
subtype word is std_ulogic_vector(63 downto 0);
type word_vector is array(integer range <>) of word;
subtype sha_msg is std_ulogic_vector(1023 downto 0);
subtype sha_hash is std_ulogic_vector(511 downto 0);
type sha_array is array(integer range <>) of sha_msg;
----------------------------------
--array of round constants
----------------------------------
constant K_constants : word_vector(0 to 79) := ( X"428a2f98d728ae22" , X"7137449123ef65cd", X"b5c0fbcfec4d3b2f" , X"e9b5dba58189dbbc" ,
X"3956c25bf348b538" ,X"59f111f1b605d019" , X"923f82a4af194f9b" , X"ab1c5ed5da6d8118" ,X"d807aa98a3030242" ,
X"12835b0145706fbe" , X"243185be4ee4b28c" ,X"550c7dc3d5ffb4e2" , X"72be5d74f27b896f" ,X"80deb1fe3b1696b1" ,
X"9bdc06a725c71235" ,X"c19bf174cf692694" , X"e49b69c19ef14ad2" ,X"efbe4786384f25e3" ,X"0fc19dc68b8cd5b5" ,
X"240ca1cc77ac9c65" ,X"2de92c6f592b0275" ,X"4a7484aa6ea6e483" ,X"5cb0a9dcbd41fbd4" ,X"76f988da831153b5" ,
X"983e5152ee66dfab" ,X"a831c66d2db43210" , X"b00327c898fb213f" , X"bf597fc7beef0ee4" ,X"c6e00bf33da88fc2",
X"d5a79147930aa725" ,X"06ca6351e003826f" ,X"142929670a0e6e70" ,X"27b70a8546d22ffc" ,X"2e1b21385c26c926" ,
X"4d2c6dfc5ac42aed" , X"53380d139d95b3df" , X"650a73548baf63de" , X"766a0abb3c77b2a8" ,X"81c2c92e47edaee6" ,
X"92722c851482353b" , X"a2bfe8a14cf10364" , X"a81a664bbc423001" ,X"c24b8b70d0f89791" ,X"c76c51a30654be30" ,
X"d192e819d6ef5218" ,X"d69906245565a910" ,X"f40e35855771202a" ,X"106aa07032bbd1b8" ,X"19a4c116b8d2d0c8" ,
X"1e376c085141ab53" ,X"2748774cdf8eeb99" ,X"34b0bcb5e19b48a8", X"391c0cb3c5c95a63" ,X"4ed8aa4ae3418acb" ,
X"5b9cca4f7763e373" , X"682e6ff3d6b2b8a3" ,X"748f82ee5defb2fc" , X"78a5636f43172f60" , X"84c87814a1f0ab72",
X"8cc702081a6439ec" ,X"90befffa23631e28" ,X"a4506cebde82bde9" ,X"bef9a3f7b2c67915" , X"c67178f2e372532b" ,
X"ca273eceea26619c" ,X"d186b8c721c0c207" ,X"eada7dd6cde0eb1e" ,X"f57d4f7fee6ed178" ,X"06f067aa72176fba" ,
X"0a637dc5a2c898a6",X"113f9804bef90dae" , X"1b710b35131c471b" ,X"28db77f523047d84" , X"32caab7b40c72493" ,
X"3c9ebe0a15c9bebc" ,X"431d67c49c100d4c" ,X"4cc5d4becb3e42b6" ,X"597f299cfc657e2a" , X"5fcb6fab3ad6faec" ,
X"6c44198c4a475817" );
----------------------------------
--array of initial hash values
----------------------------------
constant H_init : word_vector(0 to 7) := (
x"6a09e667f3bcc908",
x"bb67ae8584caa73b",
x"3c6ef372fe94f82b",
x"a54ff53a5f1d36f1",
x"510e527fade682d1",
x"9b05688c2b3e6c1f",
x"1f83d9abfb41bd6b",
x"5be0cd19137e2179"
);
----------------------------------
--function definitions
----------------------------------
function shr(x : word; n : natural) return word;
function rotr(x : word; n : natural) return word;
function rotl(x : word; n : natural) return word;
function Ch(x,y,z : word) return word;
function Maj(x,y,z : word) return word;
function sigma_lower0(x : word) return word; --std_ulogic_vector;
function sigma_lower1(x : word) return word; --std_ulogic_vector;
function sigma_upper0(x : word) return word; --std_ulogic_vector;
function sigma_upper1(x : word) return word; --std_ulogic_vector;
function expand_msg_blocks(w : word_vector(15 downto 0)) return word_vector;
function break_chunks(msg : sha_msg) return word_vector;
function return_chunk(msg : sha_msg; i : natural) return std_ulogic_vector;
procedure compression(variable a, b, c, d, e, f, g, h, t1, t2, exp_w : inout word; i : in natural);
procedure sha256_onechunk(msg : in sha_msg; variable h0, h1, h2, h3, h4, h5, h6, h7 : inout word); ---one message
function sha256(blocks : sha_array; length : natural) return std_ulogic_vector; ---array of mesgs
end sha256_pkg;
package body sha256_pkg is
----------------------------------
--function implementations
----------------------------------
function shr(x : word; n : natural) return word is
begin
return std_ulogic_vector(shift_right(unsigned(x), n));
end function;
function rotr(x : word; n : natural) return word is
begin
return std_ulogic_vector(rotate_right(unsigned(x), n));
end function;
function rotl(x : word; n : natural) return word is
begin
return std_ulogic_vector(rotate_left(unsigned(x), n));
end function;
function Ch(x,y,z : word) return word is ---was std_ulogic_vector
begin
return (x and y) xor (not(x) and z);
end function;
function Maj(x,y,z : word) return word is
begin
return (x and y) xor (x and z) xor (y and z);
end function;
-----?0(x) && ?1(x)
function sigma_lower0(x : word) return word is
begin
return rotr(x, 1) xor rotr(x, 8) xor shr(x, 7);
end function;
function sigma_lower1(x : word) return word is
begin
return rotr(x, 19) xor rotr(x, 61) xor shr(x, 6);
end function;
------- ?0(x) & ?1(x)
function sigma_upper0(x : word) return word is
begin
return rotr(x, 28) xor rotr(x, 34) xor rotr(x, 39);
end function;
function sigma_upper1(x : word) return word is
begin
return rotr(x, 14) xor rotr(x, 18) xor rotr(x, 41);
end function;
--- Wt equation
function expand_msg_blocks(w : word_vector(15 downto 0)) return word_vector is
variable exp_w : word_vector(79 downto 0);
begin
for i in 0 to 79 loop --rounds=79
if i < 16 then
exp_w(i) := w(i);
else
exp_w(i) := std_ulogic_vector(unsigned(exp_w(i-16)) + unsigned(sigma_lower0(exp_w(i-15))) + unsigned(exp_w(i-7)) + unsigned(sigma_lower1(exp_w(i-2))));
end if;
end loop;
return exp_w;
end function;
---- divide message to wt from 0:15
function break_chunks(msg : sha_msg) return word_vector is
variable w : word_vector(15 downto 0);
begin
for i in 0 to 15 loop
w(i) := msg(1024-(i*64+1) downto 1024-(i*64+64));
end loop;
return w;
end function;
function return_chunk(msg : sha_msg; i : natural) return std_ulogic_vector is
begin
return msg(1024-(i*64+1) downto 1024-(i*64+64));
end function;
procedure compression(variable a, b, c, d, e, f, g, h, t1, t2, exp_w : inout word; i : in natural) is
begin
t2 := std_ulogic_vector(unsigned(sigma_upper0(a)) + unsigned(Maj(a, b, c)));
t1 := std_ulogic_vector(unsigned(h) + unsigned(sigma_upper1(e)) + unsigned(Ch(e, f, g)) + unsigned(K_constants(i)) + unsigned(exp_w));
h := g;
g := f;
f := e;
e := std_ulogic_vector(unsigned(d) + unsigned(t1));
d := c;
c := b;
b := a;
a := std_ulogic_vector(unsigned(t1) + unsigned(t2));
end procedure;
procedure sha256_onechunk(msg : in sha_msg; variable h0, h1, h2, h3, h4, h5, h6, h7 : inout word) is
variable w : word_vector(15 downto 0);
variable exp_w : word_vector(79 downto 0);
variable a, b, c, d, e, f, g, h, t1, t2 : word;
begin
w := break_chunks(msg); --- take block 1024 bit and gives 16 words
exp_w := expand_msg_blocks(w); ---take 16 words and gives from 16 to 79
a := h0;
b := h1;
c := h2;
d := h3;
e := h4;
f := h5;
g := h6;
h := h7;
for i in 0 to 79 loop
compression(a, b, c, d, e, f, g, h, t1, t2, exp_w(i), i);
end loop;
h0 := std_ulogic_vector(unsigned(h0) + unsigned(a));
h1 := std_ulogic_vector(unsigned(h1) + unsigned(b));
h2 := std_ulogic_vector(unsigned(h2) + unsigned(c));
h3 := std_ulogic_vector(unsigned(h3) + unsigned(d));
h4 := std_ulogic_vector(unsigned(h4) + unsigned(e));
h5 := std_ulogic_vector(unsigned(h5) + unsigned(f));
h6 := std_ulogic_vector(unsigned(h6) + unsigned(g));
h7 := std_ulogic_vector(unsigned(h7) + unsigned(h));
end procedure;
function sha256(blocks : sha_array; length : natural) return std_ulogic_vector is ---- compute hash for more than one block
variable h0, h1, h2, h3, h4, h5, h6, h7 : word;
begin
h0 := H_init(0);
h1 := H_init(1);
h2 := H_init(2);
h3 := H_init(3);
h4 := H_init(4);
h5 := H_init(5);
h6 := H_init(6);
h7 := H_init(7);
for i in length-1 downto 0 loop
sha256_onechunk(blocks(i), h0, h1, h2, h3, h4, h5, h6, h7);
end loop;
return h0 & h1 & h2 & h3 & h4 & h5 & h6 & h7;
end function sha256;
end package body sha256_pkg;