From cf85a6d40c02376c82dbf43a598066de33db099f Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Mon, 23 Oct 2023 11:25:13 +0200 Subject: [PATCH] fpga: Add cores for SHA256 Cores originate from https://github.com/secworks/sha256. Original-commit: c43c72db097cbb5ebe29b7fa81484cbeaf19516b --- lib/sec/Makefile.srcs | 16 + lib/sec/SHA256.md | 31 ++ lib/sec/sha256.v | 266 +++++++++++++++++ lib/sec/sha256_core.v | 556 +++++++++++++++++++++++++++++++++++ lib/sec/sha256_k_constants.v | 136 +++++++++ lib/sec/sha256_stream.v | 79 +++++ lib/sec/sha256_w_mem.v | 242 +++++++++++++++ 7 files changed, 1326 insertions(+) create mode 100644 lib/sec/Makefile.srcs create mode 100644 lib/sec/SHA256.md create mode 100644 lib/sec/sha256.v create mode 100644 lib/sec/sha256_core.v create mode 100644 lib/sec/sha256_k_constants.v create mode 100644 lib/sec/sha256_stream.v create mode 100644 lib/sec/sha256_w_mem.v diff --git a/lib/sec/Makefile.srcs b/lib/sec/Makefile.srcs new file mode 100644 index 0000000..afc8b02 --- /dev/null +++ b/lib/sec/Makefile.srcs @@ -0,0 +1,16 @@ +# +# Copyright 2023 Ettus Research, a National Instruments Brand +# +# SPDX-License-Identifier: LGPL-3.0-or-later +# + +################################################## +# DSP Sources +################################################## +SEC_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/sec/, \ +sha256.v \ +sha256_core.v \ +sha256_k_constants.v \ +sha256_stream.v \ +sha256_w_mem.v \ +)) diff --git a/lib/sec/SHA256.md b/lib/sec/SHA256.md new file mode 100644 index 0000000..0d9682b --- /dev/null +++ b/lib/sec/SHA256.md @@ -0,0 +1,31 @@ +# SHA256 Cores + +All sha256\*.v files are copied from https://github.com/secworks/sha256 and carry +the same license text (see below). For copyright notices, see individual source +files. + +### License + +Copyright (c) 2013, Joachim Strömbergson +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. diff --git a/lib/sec/sha256.v b/lib/sec/sha256.v new file mode 100644 index 0000000..e665fe2 --- /dev/null +++ b/lib/sec/sha256.v @@ -0,0 +1,266 @@ +//====================================================================== +// +// sha256.v +// -------- +// Top level wrapper for the SHA-256 hash function providing +// a simple memory like interface with 32 bit data access. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2013, 201, Secworks Sweden AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER 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. +// +//====================================================================== + +`default_nettype none + +module sha256( + // Clock and reset. + input wire clk, + input wire reset_n, + + // Control. + input wire cs, + input wire we, + + // Data ports. + input wire [7 : 0] address, + input wire [31 : 0] write_data, + output wire [31 : 0] read_data, + output wire error + ); + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + localparam ADDR_NAME0 = 8'h00; + localparam ADDR_NAME1 = 8'h01; + localparam ADDR_VERSION = 8'h02; + + localparam ADDR_CTRL = 8'h08; + localparam CTRL_INIT_BIT = 0; + localparam CTRL_NEXT_BIT = 1; + localparam CTRL_MODE_BIT = 2; + + localparam ADDR_STATUS = 8'h09; + localparam STATUS_READY_BIT = 0; + localparam STATUS_VALID_BIT = 1; + + localparam ADDR_BLOCK0 = 8'h10; + localparam ADDR_BLOCK15 = 8'h1f; + + localparam ADDR_DIGEST0 = 8'h20; + localparam ADDR_DIGEST7 = 8'h27; + + localparam CORE_NAME0 = 32'h73686132; // "sha2" + localparam CORE_NAME1 = 32'h2d323536; // "-256" + localparam CORE_VERSION = 32'h312e3830; // "1.80" + + localparam MODE_SHA_224 = 1'h0; + localparam MODE_SHA_256 = 1'h1; + + + //---------------------------------------------------------------- + // Registers including update variables and write enable. + //---------------------------------------------------------------- + reg init_reg; + reg init_new; + + reg next_reg; + reg next_new; + + reg mode_reg; + reg mode_new; + reg mode_we; + + reg ready_reg; + + reg [31 : 0] block_reg [0 : 15]; + reg block_we; + + reg [255 : 0] digest_reg; + + reg digest_valid_reg; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + wire core_ready; + wire [511 : 0] core_block; + wire [255 : 0] core_digest; + wire core_digest_valid; + + reg [31 : 0] tmp_read_data; + reg tmp_error; + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign core_block = {block_reg[00], block_reg[01], block_reg[02], block_reg[03], + block_reg[04], block_reg[05], block_reg[06], block_reg[07], + block_reg[08], block_reg[09], block_reg[10], block_reg[11], + block_reg[12], block_reg[13], block_reg[14], block_reg[15]}; + + assign read_data = tmp_read_data; + assign error = tmp_error; + + + //---------------------------------------------------------------- + // core instantiation. + //---------------------------------------------------------------- + sha256_core core( + .clk(clk), + .reset_n(reset_n), + + .init(init_reg), + .next(next_reg), + .mode(mode_reg), + + .block(core_block), + + .ready(core_ready), + + .digest(core_digest), + .digest_valid(core_digest_valid) + ); + + + //---------------------------------------------------------------- + // reg_update + // + // Update functionality for all registers in the core. + // All registers are positive edge triggered with asynchronous + // active low reset. All registers have write enable. + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin : reg_update + integer i; + + if (!reset_n) + begin + for (i = 0 ; i < 16 ; i = i + 1) + block_reg[i] <= 32'h0; + + init_reg <= 0; + next_reg <= 0; + ready_reg <= 0; + mode_reg <= MODE_SHA_256; + digest_reg <= 256'h0; + digest_valid_reg <= 0; + end + else + begin + ready_reg <= core_ready; + digest_valid_reg <= core_digest_valid; + init_reg <= init_new; + next_reg <= next_new; + + if (mode_we) + mode_reg <= mode_new; + + if (core_digest_valid) + digest_reg <= core_digest; + + if (block_we) + block_reg[address[3 : 0]] <= write_data; + end + end // reg_update + + + //---------------------------------------------------------------- + // api_logic + // + // Implementation of the api logic. If cs is enabled will either + // try to write to or read from the internal registers. + //---------------------------------------------------------------- + always @* + begin : api_logic + init_new = 0; + next_new = 0; + mode_new = 0; + mode_we = 0; + block_we = 0; + tmp_read_data = 32'h0; + tmp_error = 0; + + if (cs) + begin + if (we) + begin + if (address == ADDR_CTRL) + begin + init_new = write_data[CTRL_INIT_BIT]; + next_new = write_data[CTRL_NEXT_BIT]; + mode_new = write_data[CTRL_MODE_BIT]; + mode_we = 1; + end + + if ((address >= ADDR_BLOCK0) && (address <= ADDR_BLOCK15)) + block_we = 1; + end // if (we) + + else + begin + if ((address >= ADDR_BLOCK0) && (address <= ADDR_BLOCK15)) + tmp_read_data = block_reg[address[3 : 0]]; + + if ((address >= ADDR_DIGEST0) && (address <= ADDR_DIGEST7)) + tmp_read_data = digest_reg[(7 - (address - ADDR_DIGEST0)) * 32 +: 32]; + + case (address) + // Read operations. + ADDR_NAME0: + tmp_read_data = CORE_NAME0; + + ADDR_NAME1: + tmp_read_data = CORE_NAME1; + + ADDR_VERSION: + tmp_read_data = CORE_VERSION; + + ADDR_CTRL: + tmp_read_data = {29'h0, mode_reg, next_reg, init_reg}; + + ADDR_STATUS: + tmp_read_data = {30'h0, digest_valid_reg, ready_reg}; + + default: + begin + end + endcase // case (address) + end + end + end // addr_decoder +endmodule // sha256 + +`default_nettype wire +//====================================================================== +// EOF sha256.v +//====================================================================== diff --git a/lib/sec/sha256_core.v b/lib/sec/sha256_core.v new file mode 100644 index 0000000..a8a821b --- /dev/null +++ b/lib/sec/sha256_core.v @@ -0,0 +1,556 @@ +//====================================================================== +// +// sha256_core.v +// ------------- +// Verilog 2001 implementation of the SHA-256 hash function. +// This is the internal core with wide interfaces. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2013, Secworks Sweden AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER 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. +// +//====================================================================== + +`default_nettype none + +module sha256_core( + input wire clk, + input wire reset_n, + + input wire init, + input wire next, + input wire mode, + + input wire [511 : 0] block, + + output wire ready, + output wire [255 : 0] digest, + output wire digest_valid + ); + + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + localparam SHA224_H0_0 = 32'hc1059ed8; + localparam SHA224_H0_1 = 32'h367cd507; + localparam SHA224_H0_2 = 32'h3070dd17; + localparam SHA224_H0_3 = 32'hf70e5939; + localparam SHA224_H0_4 = 32'hffc00b31; + localparam SHA224_H0_5 = 32'h68581511; + localparam SHA224_H0_6 = 32'h64f98fa7; + localparam SHA224_H0_7 = 32'hbefa4fa4; + + localparam SHA256_H0_0 = 32'h6a09e667; + localparam SHA256_H0_1 = 32'hbb67ae85; + localparam SHA256_H0_2 = 32'h3c6ef372; + localparam SHA256_H0_3 = 32'ha54ff53a; + localparam SHA256_H0_4 = 32'h510e527f; + localparam SHA256_H0_5 = 32'h9b05688c; + localparam SHA256_H0_6 = 32'h1f83d9ab; + localparam SHA256_H0_7 = 32'h5be0cd19; + + localparam SHA256_ROUNDS = 63; + + localparam CTRL_IDLE = 0; + localparam CTRL_ROUNDS = 1; + localparam CTRL_DONE = 2; + + + //---------------------------------------------------------------- + // Registers including update variables and write enable. + //---------------------------------------------------------------- + reg [31 : 0] a_reg; + reg [31 : 0] a_new; + reg [31 : 0] b_reg; + reg [31 : 0] b_new; + reg [31 : 0] c_reg; + reg [31 : 0] c_new; + reg [31 : 0] d_reg; + reg [31 : 0] d_new; + reg [31 : 0] e_reg; + reg [31 : 0] e_new; + reg [31 : 0] f_reg; + reg [31 : 0] f_new; + reg [31 : 0] g_reg; + reg [31 : 0] g_new; + reg [31 : 0] h_reg; + reg [31 : 0] h_new; + reg a_h_we; + + reg [31 : 0] H0_reg; + reg [31 : 0] H0_new; + reg [31 : 0] H1_reg; + reg [31 : 0] H1_new; + reg [31 : 0] H2_reg; + reg [31 : 0] H2_new; + reg [31 : 0] H3_reg; + reg [31 : 0] H3_new; + reg [31 : 0] H4_reg; + reg [31 : 0] H4_new; + reg [31 : 0] H5_reg; + reg [31 : 0] H5_new; + reg [31 : 0] H6_reg; + reg [31 : 0] H6_new; + reg [31 : 0] H7_reg; + reg [31 : 0] H7_new; + reg H_we; + + reg [5 : 0] t_ctr_reg; + reg [5 : 0] t_ctr_new; + reg t_ctr_we; + reg t_ctr_inc; + reg t_ctr_rst; + + reg digest_valid_reg; + reg digest_valid_new; + reg digest_valid_we; + + reg [1 : 0] sha256_ctrl_reg; + reg [1 : 0] sha256_ctrl_new; + reg sha256_ctrl_we; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg digest_init; + reg digest_update; + + reg state_init; + reg state_update; + + reg first_block; + + reg ready_flag; + + reg [31 : 0] t1; + reg [31 : 0] t2; + + wire [31 : 0] k_data; + + reg w_init; + reg w_next; + reg [5 : 0] w_round; + wire [31 : 0] w_data; + + + //---------------------------------------------------------------- + // Module instantiantions. + //---------------------------------------------------------------- + sha256_k_constants k_constants_inst( + .round(t_ctr_reg), + .K(k_data) + ); + + + sha256_w_mem w_mem_inst( + .clk(clk), + .reset_n(reset_n), + + .block(block), + .round(t_ctr_reg), + + .init(w_init), + .next(w_next), + .w(w_data) + ); + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign ready = ready_flag; + + assign digest = {H0_reg, H1_reg, H2_reg, H3_reg, + H4_reg, H5_reg, H6_reg, H7_reg}; + + assign digest_valid = digest_valid_reg; + + + //---------------------------------------------------------------- + // reg_update + // Update functionality for all registers in the core. + // All registers are positive edge triggered with asynchronous + // active low reset. All registers have write enable. + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin : reg_update + if (!reset_n) + begin + a_reg <= 32'h0; + b_reg <= 32'h0; + c_reg <= 32'h0; + d_reg <= 32'h0; + e_reg <= 32'h0; + f_reg <= 32'h0; + g_reg <= 32'h0; + h_reg <= 32'h0; + H0_reg <= 32'h0; + H1_reg <= 32'h0; + H2_reg <= 32'h0; + H3_reg <= 32'h0; + H4_reg <= 32'h0; + H5_reg <= 32'h0; + H6_reg <= 32'h0; + H7_reg <= 32'h0; + digest_valid_reg <= 0; + t_ctr_reg <= 6'h0; + sha256_ctrl_reg <= CTRL_IDLE; + end + else + begin + + if (a_h_we) + begin + a_reg <= a_new; + b_reg <= b_new; + c_reg <= c_new; + d_reg <= d_new; + e_reg <= e_new; + f_reg <= f_new; + g_reg <= g_new; + h_reg <= h_new; + end + + if (H_we) + begin + H0_reg <= H0_new; + H1_reg <= H1_new; + H2_reg <= H2_new; + H3_reg <= H3_new; + H4_reg <= H4_new; + H5_reg <= H5_new; + H6_reg <= H6_new; + H7_reg <= H7_new; + end + + if (t_ctr_we) + t_ctr_reg <= t_ctr_new; + + if (digest_valid_we) + digest_valid_reg <= digest_valid_new; + + if (sha256_ctrl_we) + sha256_ctrl_reg <= sha256_ctrl_new; + end + end // reg_update + + + //---------------------------------------------------------------- + // digest_logic + // + // The logic needed to init as well as update the digest. + //---------------------------------------------------------------- + always @* + begin : digest_logic + H0_new = 32'h0; + H1_new = 32'h0; + H2_new = 32'h0; + H3_new = 32'h0; + H4_new = 32'h0; + H5_new = 32'h0; + H6_new = 32'h0; + H7_new = 32'h0; + H_we = 0; + + if (digest_init) + begin + H_we = 1; + if (mode) + begin + H0_new = SHA256_H0_0; + H1_new = SHA256_H0_1; + H2_new = SHA256_H0_2; + H3_new = SHA256_H0_3; + H4_new = SHA256_H0_4; + H5_new = SHA256_H0_5; + H6_new = SHA256_H0_6; + H7_new = SHA256_H0_7; + end + else + begin + H0_new = SHA224_H0_0; + H1_new = SHA224_H0_1; + H2_new = SHA224_H0_2; + H3_new = SHA224_H0_3; + H4_new = SHA224_H0_4; + H5_new = SHA224_H0_5; + H6_new = SHA224_H0_6; + H7_new = SHA224_H0_7; + end + end + + if (digest_update) + begin + H0_new = H0_reg + a_reg; + H1_new = H1_reg + b_reg; + H2_new = H2_reg + c_reg; + H3_new = H3_reg + d_reg; + H4_new = H4_reg + e_reg; + H5_new = H5_reg + f_reg; + H6_new = H6_reg + g_reg; + H7_new = H7_reg + h_reg; + H_we = 1; + end + end // digest_logic + + + //---------------------------------------------------------------- + // t1_logic + // + // The logic for the T1 function. + //---------------------------------------------------------------- + always @* + begin : t1_logic + reg [31 : 0] sum1; + reg [31 : 0] ch; + + sum1 = {e_reg[5 : 0], e_reg[31 : 6]} ^ + {e_reg[10 : 0], e_reg[31 : 11]} ^ + {e_reg[24 : 0], e_reg[31 : 25]}; + + ch = (e_reg & f_reg) ^ ((~e_reg) & g_reg); + + t1 = h_reg + sum1 + ch + w_data + k_data; + end // t1_logic + + + //---------------------------------------------------------------- + // t2_logic + // + // The logic for the T2 function + //---------------------------------------------------------------- + always @* + begin : t2_logic + reg [31 : 0] sum0; + reg [31 : 0] maj; + + sum0 = {a_reg[1 : 0], a_reg[31 : 2]} ^ + {a_reg[12 : 0], a_reg[31 : 13]} ^ + {a_reg[21 : 0], a_reg[31 : 22]}; + + maj = (a_reg & b_reg) ^ (a_reg & c_reg) ^ (b_reg & c_reg); + + t2 = sum0 + maj; + end // t2_logic + + + //---------------------------------------------------------------- + // state_logic + // + // The logic needed to init as well as update the state during + // round processing. + //---------------------------------------------------------------- + always @* + begin : state_logic + a_new = 32'h0; + b_new = 32'h0; + c_new = 32'h0; + d_new = 32'h0; + e_new = 32'h0; + f_new = 32'h0; + g_new = 32'h0; + h_new = 32'h0; + a_h_we = 0; + + if (state_init) + begin + a_h_we = 1; + if (first_block) + begin + if (mode) + begin + a_new = SHA256_H0_0; + b_new = SHA256_H0_1; + c_new = SHA256_H0_2; + d_new = SHA256_H0_3; + e_new = SHA256_H0_4; + f_new = SHA256_H0_5; + g_new = SHA256_H0_6; + h_new = SHA256_H0_7; + end + else + begin + a_new = SHA224_H0_0; + b_new = SHA224_H0_1; + c_new = SHA224_H0_2; + d_new = SHA224_H0_3; + e_new = SHA224_H0_4; + f_new = SHA224_H0_5; + g_new = SHA224_H0_6; + h_new = SHA224_H0_7; + end + end + else + begin + a_new = H0_reg; + b_new = H1_reg; + c_new = H2_reg; + d_new = H3_reg; + e_new = H4_reg; + f_new = H5_reg; + g_new = H6_reg; + h_new = H7_reg; + end + end + + if (state_update) + begin + a_new = t1 + t2; + b_new = a_reg; + c_new = b_reg; + d_new = c_reg; + e_new = d_reg + t1; + f_new = e_reg; + g_new = f_reg; + h_new = g_reg; + a_h_we = 1; + end + end // state_logic + + + //---------------------------------------------------------------- + // t_ctr + // + // Update logic for the round counter, a monotonically + // increasing counter with reset. + //---------------------------------------------------------------- + always @* + begin : t_ctr + t_ctr_new = 0; + t_ctr_we = 0; + + if (t_ctr_rst) + begin + t_ctr_new = 0; + t_ctr_we = 1; + end + + if (t_ctr_inc) + begin + t_ctr_new = t_ctr_reg + 1'b1; + t_ctr_we = 1; + end + end // t_ctr + + + //---------------------------------------------------------------- + // sha256_ctrl_fsm + // + // Logic for the state machine controlling the core behaviour. + //---------------------------------------------------------------- + always @* + begin : sha256_ctrl_fsm + digest_init = 0; + digest_update = 0; + + state_init = 0; + state_update = 0; + + first_block = 0; + ready_flag = 0; + + w_init = 0; + w_next = 0; + + t_ctr_inc = 0; + t_ctr_rst = 0; + + digest_valid_new = 0; + digest_valid_we = 0; + + sha256_ctrl_new = CTRL_IDLE; + sha256_ctrl_we = 0; + + + case (sha256_ctrl_reg) + CTRL_IDLE: + begin + ready_flag = 1; + + if (init) + begin + digest_init = 1; + w_init = 1; + state_init = 1; + first_block = 1; + t_ctr_rst = 1; + digest_valid_new = 0; + digest_valid_we = 1; + sha256_ctrl_new = CTRL_ROUNDS; + sha256_ctrl_we = 1; + end + + if (next) + begin + t_ctr_rst = 1; + w_init = 1; + state_init = 1; + digest_valid_new = 0; + digest_valid_we = 1; + sha256_ctrl_new = CTRL_ROUNDS; + sha256_ctrl_we = 1; + end + end + + + CTRL_ROUNDS: + begin + w_next = 1; + state_update = 1; + t_ctr_inc = 1; + + if (t_ctr_reg == SHA256_ROUNDS) + begin + sha256_ctrl_new = CTRL_DONE; + sha256_ctrl_we = 1; + end + end + + + CTRL_DONE: + begin + digest_update = 1; + digest_valid_new = 1; + digest_valid_we = 1; + + sha256_ctrl_new = CTRL_IDLE; + sha256_ctrl_we = 1; + end + endcase // case (sha256_ctrl_reg) + end // sha256_ctrl_fsm + +endmodule // sha256_core + +`default_nettype wire + +//====================================================================== +// EOF sha256_core.v +//====================================================================== diff --git a/lib/sec/sha256_k_constants.v b/lib/sec/sha256_k_constants.v new file mode 100644 index 0000000..3d52638 --- /dev/null +++ b/lib/sec/sha256_k_constants.v @@ -0,0 +1,136 @@ +//====================================================================== +// +// sha256_k_constants.v +// -------------------- +// The table K with constants in the SHA-256 hash function. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2013, Secworks Sweden AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER 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. +// +//====================================================================== + +`default_nettype none + +module sha256_k_constants( + input wire [5 : 0] round, + output wire [31 : 0] K + ); + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg [31 : 0] tmp_K; + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign K = tmp_K; + + + //---------------------------------------------------------------- + // round_mux + //---------------------------------------------------------------- + always @* + begin : round_mux + case(round) + 00: tmp_K = 32'h428a2f98; + 01: tmp_K = 32'h71374491; + 02: tmp_K = 32'hb5c0fbcf; + 03: tmp_K = 32'he9b5dba5; + 04: tmp_K = 32'h3956c25b; + 05: tmp_K = 32'h59f111f1; + 06: tmp_K = 32'h923f82a4; + 07: tmp_K = 32'hab1c5ed5; + 08: tmp_K = 32'hd807aa98; + 09: tmp_K = 32'h12835b01; + 10: tmp_K = 32'h243185be; + 11: tmp_K = 32'h550c7dc3; + 12: tmp_K = 32'h72be5d74; + 13: tmp_K = 32'h80deb1fe; + 14: tmp_K = 32'h9bdc06a7; + 15: tmp_K = 32'hc19bf174; + 16: tmp_K = 32'he49b69c1; + 17: tmp_K = 32'hefbe4786; + 18: tmp_K = 32'h0fc19dc6; + 19: tmp_K = 32'h240ca1cc; + 20: tmp_K = 32'h2de92c6f; + 21: tmp_K = 32'h4a7484aa; + 22: tmp_K = 32'h5cb0a9dc; + 23: tmp_K = 32'h76f988da; + 24: tmp_K = 32'h983e5152; + 25: tmp_K = 32'ha831c66d; + 26: tmp_K = 32'hb00327c8; + 27: tmp_K = 32'hbf597fc7; + 28: tmp_K = 32'hc6e00bf3; + 29: tmp_K = 32'hd5a79147; + 30: tmp_K = 32'h06ca6351; + 31: tmp_K = 32'h14292967; + 32: tmp_K = 32'h27b70a85; + 33: tmp_K = 32'h2e1b2138; + 34: tmp_K = 32'h4d2c6dfc; + 35: tmp_K = 32'h53380d13; + 36: tmp_K = 32'h650a7354; + 37: tmp_K = 32'h766a0abb; + 38: tmp_K = 32'h81c2c92e; + 39: tmp_K = 32'h92722c85; + 40: tmp_K = 32'ha2bfe8a1; + 41: tmp_K = 32'ha81a664b; + 42: tmp_K = 32'hc24b8b70; + 43: tmp_K = 32'hc76c51a3; + 44: tmp_K = 32'hd192e819; + 45: tmp_K = 32'hd6990624; + 46: tmp_K = 32'hf40e3585; + 47: tmp_K = 32'h106aa070; + 48: tmp_K = 32'h19a4c116; + 49: tmp_K = 32'h1e376c08; + 50: tmp_K = 32'h2748774c; + 51: tmp_K = 32'h34b0bcb5; + 52: tmp_K = 32'h391c0cb3; + 53: tmp_K = 32'h4ed8aa4a; + 54: tmp_K = 32'h5b9cca4f; + 55: tmp_K = 32'h682e6ff3; + 56: tmp_K = 32'h748f82ee; + 57: tmp_K = 32'h78a5636f; + 58: tmp_K = 32'h84c87814; + 59: tmp_K = 32'h8cc70208; + 60: tmp_K = 32'h90befffa; + 61: tmp_K = 32'ha4506ceb; + 62: tmp_K = 32'hbef9a3f7; + 63: tmp_K = 32'hc67178f2; + endcase // case (round) + end // block: round_mux +endmodule // sha256_k_constants + +`default_nettype wire + +//====================================================================== +// sha256_k_constants.v +//====================================================================== diff --git a/lib/sec/sha256_stream.v b/lib/sec/sha256_stream.v new file mode 100644 index 0000000..4cbb6fb --- /dev/null +++ b/lib/sec/sha256_stream.v @@ -0,0 +1,79 @@ +//====================================================================== +// +// sha256_stream.v +// -------- +// Top level wrapper for the SHA-256 hash function providing +// a simple stream interface with 512 bit data access. +// +// +// Author: Olof Kindgren +// Copyright (c) 2016, Olof Kindgren +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER 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. +// +//====================================================================== + +`default_nettype wire + +module sha256_stream + (input clk, + input rst, + input mode, + input [511:0] s_tdata_i, + input s_tlast_i, + input s_tvalid_i, + output s_tready_o, + output [255:0] digest_o, + output digest_valid_o); + + reg first_block; + + always @(posedge clk) begin + if (s_tvalid_i & s_tready_o) + first_block <= s_tlast_i; + + if (rst) begin + first_block <= 1'b1; + end + end + + sha256_core core + (.clk (clk), + .reset_n (~rst), + + .init(s_tvalid_i & first_block), + .next(s_tvalid_i & !first_block), + .mode (mode), + + .block(s_tdata_i), + + .ready(s_tready_o), + + .digest (digest_o), + .digest_valid (digest_valid_o)); + +endmodule diff --git a/lib/sec/sha256_w_mem.v b/lib/sec/sha256_w_mem.v new file mode 100644 index 0000000..3145fe4 --- /dev/null +++ b/lib/sec/sha256_w_mem.v @@ -0,0 +1,242 @@ +//====================================================================== +// +// sha256_w_mem_regs.v +// ------------------- +// The W memory. This version uses 16 32-bit registers as a sliding +// window to generate the 64 words. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2013, Secworks Sweden AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER 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. +// +//====================================================================== + +`default_nettype none + +module sha256_w_mem( + input wire clk, + input wire reset_n, + + input wire [511 : 0] block, + input wire [5 : 0] round, + + input wire init, + input wire next, + output wire [31 : 0] w + ); + + + //---------------------------------------------------------------- + // Registers including update variables and write enable. + //---------------------------------------------------------------- + reg [31 : 0] w_mem [0 : 15]; + reg [31 : 0] w_mem00_new; + reg [31 : 0] w_mem01_new; + reg [31 : 0] w_mem02_new; + reg [31 : 0] w_mem03_new; + reg [31 : 0] w_mem04_new; + reg [31 : 0] w_mem05_new; + reg [31 : 0] w_mem06_new; + reg [31 : 0] w_mem07_new; + reg [31 : 0] w_mem08_new; + reg [31 : 0] w_mem09_new; + reg [31 : 0] w_mem10_new; + reg [31 : 0] w_mem11_new; + reg [31 : 0] w_mem12_new; + reg [31 : 0] w_mem13_new; + reg [31 : 0] w_mem14_new; + reg [31 : 0] w_mem15_new; + reg w_mem_we; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg [31 : 0] w_tmp; + reg [31 : 0] w_new; + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign w = w_tmp; + + + //---------------------------------------------------------------- + // reg_update + // Update functionality for all registers in the core. + // All registers are positive edge triggered with synchronous + // active low reset. All registers have write enable. + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin : reg_update + integer i; + + if (!reset_n) + begin + for (i = 0 ; i < 16 ; i = i + 1) begin + w_mem[i] <= 32'h0; + end + end + else + begin + if (w_mem_we) + begin + w_mem[00] <= w_mem00_new; + w_mem[01] <= w_mem01_new; + w_mem[02] <= w_mem02_new; + w_mem[03] <= w_mem03_new; + w_mem[04] <= w_mem04_new; + w_mem[05] <= w_mem05_new; + w_mem[06] <= w_mem06_new; + w_mem[07] <= w_mem07_new; + w_mem[08] <= w_mem08_new; + w_mem[09] <= w_mem09_new; + w_mem[10] <= w_mem10_new; + w_mem[11] <= w_mem11_new; + w_mem[12] <= w_mem12_new; + w_mem[13] <= w_mem13_new; + w_mem[14] <= w_mem14_new; + w_mem[15] <= w_mem15_new; + end + end + end // reg_update + + + //---------------------------------------------------------------- + // select_w + // + // Mux for the external read operation. This is where we exract + // the W variable. + //---------------------------------------------------------------- + always @* + begin : select_w + if (round < 16) + w_tmp = w_mem[round[3 : 0]]; + else + w_tmp = w_new; + end // select_w + + + //---------------------------------------------------------------- + // w_new_logic + // + // Logic that calculates the next value to be inserted into + // the sliding window of the memory. + //---------------------------------------------------------------- + always @* + begin : w_mem_update_logic + reg [31 : 0] w_0; + reg [31 : 0] w_1; + reg [31 : 0] w_9; + reg [31 : 0] w_14; + reg [31 : 0] d0; + reg [31 : 0] d1; + + w_mem00_new = 32'h0; + w_mem01_new = 32'h0; + w_mem02_new = 32'h0; + w_mem03_new = 32'h0; + w_mem04_new = 32'h0; + w_mem05_new = 32'h0; + w_mem06_new = 32'h0; + w_mem07_new = 32'h0; + w_mem08_new = 32'h0; + w_mem09_new = 32'h0; + w_mem10_new = 32'h0; + w_mem11_new = 32'h0; + w_mem12_new = 32'h0; + w_mem13_new = 32'h0; + w_mem14_new = 32'h0; + w_mem15_new = 32'h0; + w_mem_we = 0; + + w_0 = w_mem[0]; + w_1 = w_mem[1]; + w_9 = w_mem[9]; + w_14 = w_mem[14]; + + d0 = {w_1[6 : 0], w_1[31 : 7]} ^ + {w_1[17 : 0], w_1[31 : 18]} ^ + {3'b000, w_1[31 : 3]}; + + d1 = {w_14[16 : 0], w_14[31 : 17]} ^ + {w_14[18 : 0], w_14[31 : 19]} ^ + {10'b0000000000, w_14[31 : 10]}; + + w_new = d1 + w_9 + d0 + w_0; + + if (init) + begin + w_mem00_new = block[511 : 480]; + w_mem01_new = block[479 : 448]; + w_mem02_new = block[447 : 416]; + w_mem03_new = block[415 : 384]; + w_mem04_new = block[383 : 352]; + w_mem05_new = block[351 : 320]; + w_mem06_new = block[319 : 288]; + w_mem07_new = block[287 : 256]; + w_mem08_new = block[255 : 224]; + w_mem09_new = block[223 : 192]; + w_mem10_new = block[191 : 160]; + w_mem11_new = block[159 : 128]; + w_mem12_new = block[127 : 96]; + w_mem13_new = block[95 : 64]; + w_mem14_new = block[63 : 32]; + w_mem15_new = block[31 : 0]; + w_mem_we = 1; + end + + if (next && (round > 15)) + begin + w_mem00_new = w_mem[01]; + w_mem01_new = w_mem[02]; + w_mem02_new = w_mem[03]; + w_mem03_new = w_mem[04]; + w_mem04_new = w_mem[05]; + w_mem05_new = w_mem[06]; + w_mem06_new = w_mem[07]; + w_mem07_new = w_mem[08]; + w_mem08_new = w_mem[09]; + w_mem09_new = w_mem[10]; + w_mem10_new = w_mem[11]; + w_mem11_new = w_mem[12]; + w_mem12_new = w_mem[13]; + w_mem13_new = w_mem[14]; + w_mem14_new = w_mem[15]; + w_mem15_new = w_new; + w_mem_we = 1; + end + end // w_mem_update_logic +endmodule // sha256_w_mem + +`default_nettype wire +//====================================================================== +// sha256_w_mem.v +//======================================================================