///////////////////////////////////////////////////////////////////// //// //// //// SHA-160 //// //// Secure Hash Algorithm (SHA-160) //// //// //// //// Author: marsgod //// //// marsgod@opencores.org //// //// //// //// //// //// Downloaded from: http://www.opencores.org/cores/sha_core/ //// //// //// ///////////////////////////////////////////////////////////////////// //// //// //// Copyright (C) 2002-2004 marsgod //// //// marsgod@opencores.org //// //// //// //// //// //// This source file may be used and distributed without //// //// restriction provided that this copyright statement is not //// //// removed from the file and that any derivative work contains //// //// the original copyright notice and the associated disclaimer.//// //// //// //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// //// POSSIBILITY OF SUCH DAMAGE. //// //// //// ///////////////////////////////////////////////////////////////////// `define SHA1_H0 32'h67452301 `define SHA1_H1 32'hefcdab89 `define SHA1_H2 32'h98badcfe `define SHA1_H3 32'h10325476 `define SHA1_H4 32'hc3d2e1f0 `define SHA1_K0 32'h5a827999 `define SHA1_K1 32'h6ed9eba1 `define SHA1_K2 32'h8f1bbcdc `define SHA1_K3 32'hca62c1d6 module sha1 (clk_i, rst_i, text_i, text_o, cmd_i, cmd_w_i, cmd_o); input clk_i; // global clock input input rst_i; // global reset input , active high input [31:0] text_i; // text input 32bit output [31:0] text_o; // text output 32bit input [2:0] cmd_i; // command input input cmd_w_i;// command input write enable output [3:0] cmd_o; // command output(status) /* cmd Busy Round W R bit3 bit2 bit1 bit0 Busy Round W R Busy: 0 idle 1 busy Round: 0 first round 1 internal round W: 0 No-op 1 write data R: 0 No-op 1 read data */ reg [3:0] cmd; wire [3:0] cmd_o; reg [31:0] text_o; reg [6:0] round; wire [6:0] round_plus_1; reg [2:0] read_counter; reg [31:0] H0,H1,H2,H3,H4; reg [31:0] W0,W1,W2,W3,W4,W5,W6,W7,W8,W9,W10,W11,W12,W13,W14; reg [31:0] Wt,Kt; reg [31:0] A,B,C,D,E; reg busy; assign cmd_o = cmd; always @ (posedge clk_i) begin if (rst_i) cmd <= 'b0; else if (cmd_w_i) cmd[2:0] <= cmd_i[2:0]; // busy bit can't write else begin cmd[3] <= busy; // update busy bit if (~busy) cmd[1:0] <= 2'b00; // hardware auto clean R/W bits end end // Hash functions wire [31:0] SHA1_f1_BCD,SHA1_f2_BCD,SHA1_f3_BCD,SHA1_Wt_1; wire [31:0] SHA1_ft_BCD; wire [31:0] next_Wt,next_A,next_C; wire [159:0] SHA1_result; assign SHA1_f1_BCD = (B & C) ^ (~B & D); assign SHA1_f2_BCD = B ^ C ^ D; assign SHA1_f3_BCD = (B & C) ^ (C & D) ^ (B & D); assign SHA1_ft_BCD = (round < 'd21) ? SHA1_f1_BCD : (round < 'd41) ? SHA1_f2_BCD : (round < 'd61) ? SHA1_f3_BCD : SHA1_f2_BCD; assign SHA1_Wt_1 = {W13 ^ W8 ^ W2 ^ W0}; assign next_Wt = {SHA1_Wt_1[30:0],SHA1_Wt_1[31]}; // NSA fix added assign next_A = {A[26:0],A[31:27]} + SHA1_ft_BCD + E + Kt + Wt; assign next_C = {B[1:0],B[31:2]}; assign SHA1_result = {A,B,C,D,E}; assign round_plus_1 = round + 1; //------------------------------------------------------------------ // SHA round //------------------------------------------------------------------ always @(posedge clk_i) begin if (rst_i) begin round <= 'd0; busy <= 'b0; W0 <= 'b0; W1 <= 'b0; W2 <= 'b0; W3 <= 'b0; W4 <= 'b0; W5 <= 'b0; W6 <= 'b0; W7 <= 'b0; W8 <= 'b0; W9 <= 'b0; W10 <= 'b0; W11 <= 'b0; W12 <= 'b0; W13 <= 'b0; W14 <= 'b0; Wt <= 'b0; A <= 'b0; B <= 'b0; C <= 'b0; D <= 'b0; E <= 'b0; H0 <= 'b0; H1 <= 'b0; H2 <= 'b0; H3 <= 'b0; H4 <= 'b0; end else begin case (round) 'd0: begin if (cmd[1]) begin W0 <= text_i; Wt <= text_i; busy <= 'b1; round <= round_plus_1; case (cmd[2]) 1'b0: // sha-1 first message begin A <= `SHA1_H0; B <= `SHA1_H1; C <= `SHA1_H2; D <= `SHA1_H3; E <= `SHA1_H4; H0 <= `SHA1_H0; H1 <= `SHA1_H1; H2 <= `SHA1_H2; H3 <= `SHA1_H3; H4 <= `SHA1_H4; end 1'b1: // sha-1 internal message begin H0 <= A; H1 <= B; H2 <= C; H3 <= D; H4 <= E; end endcase end else begin // IDLE round <= 'd0; end end 'd1: begin W1 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd2: begin W2 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd3: begin W3 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd4: begin W4 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd5: begin W5 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd6: begin W6 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd7: begin W7 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd8: begin W8 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd9: begin W9 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd10: begin W10 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd11: begin W11 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd12: begin W12 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd13: begin W13 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd14: begin W14 <= text_i; Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd15: begin Wt <= text_i; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd16, 'd17, 'd18, 'd19, 'd20, 'd21, 'd22, 'd23, 'd24, 'd25, 'd26, 'd27, 'd28, 'd29, 'd30, 'd31, 'd32, 'd33, 'd34, 'd35, 'd36, 'd37, 'd38, 'd39, 'd40, 'd41, 'd42, 'd43, 'd44, 'd45, 'd46, 'd47, 'd48, 'd49, 'd50, 'd51, 'd52, 'd53, 'd54, 'd55, 'd56, 'd57, 'd58, 'd59, 'd60, 'd61, 'd62, 'd63, 'd64, 'd65, 'd66, 'd67, 'd68, 'd69, 'd70, 'd71, 'd72, 'd73, 'd74, 'd75, 'd76, 'd77, 'd78, 'd79: begin W0 <= W1; W1 <= W2; W2 <= W3; W3 <= W4; W4 <= W5; W5 <= W6; W6 <= W7; W7 <= W8; W8 <= W9; W9 <= W10; W10 <= W11; W11 <= W12; W12 <= W13; W13 <= W14; W14 <= Wt; Wt <= next_Wt; E <= D; D <= C; C <= next_C; B <= A; A <= next_A; round <= round_plus_1; end 'd80: begin A <= next_A + H0; B <= A + H1; C <= next_C + H2; D <= C + H3; E <= D + H4; round <= 'd0; busy <= 'b0; end default: begin round <= 'd0; busy <= 'b0; end endcase end end //------------------------------------------------------------------ // Kt generator //------------------------------------------------------------------ always @ (posedge clk_i) begin if (rst_i) begin Kt <= 'b0; end else begin if (round < 'd20) Kt <= `SHA1_K0; else if (round < 'd40) Kt <= `SHA1_K1; else if (round < 'd60) Kt <= `SHA1_K2; else Kt <= `SHA1_K3; end end //------------------------------------------------------------------ // read result //------------------------------------------------------------------ always @ (posedge clk_i) begin if (rst_i) begin text_o <= 'b0; read_counter <= 'b0; end else begin if (cmd[0]) begin read_counter <= 'd4; // sha-1 160/32=5 end else begin if (~busy) begin case (read_counter) 'd4: text_o <= SHA1_result[5*32-1:4*32]; 'd3: text_o <= SHA1_result[4*32-1:3*32]; 'd2: text_o <= SHA1_result[3*32-1:2*32]; 'd1: text_o <= SHA1_result[2*32-1:1*32]; 'd0: text_o <= SHA1_result[1*32-1:0*32]; default:text_o <= 'b0; endcase if (|read_counter) read_counter <= read_counter - 'd1; end else begin text_o <= 'b0; end end end end endmodule